Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 : #include <string>
51 :
52 : // ObjexxFCL Headers
53 : #include <ObjexxFCL/Array.functions.hh>
54 : #include <ObjexxFCL/Fmath.hh>
55 :
56 : // EnergyPlus Headers
57 : #include <EnergyPlus/Autosizing/Base.hh>
58 : #include <EnergyPlus/BranchNodeConnections.hh>
59 : #include <EnergyPlus/CurveManager.hh>
60 : #include <EnergyPlus/Data/EnergyPlusData.hh>
61 : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
62 : #include <EnergyPlus/DataHVACGlobals.hh>
63 : #include <EnergyPlus/DataIPShortCuts.hh>
64 : #include <EnergyPlus/DataLoopNode.hh>
65 : #include <EnergyPlus/DataSizing.hh>
66 : #include <EnergyPlus/EMSManager.hh>
67 : #include <EnergyPlus/FluidProperties.hh>
68 : #include <EnergyPlus/General.hh>
69 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
70 : #include <EnergyPlus/NodeInputManager.hh>
71 : #include <EnergyPlus/OutputProcessor.hh>
72 : #include <EnergyPlus/OutputReportPredefined.hh>
73 : #include <EnergyPlus/Plant/DataPlant.hh>
74 : #include <EnergyPlus/Plant/PlantLocation.hh>
75 : #include <EnergyPlus/PlantCentralGSHP.hh>
76 : #include <EnergyPlus/PlantUtilities.hh>
77 : #include <EnergyPlus/ScheduleManager.hh>
78 : #include <EnergyPlus/UtilityRoutines.hh>
79 :
80 : namespace EnergyPlus::PlantCentralGSHP {
81 :
82 : // MODULE INFORMATION:
83 : // AUTHOR PNNL
84 : // DATE WRITTEN Feb 2013
85 : // MODIFIED na
86 : // RE-ENGINEERED na
87 : // PURPOSE OF THIS MODULE:
88 : // This module simulates the performance of the Central Plant GSHP systems
89 : // It currently includes one object: ChillerHeaterPerformance:Electric:EIR.
90 : // The other object available for this central CGSHP system such as HeatPumpPerformance:WaterToWater:EIR
91 : // will be implemented later.
92 :
93 : // METHODOLOGY EMPLOYED:
94 : // Once the PlantLoopManager determines that the Central Plant GSHP
95 : // is available to meet a loop cooling and heating demands, it calls simulate
96 : // which in turn calls the electric PlantCentralGSHP model. The PlantCentralGSHP model is based on
97 : // polynomial fits of chiller/heater or heat pump performance data.
98 :
99 0 : PlantComponent *WrapperSpecs::factory(EnergyPlusData &state, std::string const &objectName)
100 : {
101 : // Process the input data
102 0 : if (state.dataPlantCentralGSHP->getWrapperInputFlag) {
103 0 : GetWrapperInput(state);
104 0 : state.dataPlantCentralGSHP->getWrapperInputFlag = false;
105 : }
106 :
107 : // Now look for this particular object
108 0 : for (auto &thisWrapper : state.dataPlantCentralGSHP->Wrapper) {
109 0 : if (thisWrapper.Name == objectName) {
110 0 : return &thisWrapper;
111 : }
112 0 : }
113 : // If we didn't find it, fatal
114 : ShowFatalError(state, format("LocalPlantCentralGSHPFactory: Error getting inputs for object named: {}", objectName)); // LCOV_EXCL_LINE
115 : // Shut up the compiler
116 : return nullptr; // LCOV_EXCL_LINE
117 : }
118 :
119 0 : void WrapperSpecs::onInitLoopEquip(EnergyPlusData &state, const PlantLocation &calledFromLocation)
120 : {
121 0 : this->initialize(state, 0.0, calledFromLocation.loopNum);
122 0 : this->SizeWrapper(state);
123 0 : }
124 :
125 0 : void WrapperSpecs::getDesignCapacities(
126 : [[maybe_unused]] EnergyPlusData &state, const PlantLocation &calledFromLocation, Real64 &MaxLoad, Real64 &MinLoad, Real64 &OptLoad)
127 : {
128 0 : MinLoad = 0.0;
129 0 : MaxLoad = 0.0;
130 0 : OptLoad = 0.0;
131 0 : if (calledFromLocation.loopNum == this->CWPlantLoc.loopNum) { // Chilled water loop
132 0 : if (this->ControlMode == CondenserType::SmartMixing) { // control mode is SmartMixing
133 0 : for (int NumChillerHeater = 1; NumChillerHeater <= this->ChillerHeaterNums; ++NumChillerHeater) {
134 0 : MaxLoad += this->ChillerHeater(NumChillerHeater).RefCapCooling * this->ChillerHeater(NumChillerHeater).MaxPartLoadRatCooling;
135 0 : OptLoad += this->ChillerHeater(NumChillerHeater).RefCapCooling * this->ChillerHeater(NumChillerHeater).OptPartLoadRatCooling;
136 0 : MinLoad += this->ChillerHeater(NumChillerHeater).RefCapCooling * this->ChillerHeater(NumChillerHeater).MinPartLoadRatCooling;
137 : }
138 : }
139 0 : } else if (calledFromLocation.loopNum == this->HWPlantLoc.loopNum) { // Hot water loop
140 0 : if (this->ControlMode == CondenserType::SmartMixing) { // control mode is SmartMixing
141 0 : for (int NumChillerHeater = 1; NumChillerHeater <= this->ChillerHeaterNums; ++NumChillerHeater) {
142 0 : MaxLoad += this->ChillerHeater(NumChillerHeater).RefCapClgHtg * this->ChillerHeater(NumChillerHeater).MaxPartLoadRatClgHtg;
143 0 : OptLoad += this->ChillerHeater(NumChillerHeater).RefCapClgHtg * this->ChillerHeater(NumChillerHeater).OptPartLoadRatClgHtg;
144 0 : MinLoad += this->ChillerHeater(NumChillerHeater).RefCapClgHtg * this->ChillerHeater(NumChillerHeater).MinPartLoadRatClgHtg;
145 : }
146 : } // End of control mode determination
147 : }
148 0 : }
149 :
150 0 : void WrapperSpecs::getSizingFactor(Real64 &SizFac)
151 : {
152 0 : SizFac = 1.0;
153 0 : }
154 :
155 0 : void WrapperSpecs::simulate(
156 : EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, [[maybe_unused]] bool RunFlag)
157 : {
158 0 : if (calledFromLocation.loopNum != this->GLHEPlantLoc.loopNum) {
159 :
160 0 : this->initialize(state, CurLoad, calledFromLocation.loopNum);
161 0 : this->CalcWrapperModel(state, CurLoad, calledFromLocation.loopNum);
162 :
163 0 : } else if (calledFromLocation.loopNum == this->GLHEPlantLoc.loopNum) {
164 0 : PlantUtilities::UpdateChillerComponentCondenserSide(state,
165 0 : calledFromLocation.loopNum,
166 : this->GLHEPlantLoc.loopSideNum,
167 : DataPlant::PlantEquipmentType::CentralGroundSourceHeatPump,
168 : this->GLHEInletNodeNum,
169 : this->GLHEOutletNodeNum,
170 : this->Report.GLHERate,
171 : this->Report.GLHEInletTemp,
172 : this->Report.GLHEOutletTemp,
173 : this->Report.GLHEmdot,
174 : FirstHVACIteration);
175 :
176 : // Use the first chiller heater's evaporator capacity ratio to determine dominant load
177 0 : this->SimulClgDominant = false;
178 0 : this->SimulHtgDominant = false;
179 0 : if (this->WrapperCoolingLoad > 0 && this->WrapperHeatingLoad > 0) {
180 0 : Real64 SimulLoadRatio = this->WrapperCoolingLoad / this->WrapperHeatingLoad;
181 0 : if (SimulLoadRatio > this->ChillerHeater(1).ClgHtgToCoolingCapRatio) {
182 0 : this->SimulClgDominant = true;
183 0 : this->SimulHtgDominant = false;
184 : } else {
185 0 : this->SimulHtgDominant = true;
186 0 : this->SimulClgDominant = false;
187 : }
188 : }
189 : }
190 0 : }
191 :
192 1 : void WrapperSpecs::SizeWrapper(EnergyPlusData &state)
193 : {
194 : // SUBROUTINE INFORMATION:
195 : // AUTHOR Yunzhi Huang, PNNL
196 : // DATE WRITTEN Feb 2013
197 : // MODIFIED November 2013 Daeho Kang, add component sizing table entries
198 : // RE-ENGINEERED na
199 :
200 : // PURPOSE OF THIS SUBROUTINE:
201 : // This subroutine is for sizing all the components under each 'CentralHeatPumpSystem' object,
202 : // for which capacities and flow rates have not been specified in the input.
203 :
204 : // METHODOLOGY EMPLOYED:
205 : // Obtains evaporator flow rate from the plant sizing array. Calculates reference capacity from
206 : // the evaporator (or load side) flow rate and the chilled water loop design delta T. The condenser
207 : // flow (or source side) rate is calculated from the reference capacity, the COP, and the condenser
208 : // loop design delta T.
209 :
210 : static constexpr std::string_view RoutineName("SizeCGSHPChillerHeater");
211 :
212 : // auto-size the chiller heater components
213 1 : if (this->ControlMode == CondenserType::SmartMixing) {
214 :
215 3 : for (int NumChillerHeater = 1; NumChillerHeater <= this->ChillerHeaterNums; ++NumChillerHeater) {
216 2 : bool ErrorsFound = false;
217 :
218 : // find the appropriate Plant Sizing object
219 2 : int PltSizNum = this->CWPlantLoc.loop->PlantSizNum;
220 :
221 : // if ( Wrapper( WrapperNum ).ChillerHeater( NumChillerHeater ).CondVolFlowRate == AutoSize ) {
222 2 : int PltSizCondNum = this->GLHEPlantLoc.loop->PlantSizNum;
223 : //}
224 :
225 2 : Real64 tmpNomCap = this->ChillerHeater(NumChillerHeater).RefCapCooling;
226 2 : Real64 tmpEvapVolFlowRate = this->ChillerHeater(NumChillerHeater).EvapVolFlowRate;
227 2 : Real64 tmpCondVolFlowRate = this->ChillerHeater(NumChillerHeater).CondVolFlowRate;
228 :
229 : // auto-size the Evaporator Flow Rate
230 2 : if (PltSizNum > 0) {
231 2 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
232 2 : tmpEvapVolFlowRate = state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate * this->ChillerHeater(NumChillerHeater).SizFac;
233 2 : this->ChillerHeater(NumChillerHeater).tmpEvapVolFlowRate = tmpEvapVolFlowRate;
234 2 : if (!this->ChillerHeater(NumChillerHeater).EvapVolFlowRateWasAutoSized) {
235 0 : tmpEvapVolFlowRate = this->ChillerHeater(NumChillerHeater).EvapVolFlowRate;
236 : }
237 :
238 : } else {
239 0 : if (this->ChillerHeater(NumChillerHeater).EvapVolFlowRateWasAutoSized) {
240 0 : tmpEvapVolFlowRate = 0.0;
241 : }
242 0 : this->ChillerHeater(NumChillerHeater).tmpEvapVolFlowRate = tmpEvapVolFlowRate;
243 : }
244 2 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
245 2 : if (this->ChillerHeater(NumChillerHeater).EvapVolFlowRateWasAutoSized) {
246 2 : this->ChillerHeater(NumChillerHeater).EvapVolFlowRate = tmpEvapVolFlowRate;
247 2 : if (state.dataPlnt->PlantFinalSizesOkayToReport && !this->mySizesReported) {
248 0 : BaseSizer::reportSizerOutput(state,
249 : "ChillerHeaterPerformance:Electric:EIR",
250 0 : this->ChillerHeater(NumChillerHeater).Name,
251 : "Design Size Reference Chilled Water Flow Rate [m3/s]",
252 : tmpEvapVolFlowRate);
253 : }
254 2 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
255 0 : BaseSizer::reportSizerOutput(state,
256 : "ChillerHeaterPerformance:Electric:EIR",
257 0 : this->ChillerHeater(NumChillerHeater).Name,
258 : "Initial Design Size Reference Chilled Water Flow Rate [m3/s]",
259 : tmpEvapVolFlowRate);
260 : }
261 : } else {
262 0 : if (this->ChillerHeater(NumChillerHeater).EvapVolFlowRate > 0.0 && tmpEvapVolFlowRate > 0.0 &&
263 0 : state.dataPlnt->PlantFinalSizesOkayToReport && !this->mySizesReported) {
264 :
265 : // Hardsized evaporator design volume flow rate for reporting
266 0 : Real64 EvapVolFlowRateUser = this->ChillerHeater(NumChillerHeater).EvapVolFlowRate;
267 0 : BaseSizer::reportSizerOutput(state,
268 : "ChillerHeaterPerformance:Electric:EIR",
269 0 : this->ChillerHeater(NumChillerHeater).Name,
270 : "Design Size Reference Chilled Water Flow Rate [m3/s]",
271 : tmpEvapVolFlowRate,
272 : "User-Specified Reference Chilled Water Flow Rate [m3/s]",
273 : EvapVolFlowRateUser);
274 0 : tmpEvapVolFlowRate = EvapVolFlowRateUser;
275 0 : if (state.dataGlobal->DisplayExtraWarnings) {
276 0 : if ((std::abs(tmpEvapVolFlowRate - EvapVolFlowRateUser) / EvapVolFlowRateUser) >
277 0 : state.dataSize->AutoVsHardSizingThreshold) {
278 0 : ShowMessage(state,
279 0 : format("SizeChillerHeaterPerformanceElectricEIR: Potential issue with equipment sizing for {}",
280 0 : this->ChillerHeater(NumChillerHeater).Name));
281 0 : ShowContinueError(
282 0 : state, format("User-Specified Reference Chilled Water Flow Rate of {:.5R} [m3/s]", EvapVolFlowRateUser));
283 0 : ShowContinueError(
284 : state,
285 0 : format("differs from Design Size Reference Chilled Water Flow Rate of {:.5R} [m3/s]", tmpEvapVolFlowRate));
286 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
287 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
288 : }
289 : }
290 : }
291 : }
292 : }
293 : } else {
294 0 : if (this->ChillerHeater(NumChillerHeater).EvapVolFlowRateWasAutoSized) {
295 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
296 0 : ShowSevereError(state, "Autosizing of CGSHP Chiller Heater evap flow rate requires a loop Sizing:Plant object");
297 0 : ShowContinueError(state,
298 0 : format("Occurs in CGSHP Chiller Heater Performance object={}", this->ChillerHeater(NumChillerHeater).Name));
299 0 : ErrorsFound = true;
300 : }
301 : } else {
302 0 : if (this->ChillerHeater(NumChillerHeater).EvapVolFlowRate > 0.0 && state.dataPlnt->PlantFinalSizesOkayToReport &&
303 0 : !this->mySizesReported) {
304 0 : BaseSizer::reportSizerOutput(state,
305 : "ChillerHeaterPerformance:Electric:EIR",
306 0 : this->ChillerHeater(NumChillerHeater).Name,
307 : "User-Specified Reference Chilled Water Flow Rate [m3/s]",
308 0 : this->ChillerHeater(NumChillerHeater).EvapVolFlowRate);
309 : }
310 : }
311 : }
312 :
313 : // auto-size the Reference Cooling Capacity
314 : // each individual chiller heater module is sized to be capable of supporting the total load on the wrapper
315 2 : if (PltSizNum > 0) {
316 2 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow && tmpEvapVolFlowRate > 0.0) {
317 2 : Real64 Cp = this->CWPlantLoc.loop->glycol->getSpecificHeat(state, Constant::CWInitConvTemp, RoutineName);
318 :
319 2 : Real64 rho = this->CWPlantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
320 2 : tmpNomCap = Cp * rho * state.dataSize->PlantSizData(PltSizNum).DeltaT * tmpEvapVolFlowRate;
321 2 : if (!this->ChillerHeater(NumChillerHeater).RefCapCoolingWasAutoSized) {
322 0 : tmpNomCap = this->ChillerHeater(NumChillerHeater).RefCapCooling;
323 : }
324 : } else {
325 0 : if (this->ChillerHeater(NumChillerHeater).RefCapCoolingWasAutoSized) {
326 0 : tmpNomCap = 0.0;
327 : }
328 : }
329 2 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
330 2 : if (this->ChillerHeater(NumChillerHeater).RefCapCoolingWasAutoSized) {
331 2 : this->ChillerHeater(NumChillerHeater).RefCapCooling = tmpNomCap;
332 :
333 : // Now that we have the Reference Cooling Capacity, we need to also initialize the Heating side
334 : // given the ratios
335 4 : this->ChillerHeater(NumChillerHeater).RefCapClgHtg =
336 2 : this->ChillerHeater(NumChillerHeater).RefCapCooling * this->ChillerHeater(NumChillerHeater).ClgHtgToCoolingCapRatio;
337 :
338 4 : this->ChillerHeater(NumChillerHeater).RefPowerClgHtg =
339 2 : (this->ChillerHeater(NumChillerHeater).RefCapCooling / this->ChillerHeater(NumChillerHeater).RefCOPCooling) *
340 2 : this->ChillerHeater(NumChillerHeater).ClgHtgtoCogPowerRatio;
341 :
342 4 : this->ChillerHeater(NumChillerHeater).RefCOPClgHtg =
343 2 : this->ChillerHeater(NumChillerHeater).RefCapClgHtg / this->ChillerHeater(NumChillerHeater).RefPowerClgHtg;
344 :
345 2 : if (state.dataPlnt->PlantFinalSizesOkayToReport && !this->mySizesReported) {
346 0 : BaseSizer::reportSizerOutput(state,
347 : "ChillerHeaterPerformance:Electric:EIR",
348 0 : this->ChillerHeater(NumChillerHeater).Name,
349 : "Design Size Reference Capacity [W]",
350 : tmpNomCap);
351 : }
352 2 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
353 0 : BaseSizer::reportSizerOutput(state,
354 : "ChillerHeaterPerformance:Electric:EIR",
355 0 : this->ChillerHeater(NumChillerHeater).Name,
356 : "Initial Design Size Reference Capacity [W]",
357 : tmpNomCap);
358 : }
359 : } else {
360 0 : if (this->ChillerHeater(NumChillerHeater).RefCapCooling > 0.0 && tmpNomCap > 0.0 &&
361 0 : state.dataPlnt->PlantFinalSizesOkayToReport && !this->mySizesReported) {
362 :
363 : // Hardsized nominal capacity cooling power for reporting
364 0 : Real64 NomCapUser = this->ChillerHeater(NumChillerHeater).RefCapCooling;
365 0 : BaseSizer::reportSizerOutput(state,
366 : "ChillerHeaterPerformance:Electric:EIR",
367 0 : this->ChillerHeater(NumChillerHeater).Name,
368 : "Design Size Reference Capacity [W]",
369 : tmpNomCap,
370 : "User-Specified Reference Capacity [W]",
371 : NomCapUser);
372 0 : tmpNomCap = NomCapUser;
373 0 : if (state.dataGlobal->DisplayExtraWarnings) {
374 0 : if ((std::abs(tmpNomCap - NomCapUser) / NomCapUser) > state.dataSize->AutoVsHardSizingThreshold) {
375 0 : ShowMessage(state,
376 0 : format("SizeChillerHeaterPerformanceElectricEIR: Potential issue with equipment sizing for {}",
377 0 : this->ChillerHeater(NumChillerHeater).Name));
378 0 : ShowContinueError(state, format("User-Specified Reference Capacity of {:.2R} [W]", NomCapUser));
379 0 : ShowContinueError(state, format("differs from Design Size Reference Capacity of {:.2R} [W]", tmpNomCap));
380 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
381 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
382 : }
383 : }
384 : }
385 : }
386 : }
387 : } else {
388 0 : if (this->ChillerHeater(NumChillerHeater).RefCapCoolingWasAutoSized) {
389 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
390 0 : ShowSevereError(
391 : state,
392 0 : format("Size ChillerHeaterPerformance:Electric:EIR=\"{}\", autosize error.", this->ChillerHeater(NumChillerHeater).Name));
393 0 : ShowContinueError(state, "Autosizing of CGSHP Chiller Heater reference capacity requires");
394 0 : ShowContinueError(state, "a cooling loop Sizing:Plant object.");
395 0 : ErrorsFound = true;
396 : }
397 : } else {
398 0 : if (this->ChillerHeater(NumChillerHeater).RefCapCooling > 0.0 && state.dataPlnt->PlantFinalSizesOkayToReport &&
399 0 : !this->mySizesReported) {
400 0 : BaseSizer::reportSizerOutput(state,
401 : "ChillerHeaterPerformance:Electric:EIR",
402 0 : this->ChillerHeater(NumChillerHeater).Name,
403 : "User-Specified Reference Capacity [W]",
404 0 : this->ChillerHeater(NumChillerHeater).RefCapCooling);
405 : }
406 : }
407 : }
408 :
409 : // auto-size the condenser volume flow rate
410 : // each individual chiller heater module is sized to be capable of supporting the total load on the wrapper
411 2 : if (PltSizCondNum > 0) {
412 2 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
413 2 : Real64 rho = this->GLHEPlantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
414 : // TODO: JM 2018-12-06 I wonder why Cp isn't calculated at the same temp as rho...
415 6 : Real64 Cp = this->GLHEPlantLoc.loop->glycol->getSpecificHeat(
416 2 : state, this->ChillerHeater(NumChillerHeater).TempRefCondInCooling, RoutineName);
417 2 : tmpCondVolFlowRate =
418 2 : tmpNomCap *
419 2 : (1.0 + (1.0 / this->ChillerHeater(NumChillerHeater).RefCOPCooling) * this->ChillerHeater(NumChillerHeater).OpenMotorEff) /
420 2 : (state.dataSize->PlantSizData(PltSizCondNum).DeltaT * Cp * rho);
421 2 : this->ChillerHeater(NumChillerHeater).tmpCondVolFlowRate = tmpCondVolFlowRate;
422 2 : if (!this->ChillerHeater(NumChillerHeater).CondVolFlowRateWasAutoSized) {
423 0 : tmpCondVolFlowRate = this->ChillerHeater(NumChillerHeater).CondVolFlowRate;
424 : }
425 :
426 : } else {
427 0 : if (this->ChillerHeater(NumChillerHeater).CondVolFlowRateWasAutoSized) {
428 0 : tmpCondVolFlowRate = 0.0;
429 : }
430 0 : this->ChillerHeater(NumChillerHeater).tmpCondVolFlowRate = tmpCondVolFlowRate;
431 : }
432 2 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
433 2 : if (this->ChillerHeater(NumChillerHeater).CondVolFlowRateWasAutoSized) {
434 2 : this->ChillerHeater(NumChillerHeater).CondVolFlowRate = tmpCondVolFlowRate;
435 2 : if (state.dataPlnt->PlantFinalSizesOkayToReport && !this->mySizesReported) {
436 0 : BaseSizer::reportSizerOutput(state,
437 : "ChillerHeaterPerformance:Electric:EIR",
438 0 : this->ChillerHeater(NumChillerHeater).Name,
439 : "Design Size Reference Condenser Water Flow Rate [m3/s]",
440 : tmpCondVolFlowRate);
441 : }
442 2 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
443 0 : BaseSizer::reportSizerOutput(state,
444 : "ChillerHeaterPerformance:Electric:EIR",
445 0 : this->ChillerHeater(NumChillerHeater).Name,
446 : "Initial Design Size Reference Condenser Water Flow Rate [m3/s]",
447 : tmpCondVolFlowRate);
448 : }
449 : } else {
450 0 : if (this->ChillerHeater(NumChillerHeater).CondVolFlowRate > 0.0 && tmpCondVolFlowRate > 0.0 &&
451 0 : state.dataPlnt->PlantFinalSizesOkayToReport && !this->mySizesReported) {
452 :
453 : // Hardsized condenser design volume flow rate for reporting
454 0 : Real64 CondVolFlowRateUser = this->ChillerHeater(NumChillerHeater).CondVolFlowRate;
455 0 : BaseSizer::reportSizerOutput(state,
456 : "ChillerHeaterPerformance:Electric:EIR",
457 0 : this->ChillerHeater(NumChillerHeater).Name,
458 : "Design Size Reference Condenser Water Flow Rate [m3/s]",
459 : tmpCondVolFlowRate,
460 : "User-Specified Reference Condenser Water Flow Rate [m3/s]",
461 : CondVolFlowRateUser);
462 0 : if (state.dataGlobal->DisplayExtraWarnings) {
463 0 : if ((std::abs(tmpCondVolFlowRate - CondVolFlowRateUser) / CondVolFlowRateUser) >
464 0 : state.dataSize->AutoVsHardSizingThreshold) {
465 0 : ShowMessage(state,
466 0 : format("SizeChillerHeaterPerformanceElectricEIR: Potential issue with equipment sizing for {}",
467 0 : this->ChillerHeater(NumChillerHeater).Name));
468 0 : ShowContinueError(
469 0 : state, format("User-Specified Reference Condenser Water Flow Rate of {:.5R} [m3/s]", CondVolFlowRateUser));
470 0 : ShowContinueError(
471 : state,
472 0 : format("differs from Design Size Reference Condenser Water Flow Rate of {:.5R} [m3/s]", tmpCondVolFlowRate));
473 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
474 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
475 : }
476 : }
477 : }
478 : }
479 : }
480 : } else {
481 0 : if (this->ChillerHeater(NumChillerHeater).CondVolFlowRateWasAutoSized) {
482 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
483 0 : ShowSevereError(
484 : state,
485 0 : format("Size ChillerHeaterPerformance:Electric:EIR=\"{}\", autosize error.", this->ChillerHeater(NumChillerHeater).Name));
486 0 : ShowContinueError(state, "Autosizing of CGSHP Chiller Heater condenser flow rate requires");
487 0 : ShowContinueError(state, "a condenser loop Sizing:Plant object.");
488 0 : ErrorsFound = true;
489 : }
490 : } else {
491 0 : if (this->ChillerHeater(NumChillerHeater).CondVolFlowRate > 0.0 && state.dataPlnt->PlantFinalSizesOkayToReport &&
492 0 : !this->mySizesReported) {
493 0 : BaseSizer::reportSizerOutput(state,
494 : "ChillerHeaterPerformance:Electric:EIR",
495 0 : this->ChillerHeater(NumChillerHeater).Name,
496 : "User-Specified Reference Condenser Water Flow Rate [m3/s]",
497 0 : this->ChillerHeater(NumChillerHeater).CondVolFlowRate);
498 : }
499 : }
500 : }
501 :
502 2 : if (state.dataPlnt->PlantFinalSizesOkayToReport && !this->mySizesReported) {
503 : // create predefined report
504 0 : std::string equipName = this->ChillerHeater(NumChillerHeater).Name;
505 0 : OutputReportPredefined::PreDefTableEntry(
506 0 : state, state.dataOutRptPredefined->pdchMechType, equipName, "ChillerHeaterPerformance:Electric:EIR");
507 0 : OutputReportPredefined::PreDefTableEntry(
508 0 : state, state.dataOutRptPredefined->pdchMechNomEff, equipName, this->ChillerHeater(NumChillerHeater).RefCOPCooling);
509 0 : OutputReportPredefined::PreDefTableEntry(
510 0 : state, state.dataOutRptPredefined->pdchMechNomCap, equipName, this->ChillerHeater(NumChillerHeater).RefCapCooling);
511 0 : }
512 :
513 2 : if (ErrorsFound) {
514 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
515 : }
516 : }
517 :
518 : // sum individual volume flows and register wrapper inlets
519 1 : Real64 TotalEvapVolFlowRate = 0.0;
520 1 : Real64 TotalCondVolFlowRate = 0.0;
521 1 : Real64 TotalHotWaterVolFlowRate = 0.0;
522 3 : for (int NumChillerHeater = 1; NumChillerHeater <= this->ChillerHeaterNums; ++NumChillerHeater) {
523 2 : TotalEvapVolFlowRate += this->ChillerHeater(NumChillerHeater).tmpEvapVolFlowRate;
524 2 : TotalCondVolFlowRate += this->ChillerHeater(NumChillerHeater).tmpCondVolFlowRate;
525 2 : TotalHotWaterVolFlowRate += this->ChillerHeater(NumChillerHeater).DesignHotWaterVolFlowRate;
526 : }
527 :
528 1 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->CHWInletNodeNum, TotalEvapVolFlowRate);
529 1 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->HWInletNodeNum, TotalHotWaterVolFlowRate);
530 : // save the reference condenser water volumetric flow rate for use by the condenser water loop sizing algorithms
531 1 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->GLHEInletNodeNum, TotalCondVolFlowRate);
532 :
533 1 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
534 0 : this->mySizesReported = true;
535 : }
536 :
537 1 : return;
538 : }
539 : }
540 :
541 1 : void GetWrapperInput(EnergyPlusData &state)
542 : {
543 : // SUBROUTINE INFORMATION:
544 : // AUTHOR: Yunzhi Huang and Daeho Kang, PNNL
545 : // DATE WRITTEN: Feb 2013
546 :
547 : // PURPOSE OF THIS SUBROUTINE:
548 : // This routine will get the input required by the Wrapper model.
549 :
550 : static constexpr std::string_view routineName = "GetWrapperInput";
551 :
552 1 : bool ErrorsFound(false); // True when input errors are found
553 : int NumAlphas; // Number of elements in the alpha array
554 : int NumNums; // Number of elements in the numeric array
555 : int IOStat; // IO Status when calling get input subroutine
556 :
557 1 : state.dataIPShortCut->cCurrentModuleObject = "CentralHeatPumpSystem";
558 2 : state.dataPlantCentralGSHP->numWrappers =
559 1 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
560 :
561 1 : if (state.dataPlantCentralGSHP->numWrappers <= 0) {
562 0 : ShowSevereError(state, format("No {} equipment specified in input file", state.dataIPShortCut->cCurrentModuleObject));
563 : }
564 :
565 1 : state.dataPlantCentralGSHP->Wrapper.allocate(state.dataPlantCentralGSHP->numWrappers);
566 :
567 : // Load arrays with electric EIR chiller data
568 2 : for (int WrapperNum = 1; WrapperNum <= state.dataPlantCentralGSHP->numWrappers; ++WrapperNum) {
569 3 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
570 1 : state.dataIPShortCut->cCurrentModuleObject,
571 : WrapperNum,
572 1 : state.dataIPShortCut->cAlphaArgs,
573 : NumAlphas,
574 1 : state.dataIPShortCut->rNumericArgs,
575 : NumNums,
576 : IOStat,
577 : _,
578 1 : state.dataIPShortCut->lAlphaFieldBlanks,
579 1 : state.dataIPShortCut->cAlphaFieldNames,
580 1 : state.dataIPShortCut->cNumericFieldNames);
581 :
582 1 : ErrorObjectHeader eoh{routineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
583 :
584 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).Name = state.dataIPShortCut->cAlphaArgs(1);
585 :
586 : // initialize nth chiller heater index (including identical units) for current wrapper
587 1 : if (Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound)) {
588 0 : continue;
589 : }
590 :
591 1 : if (state.dataIPShortCut->cAlphaArgs(2) == "SMARTMIXING") {
592 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).ControlMode = CondenserType::SmartMixing;
593 : }
594 :
595 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).CHWInletNodeNum =
596 2 : NodeInputManager::GetOnlySingleNode(state,
597 1 : state.dataIPShortCut->cAlphaArgs(3),
598 : ErrorsFound,
599 : DataLoopNode::ConnectionObjectType::CentralHeatPumpSystem,
600 1 : state.dataIPShortCut->cAlphaArgs(1),
601 : DataLoopNode::NodeFluidType::Water,
602 : DataLoopNode::ConnectionType::Inlet,
603 : NodeInputManager::CompFluidStream::Primary,
604 : DataLoopNode::ObjectIsNotParent); // node name : connection should be careful!
605 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).CHWOutletNodeNum =
606 3 : NodeInputManager::GetOnlySingleNode(state,
607 1 : state.dataIPShortCut->cAlphaArgs(4),
608 : ErrorsFound,
609 : DataLoopNode::ConnectionObjectType::CentralHeatPumpSystem,
610 1 : state.dataIPShortCut->cAlphaArgs(1),
611 : DataLoopNode::NodeFluidType::Water,
612 : DataLoopNode::ConnectionType::Outlet,
613 : NodeInputManager::CompFluidStream::Primary,
614 : DataLoopNode::ObjectIsNotParent);
615 2 : BranchNodeConnections::TestCompSet(state,
616 1 : state.dataIPShortCut->cCurrentModuleObject,
617 1 : state.dataIPShortCut->cAlphaArgs(1),
618 1 : state.dataIPShortCut->cAlphaArgs(3),
619 1 : state.dataIPShortCut->cAlphaArgs(4),
620 : "Chilled Water Nodes");
621 :
622 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).GLHEInletNodeNum =
623 2 : NodeInputManager::GetOnlySingleNode(state,
624 1 : state.dataIPShortCut->cAlphaArgs(5),
625 : ErrorsFound,
626 : DataLoopNode::ConnectionObjectType::CentralHeatPumpSystem,
627 1 : state.dataIPShortCut->cAlphaArgs(1),
628 : DataLoopNode::NodeFluidType::Water,
629 : DataLoopNode::ConnectionType::Inlet,
630 : NodeInputManager::CompFluidStream::Secondary,
631 : DataLoopNode::ObjectIsNotParent); // node name : connection should be careful!
632 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).GLHEOutletNodeNum =
633 3 : NodeInputManager::GetOnlySingleNode(state,
634 1 : state.dataIPShortCut->cAlphaArgs(6),
635 : ErrorsFound,
636 : DataLoopNode::ConnectionObjectType::CentralHeatPumpSystem,
637 1 : state.dataIPShortCut->cAlphaArgs(1),
638 : DataLoopNode::NodeFluidType::Water,
639 : DataLoopNode::ConnectionType::Outlet,
640 : NodeInputManager::CompFluidStream::Secondary,
641 : DataLoopNode::ObjectIsNotParent);
642 2 : BranchNodeConnections::TestCompSet(state,
643 1 : state.dataIPShortCut->cCurrentModuleObject,
644 1 : state.dataIPShortCut->cAlphaArgs(1),
645 1 : state.dataIPShortCut->cAlphaArgs(5),
646 1 : state.dataIPShortCut->cAlphaArgs(6),
647 : "GLHE Nodes");
648 :
649 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).HWInletNodeNum =
650 2 : NodeInputManager::GetOnlySingleNode(state,
651 1 : state.dataIPShortCut->cAlphaArgs(7),
652 : ErrorsFound,
653 : DataLoopNode::ConnectionObjectType::CentralHeatPumpSystem,
654 1 : state.dataIPShortCut->cAlphaArgs(1),
655 : DataLoopNode::NodeFluidType::Water,
656 : DataLoopNode::ConnectionType::Inlet,
657 : NodeInputManager::CompFluidStream::Tertiary,
658 : DataLoopNode::ObjectIsNotParent); // node name : connection should be careful!
659 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).HWOutletNodeNum =
660 3 : NodeInputManager::GetOnlySingleNode(state,
661 1 : state.dataIPShortCut->cAlphaArgs(8),
662 : ErrorsFound,
663 : DataLoopNode::ConnectionObjectType::CentralHeatPumpSystem,
664 1 : state.dataIPShortCut->cAlphaArgs(1),
665 : DataLoopNode::NodeFluidType::Water,
666 : DataLoopNode::ConnectionType::Outlet,
667 : NodeInputManager::CompFluidStream::Tertiary,
668 : DataLoopNode::ObjectIsNotParent);
669 2 : BranchNodeConnections::TestCompSet(state,
670 1 : state.dataIPShortCut->cCurrentModuleObject,
671 1 : state.dataIPShortCut->cAlphaArgs(1),
672 1 : state.dataIPShortCut->cAlphaArgs(7),
673 1 : state.dataIPShortCut->cAlphaArgs(8),
674 : "Hot Water Nodes");
675 :
676 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).AncillaryPower = state.dataIPShortCut->rNumericArgs(1);
677 1 : if (state.dataIPShortCut->lAlphaFieldBlanks(9)) {
678 : // Leave this as nullptr
679 0 : } else if ((state.dataPlantCentralGSHP->Wrapper(WrapperNum).ancillaryPowerSched =
680 0 : Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(9))) == nullptr) {
681 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(9), state.dataIPShortCut->cAlphaArgs(9));
682 : }
683 :
684 1 : int NumberOfComp = (NumAlphas - 9) / 3;
685 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).NumOfComp = NumberOfComp;
686 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp.allocate(NumberOfComp);
687 :
688 1 : if (state.dataPlantCentralGSHP->Wrapper(WrapperNum).NumOfComp == 0) {
689 0 : ShowSevereError(state,
690 0 : format("GetWrapperInput: No component names on {}={}",
691 0 : state.dataIPShortCut->cCurrentModuleObject,
692 0 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).Name));
693 0 : ErrorsFound = true;
694 : } else {
695 1 : int Comp = 0;
696 1 : int NumChHtrPerWrapper = 0;
697 2 : for (int loop = 10; loop <= NumAlphas; loop += 3) {
698 1 : ++Comp;
699 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).WrapperPerformanceObjectType =
700 2 : state.dataIPShortCut->cAlphaArgs(loop);
701 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).WrapperComponentName = state.dataIPShortCut->cAlphaArgs(loop + 1);
702 :
703 1 : if (state.dataIPShortCut->lAlphaFieldBlanks(loop + 2)) {
704 0 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).chSched =
705 0 : Sched::GetScheduleAlwaysOn(state); // Not an availability schedule, but defaults to constant-1.0
706 1 : } else if ((state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).chSched =
707 2 : Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(loop + 2))) == nullptr) {
708 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).chSched =
709 1 : Sched::GetScheduleAlwaysOn(state); // Not an availabilty schedule, but defaults to constant-1.0
710 2 : ShowWarningItemNotFound(state,
711 : eoh,
712 1 : state.dataIPShortCut->cAlphaFieldNames(loop + 2),
713 1 : state.dataIPShortCut->cAlphaArgs(loop + 2),
714 : "The Control Schedule is treated as AlwaysOn instead.");
715 : }
716 :
717 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).WrapperIdenticalObjectNum =
718 1 : state.dataIPShortCut->rNumericArgs(1 + Comp);
719 1 : if (state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).WrapperPerformanceObjectType ==
720 : "CHILLERHEATERPERFORMANCE:ELECTRIC:EIR") {
721 :
722 : // count number of chiller heaters (including identical units) for current wrapper
723 1 : if (state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).WrapperIdenticalObjectNum > 1) {
724 1 : NumChHtrPerWrapper += state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).WrapperIdenticalObjectNum;
725 : } else {
726 0 : ++NumChHtrPerWrapper;
727 : }
728 :
729 : // count total number of chiller heaters (not including identical units) for ALL wrappers
730 1 : ++state.dataPlantCentralGSHP->numChillerHeaters;
731 : }
732 : }
733 :
734 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).ChillerHeaterNums = NumChHtrPerWrapper;
735 : }
736 :
737 1 : if (ErrorsFound) {
738 0 : ShowFatalError(
739 : state,
740 0 : format("GetWrapperInput: Invalid {} Input, preceding condition(s) cause termination.", state.dataIPShortCut->cCurrentModuleObject));
741 : }
742 :
743 : // ALLOCATE ARRAYS
744 1 : if ((state.dataPlantCentralGSHP->numChillerHeaters == 0) &&
745 0 : (state.dataPlantCentralGSHP->Wrapper(WrapperNum).ControlMode == CondenserType::SmartMixing)) {
746 0 : ShowFatalError(state,
747 0 : format("SmartMixing Control Mode in object {} : {} need to apply to ChillerHeaterPerformance:Electric:EIR object(s).",
748 0 : state.dataIPShortCut->cCurrentModuleObject,
749 0 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).Name));
750 : }
751 : }
752 :
753 1 : if (state.dataPlantCentralGSHP->numChillerHeaters > 0) {
754 :
755 2 : for (int WrapperNum = 1; WrapperNum <= state.dataPlantCentralGSHP->numWrappers; ++WrapperNum) {
756 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).ChillerHeater.allocate(state.dataPlantCentralGSHP->Wrapper(WrapperNum).ChillerHeaterNums);
757 : }
758 1 : GetChillerHeaterInput(state);
759 : }
760 :
761 2 : for (int WrapperNum = 1; WrapperNum <= state.dataPlantCentralGSHP->numWrappers; ++WrapperNum) {
762 1 : int ChillerHeaterNum = 0; // initialize nth chiller heater index (including identical units) for current wrapper
763 2 : for (int Comp = 1; Comp <= state.dataPlantCentralGSHP->Wrapper(WrapperNum).NumOfComp; ++Comp) {
764 1 : if (state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).WrapperPerformanceObjectType ==
765 : "CHILLERHEATERPERFORMANCE:ELECTRIC:EIR") {
766 1 : std::string CompName = state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).WrapperComponentName;
767 1 : int CompIndex = Util::FindItemInList(CompName, state.dataPlantCentralGSHP->ChillerHeater);
768 : // User may enter invalid name rather than selecting one from the object list
769 1 : if (CompIndex <= 0) {
770 0 : ShowSevereError(state, format("GetWrapperInput: Invalid Chiller Heater Modules Performance Component Name ={}", CompName));
771 0 : ShowContinueError(state, "Select the name of ChillerHeaterPerformance:Electric:EIR object(s) from the object list.");
772 0 : ShowFatalError(state, "Program terminates due to preceding condition.");
773 : }
774 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).WrapperPerformanceObjectIndex = CompIndex;
775 1 : if (state.dataPlantCentralGSHP->ChillerHeater(CompIndex).VariableFlow) {
776 1 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).VariableFlowCH = true;
777 : }
778 3 : for (int i_CH = 1; i_CH <= state.dataPlantCentralGSHP->Wrapper(WrapperNum).WrapperComp(Comp).WrapperIdenticalObjectNum; ++i_CH) {
779 : // increment nth chiller heater index (including identical units) for current wrapper
780 2 : ++ChillerHeaterNum;
781 2 : state.dataPlantCentralGSHP->Wrapper(WrapperNum).ChillerHeater(ChillerHeaterNum) =
782 4 : state.dataPlantCentralGSHP->ChillerHeater(CompIndex);
783 : }
784 1 : }
785 : }
786 : }
787 :
788 : // Release memory from temporary arrays; values now copied into their associated Wrapper in above loop
789 1 : if (allocated(state.dataPlantCentralGSHP->ChillerHeater)) {
790 1 : state.dataPlantCentralGSHP->ChillerHeater.deallocate();
791 : }
792 :
793 : // Set up output variables
794 2 : for (int WrapperNum = 1; WrapperNum <= state.dataPlantCentralGSHP->numWrappers; ++WrapperNum) {
795 : } // End of wrapper count
796 1 : }
797 :
798 0 : void WrapperSpecs::setupOutputVars(EnergyPlusData &state)
799 : {
800 0 : SetupOutputVariable(state,
801 : "Chiller Heater System Cooling Electricity Energy",
802 : Constant::Units::J,
803 0 : this->Report.TotElecCooling,
804 : OutputProcessor::TimeStepType::System,
805 : OutputProcessor::StoreType::Sum,
806 0 : this->Name,
807 : Constant::eResource::Electricity,
808 : OutputProcessor::Group::Plant,
809 : OutputProcessor::EndUseCat::Cooling);
810 :
811 0 : SetupOutputVariable(state,
812 : "Chiller Heater System Heating Electricity Energy",
813 : Constant::Units::J,
814 0 : this->Report.TotElecHeating,
815 : OutputProcessor::TimeStepType::System,
816 : OutputProcessor::StoreType::Sum,
817 0 : this->Name,
818 : Constant::eResource::Electricity,
819 : OutputProcessor::Group::Plant,
820 : OutputProcessor::EndUseCat::Heating);
821 :
822 0 : SetupOutputVariable(state,
823 : "Chiller Heater System Cooling Electricity Rate",
824 : Constant::Units::W,
825 0 : this->Report.TotElecCoolingPwr,
826 : OutputProcessor::TimeStepType::System,
827 : OutputProcessor::StoreType::Average,
828 0 : this->Name);
829 :
830 0 : SetupOutputVariable(state,
831 : "Chiller Heater System Heating Electricity Rate",
832 : Constant::Units::W,
833 0 : this->Report.TotElecHeatingPwr,
834 : OutputProcessor::TimeStepType::System,
835 : OutputProcessor::StoreType::Average,
836 0 : this->Name);
837 :
838 0 : SetupOutputVariable(state,
839 : "Chiller Heater System Cooling Energy",
840 : Constant::Units::J,
841 0 : this->Report.CoolingEnergy,
842 : OutputProcessor::TimeStepType::System,
843 : OutputProcessor::StoreType::Sum,
844 0 : this->Name,
845 : Constant::eResource::EnergyTransfer,
846 : OutputProcessor::Group::Plant,
847 : OutputProcessor::EndUseCat::Chillers);
848 :
849 0 : SetupOutputVariable(state,
850 : "Chiller Heater System Heating Energy",
851 : Constant::Units::J,
852 0 : this->Report.HeatingEnergy,
853 : OutputProcessor::TimeStepType::System,
854 : OutputProcessor::StoreType::Sum,
855 0 : this->Name,
856 : Constant::eResource::EnergyTransfer,
857 : OutputProcessor::Group::Plant,
858 : OutputProcessor::EndUseCat::Boilers);
859 :
860 0 : SetupOutputVariable(state,
861 : "Chiller Heater System Source Heat Transfer Energy",
862 : Constant::Units::J,
863 0 : this->Report.GLHEEnergy,
864 : OutputProcessor::TimeStepType::System,
865 : OutputProcessor::StoreType::Sum,
866 0 : this->Name,
867 : Constant::eResource::EnergyTransfer,
868 : OutputProcessor::Group::Plant,
869 : OutputProcessor::EndUseCat::HeatRejection);
870 :
871 0 : SetupOutputVariable(state,
872 : "Chiller Heater System Cooling Rate",
873 : Constant::Units::W,
874 0 : this->Report.CoolingRate,
875 : OutputProcessor::TimeStepType::System,
876 : OutputProcessor::StoreType::Average,
877 0 : this->Name);
878 :
879 0 : SetupOutputVariable(state,
880 : "Chiller Heater System Heating Rate",
881 : Constant::Units::W,
882 0 : this->Report.HeatingRate,
883 : OutputProcessor::TimeStepType::System,
884 : OutputProcessor::StoreType::Average,
885 0 : this->Name);
886 :
887 0 : SetupOutputVariable(state,
888 : "Chiller Heater System Source Heat Transfer Rate",
889 : Constant::Units::W,
890 0 : this->Report.GLHERate,
891 : OutputProcessor::TimeStepType::System,
892 : OutputProcessor::StoreType::Average,
893 0 : this->Name);
894 :
895 0 : SetupOutputVariable(state,
896 : "Chiller Heater System Cooling Mass Flow Rate",
897 : Constant::Units::kg_s,
898 0 : this->Report.CHWmdot,
899 : OutputProcessor::TimeStepType::System,
900 : OutputProcessor::StoreType::Average,
901 0 : this->Name);
902 :
903 0 : SetupOutputVariable(state,
904 : "Chiller Heater System Heating Mass Flow Rate",
905 : Constant::Units::kg_s,
906 0 : this->Report.HWmdot,
907 : OutputProcessor::TimeStepType::System,
908 : OutputProcessor::StoreType::Average,
909 0 : this->Name);
910 :
911 0 : SetupOutputVariable(state,
912 : "Chiller Heater System Source Mass Flow Rate",
913 : Constant::Units::kg_s,
914 0 : this->Report.GLHEmdot,
915 : OutputProcessor::TimeStepType::System,
916 : OutputProcessor::StoreType::Average,
917 0 : this->Name);
918 :
919 0 : SetupOutputVariable(state,
920 : "Chiller Heater System Cooling Inlet Temperature",
921 : Constant::Units::C,
922 0 : this->Report.CHWInletTemp,
923 : OutputProcessor::TimeStepType::System,
924 : OutputProcessor::StoreType::Average,
925 0 : this->Name);
926 :
927 0 : SetupOutputVariable(state,
928 : "Chiller Heater System Heating Inlet Temperature",
929 : Constant::Units::C,
930 0 : this->Report.HWInletTemp,
931 : OutputProcessor::TimeStepType::System,
932 : OutputProcessor::StoreType::Average,
933 0 : this->Name);
934 :
935 0 : SetupOutputVariable(state,
936 : "Chiller Heater System Source Inlet Temperature",
937 : Constant::Units::C,
938 0 : this->Report.GLHEInletTemp,
939 : OutputProcessor::TimeStepType::System,
940 : OutputProcessor::StoreType::Average,
941 0 : this->Name);
942 :
943 0 : SetupOutputVariable(state,
944 : "Chiller Heater System Cooling Outlet Temperature",
945 : Constant::Units::C,
946 0 : this->Report.CHWOutletTemp,
947 : OutputProcessor::TimeStepType::System,
948 : OutputProcessor::StoreType::Average,
949 0 : this->Name);
950 :
951 0 : SetupOutputVariable(state,
952 : "Chiller Heater System Heating Outlet Temperature",
953 : Constant::Units::C,
954 0 : this->Report.HWOutletTemp,
955 : OutputProcessor::TimeStepType::System,
956 : OutputProcessor::StoreType::Average,
957 0 : this->Name);
958 :
959 0 : SetupOutputVariable(state,
960 : "Chiller Heater System Source Outlet Temperature",
961 : Constant::Units::C,
962 0 : this->Report.GLHEOutletTemp,
963 : OutputProcessor::TimeStepType::System,
964 : OutputProcessor::StoreType::Average,
965 0 : this->Name);
966 :
967 0 : if (this->ChillerHeaterNums > 0) {
968 :
969 0 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
970 :
971 0 : SetupOutputVariable(state,
972 0 : format("Chiller Heater Operation Mode Unit {}", ChillerHeaterNum),
973 : Constant::Units::None,
974 0 : this->ChillerHeater(ChillerHeaterNum).Report.CurrentMode,
975 : OutputProcessor::TimeStepType::System,
976 : OutputProcessor::StoreType::Average,
977 0 : this->ChillerHeater(ChillerHeaterNum).Name);
978 :
979 0 : SetupOutputVariable(state,
980 0 : format("Chiller Heater Part Load Ratio Unit {}", ChillerHeaterNum),
981 : Constant::Units::None,
982 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerPartLoadRatio,
983 : OutputProcessor::TimeStepType::System,
984 : OutputProcessor::StoreType::Average,
985 0 : this->ChillerHeater(ChillerHeaterNum).Name);
986 :
987 0 : SetupOutputVariable(state,
988 0 : format("Chiller Heater Cycling Ratio Unit {}", ChillerHeaterNum),
989 : Constant::Units::None,
990 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerCyclingRatio,
991 : OutputProcessor::TimeStepType::System,
992 : OutputProcessor::StoreType::Average,
993 0 : this->ChillerHeater(ChillerHeaterNum).Name);
994 :
995 0 : SetupOutputVariable(state,
996 0 : format("Chiller Heater Cooling Electricity Rate Unit {}", ChillerHeaterNum),
997 : Constant::Units::W,
998 0 : this->ChillerHeater(ChillerHeaterNum).Report.CoolingPower,
999 : OutputProcessor::TimeStepType::System,
1000 : OutputProcessor::StoreType::Average,
1001 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1002 :
1003 0 : SetupOutputVariable(state,
1004 0 : format("Chiller Heater Heating Electricity Rate Unit {}", ChillerHeaterNum),
1005 : Constant::Units::W,
1006 0 : this->ChillerHeater(ChillerHeaterNum).Report.HeatingPower,
1007 : OutputProcessor::TimeStepType::System,
1008 : OutputProcessor::StoreType::Average,
1009 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1010 :
1011 0 : SetupOutputVariable(state,
1012 0 : format("Chiller Heater Cooling Electricity Energy Unit {}", ChillerHeaterNum),
1013 : Constant::Units::J,
1014 0 : this->ChillerHeater(ChillerHeaterNum).Report.CoolingEnergy,
1015 : OutputProcessor::TimeStepType::System,
1016 : OutputProcessor::StoreType::Sum,
1017 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1018 :
1019 0 : SetupOutputVariable(state,
1020 0 : format("Chiller Heater Heating Electricity Energy Unit {}", ChillerHeaterNum),
1021 : Constant::Units::J,
1022 0 : this->ChillerHeater(ChillerHeaterNum).Report.HeatingEnergy,
1023 : OutputProcessor::TimeStepType::System,
1024 : OutputProcessor::StoreType::Sum,
1025 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1026 :
1027 0 : SetupOutputVariable(state,
1028 0 : format("Chiller Heater Cooling Rate Unit {}", ChillerHeaterNum),
1029 : Constant::Units::W,
1030 0 : this->ChillerHeater(ChillerHeaterNum).Report.QEvap,
1031 : OutputProcessor::TimeStepType::System,
1032 : OutputProcessor::StoreType::Average,
1033 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1034 :
1035 0 : SetupOutputVariable(state,
1036 0 : format("Chiller Heater Cooling Energy Unit {}", ChillerHeaterNum),
1037 : Constant::Units::J,
1038 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapEnergy,
1039 : OutputProcessor::TimeStepType::System,
1040 : OutputProcessor::StoreType::Sum,
1041 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1042 :
1043 0 : SetupOutputVariable(state,
1044 0 : format("Chiller Heater False Load Heat Transfer Rate Unit {}", ChillerHeaterNum),
1045 : Constant::Units::W,
1046 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoadRate,
1047 : OutputProcessor::TimeStepType::System,
1048 : OutputProcessor::StoreType::Average,
1049 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1050 :
1051 0 : SetupOutputVariable(state,
1052 0 : format("Chiller Heater False Load Heat Transfer Energy Unit {}", ChillerHeaterNum),
1053 : Constant::Units::J,
1054 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoad,
1055 : OutputProcessor::TimeStepType::System,
1056 : OutputProcessor::StoreType::Sum,
1057 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1058 :
1059 0 : SetupOutputVariable(state,
1060 0 : format("Chiller Heater Evaporator Inlet Temperature Unit {}", ChillerHeaterNum),
1061 : Constant::Units::C,
1062 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapInletTemp,
1063 : OutputProcessor::TimeStepType::System,
1064 : OutputProcessor::StoreType::Average,
1065 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1066 :
1067 0 : SetupOutputVariable(state,
1068 0 : format("Chiller Heater Evaporator Outlet Temperature Unit {}", ChillerHeaterNum),
1069 : Constant::Units::C,
1070 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapOutletTemp,
1071 : OutputProcessor::TimeStepType::System,
1072 : OutputProcessor::StoreType::Average,
1073 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1074 :
1075 0 : SetupOutputVariable(state,
1076 0 : format("Chiller Heater Evaporator Mass Flow Rate Unit {}", ChillerHeaterNum),
1077 : Constant::Units::kg_s,
1078 0 : this->ChillerHeater(ChillerHeaterNum).Report.Evapmdot,
1079 : OutputProcessor::TimeStepType::System,
1080 : OutputProcessor::StoreType::Average,
1081 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1082 :
1083 0 : SetupOutputVariable(state,
1084 0 : format("Chiller Heater Condenser Heat Transfer Rate Unit {}", ChillerHeaterNum),
1085 : Constant::Units::W,
1086 0 : this->ChillerHeater(ChillerHeaterNum).Report.QCond,
1087 : OutputProcessor::TimeStepType::System,
1088 : OutputProcessor::StoreType::Average,
1089 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1090 :
1091 0 : SetupOutputVariable(state,
1092 0 : format("Chiller Heater Condenser Heat Transfer Energy Unit {}", ChillerHeaterNum),
1093 : Constant::Units::J,
1094 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondEnergy,
1095 : OutputProcessor::TimeStepType::System,
1096 : OutputProcessor::StoreType::Sum,
1097 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1098 :
1099 0 : SetupOutputVariable(state,
1100 0 : format("Chiller Heater COP Unit {}", ChillerHeaterNum),
1101 : Constant::Units::W_W,
1102 0 : this->ChillerHeater(ChillerHeaterNum).Report.ActualCOP,
1103 : OutputProcessor::TimeStepType::System,
1104 : OutputProcessor::StoreType::Average,
1105 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1106 :
1107 0 : SetupOutputVariable(state,
1108 0 : format("Chiller Heater Capacity Temperature Modifier Multiplier Unit {}", ChillerHeaterNum),
1109 : Constant::Units::None,
1110 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerCapFT,
1111 : OutputProcessor::TimeStepType::System,
1112 : OutputProcessor::StoreType::Average,
1113 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1114 :
1115 0 : SetupOutputVariable(state,
1116 0 : format("Chiller Heater EIR Temperature Modifier Multiplier Unit {}", ChillerHeaterNum),
1117 : Constant::Units::None,
1118 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFT,
1119 : OutputProcessor::TimeStepType::System,
1120 : OutputProcessor::StoreType::Average,
1121 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1122 :
1123 0 : SetupOutputVariable(state,
1124 0 : format("Chiller Heater EIR Part Load Modifier Multiplier Unit {}", ChillerHeaterNum),
1125 : Constant::Units::None,
1126 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFPLR,
1127 : OutputProcessor::TimeStepType::System,
1128 : OutputProcessor::StoreType::Average,
1129 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1130 :
1131 0 : SetupOutputVariable(state,
1132 0 : format("Chiller Heater Condenser Inlet Temperature Unit {}", ChillerHeaterNum),
1133 : Constant::Units::C,
1134 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondInletTemp,
1135 : OutputProcessor::TimeStepType::System,
1136 : OutputProcessor::StoreType::Average,
1137 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1138 :
1139 0 : SetupOutputVariable(state,
1140 0 : format("Chiller Heater Condenser Outlet Temperature Unit {}", ChillerHeaterNum),
1141 : Constant::Units::C,
1142 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondOutletTemp,
1143 : OutputProcessor::TimeStepType::System,
1144 : OutputProcessor::StoreType::Average,
1145 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1146 :
1147 0 : SetupOutputVariable(state,
1148 0 : format("Chiller Heater Condenser Mass Flow Rate Unit {}", ChillerHeaterNum),
1149 : Constant::Units::kg_s,
1150 0 : this->ChillerHeater(ChillerHeaterNum).Report.Condmdot,
1151 : OutputProcessor::TimeStepType::System,
1152 : OutputProcessor::StoreType::Average,
1153 0 : this->ChillerHeater(ChillerHeaterNum).Name);
1154 : } // End of individual chiller heater count for current wrapper
1155 :
1156 : } // End of individual chiller heater output
1157 0 : }
1158 :
1159 1 : void GetChillerHeaterInput(EnergyPlusData &state)
1160 : {
1161 : // SUBROUTINE INFORMATION:
1162 : // AUTHOR: Kyung Tae Yun, Mississippi State University
1163 : // DATE WRITTEN: Feb 2013
1164 :
1165 : // PURPOSE OF THIS SUBROUTINE:
1166 : // This routine will get the input required by the ChillerHeaterPerformance:Electric:EIR model.
1167 :
1168 1 : bool CHErrorsFound(false); // True when input errors are found
1169 : int NumAlphas; // Number of elements in the alpha array
1170 : int NumNums; // Number of elements in the numeric array
1171 : int IOStat; // IO Status when calling get input subroutine
1172 1 : Array1D<Real64> CurveValArray(11); // Used to evaluate PLFFPLR curve objects
1173 :
1174 1 : state.dataIPShortCut->cCurrentModuleObject = "ChillerHeaterPerformance:Electric:EIR";
1175 2 : state.dataPlantCentralGSHP->numChillerHeaters =
1176 1 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
1177 :
1178 1 : if (state.dataPlantCentralGSHP->numChillerHeaters <= 0) {
1179 0 : ShowSevereError(state, format("No {} equipment specified in input file", state.dataIPShortCut->cCurrentModuleObject));
1180 0 : CHErrorsFound = true;
1181 : }
1182 :
1183 : // Allocate temporary ChillerHeater and ChillerHeaterReport arrays
1184 1 : if (allocated(state.dataPlantCentralGSHP->ChillerHeater)) {
1185 0 : state.dataPlantCentralGSHP->ChillerHeater.deallocate();
1186 : }
1187 1 : state.dataPlantCentralGSHP->ChillerHeater.allocate(state.dataPlantCentralGSHP->numChillerHeaters);
1188 :
1189 : // Load arrays with electric EIR chiller data
1190 2 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= state.dataPlantCentralGSHP->numChillerHeaters; ++ChillerHeaterNum) {
1191 3 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1192 1 : state.dataIPShortCut->cCurrentModuleObject,
1193 : ChillerHeaterNum,
1194 1 : state.dataIPShortCut->cAlphaArgs,
1195 : NumAlphas,
1196 1 : state.dataIPShortCut->rNumericArgs,
1197 : NumNums,
1198 : IOStat,
1199 : _,
1200 1 : state.dataIPShortCut->lAlphaFieldBlanks,
1201 1 : state.dataIPShortCut->cAlphaFieldNames,
1202 1 : state.dataIPShortCut->cNumericFieldNames);
1203 :
1204 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).Name = state.dataIPShortCut->cAlphaArgs(1);
1205 1 : Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, CHErrorsFound);
1206 :
1207 1 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(4), "LEAVINGCONDENSER")) {
1208 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).CondModeCooling = CondenserModeTemperature::LeavingCondenser;
1209 : } else { // only other option and default value is EnteringCondenser
1210 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).CondModeCooling = CondenserModeTemperature::EnteringCondenser;
1211 : }
1212 :
1213 : // Performance curves
1214 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerCapFTCoolingIDX =
1215 1 : Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(5));
1216 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerCapFTCoolingIDX == 0) {
1217 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1218 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cAlphaFieldNames(5), state.dataIPShortCut->cAlphaArgs(5)));
1219 0 : CHErrorsFound = true;
1220 : }
1221 :
1222 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFTCoolingIDX =
1223 1 : Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(6));
1224 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFTCoolingIDX == 0) {
1225 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1226 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cAlphaFieldNames(6), state.dataIPShortCut->cAlphaArgs(6)));
1227 0 : CHErrorsFound = true;
1228 : }
1229 :
1230 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRCoolingIDX =
1231 1 : Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(7));
1232 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRCoolingIDX == 0) {
1233 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1234 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cAlphaFieldNames(7), state.dataIPShortCut->cAlphaArgs(7)));
1235 0 : CHErrorsFound = true;
1236 : }
1237 :
1238 1 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(8), "LEAVINGCONDENSER")) {
1239 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).CondModeHeating = CondenserModeTemperature::LeavingCondenser;
1240 : } else { // only other option and default value is EnteringCondenser
1241 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).CondModeHeating = CondenserModeTemperature::EnteringCondenser;
1242 : }
1243 :
1244 : // Performance curves
1245 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerCapFTHeatingIDX =
1246 1 : Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(9));
1247 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerCapFTHeatingIDX == 0) {
1248 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1249 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cAlphaFieldNames(9), state.dataIPShortCut->cAlphaArgs(9)));
1250 0 : CHErrorsFound = true;
1251 : }
1252 :
1253 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFTHeatingIDX =
1254 1 : Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(10));
1255 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFTHeatingIDX == 0) {
1256 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1257 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cAlphaFieldNames(10), state.dataIPShortCut->cAlphaArgs(10)));
1258 0 : CHErrorsFound = true;
1259 : }
1260 :
1261 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRHeatingIDX =
1262 1 : Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(11));
1263 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRHeatingIDX == 0) {
1264 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1265 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cAlphaFieldNames(11), state.dataIPShortCut->cAlphaArgs(11)));
1266 0 : CHErrorsFound = true;
1267 : }
1268 :
1269 1 : if (state.dataIPShortCut->cAlphaArgs(2) == "CONSTANTFLOW") {
1270 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ConstantFlow = true;
1271 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).VariableFlow = false;
1272 1 : } else if (state.dataIPShortCut->cAlphaArgs(2) == "VARIABLEFLOW") {
1273 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ConstantFlow = false;
1274 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).VariableFlow = true;
1275 : } else { // Assume a constant flow chiller if none is specified
1276 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ConstantFlow = true;
1277 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).VariableFlow = false;
1278 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1279 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
1280 0 : ShowContinueError(state, "simulation assumes CONSTANTFLOW and continues..");
1281 : }
1282 :
1283 1 : if (ChillerHeaterNum > 1) {
1284 0 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ConstantFlow !=
1285 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum - 1).ConstantFlow) {
1286 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ConstantFlow = true;
1287 0 : ShowWarningError(state,
1288 0 : format("Water flow mode is different from the other chiller heater(s) {}={}",
1289 0 : state.dataIPShortCut->cCurrentModuleObject,
1290 0 : state.dataIPShortCut->cAlphaArgs(1)));
1291 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
1292 0 : ShowContinueError(state, "Simulation assumes CONSTANTFLOW and continues..");
1293 : }
1294 : }
1295 :
1296 1 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(3), "WaterCooled")) {
1297 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).condenserType = CondenserType::WaterCooled;
1298 : } else {
1299 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1300 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
1301 0 : ShowContinueError(state, "Valid entries is WaterCooled");
1302 0 : CHErrorsFound = true;
1303 : }
1304 :
1305 : // Chiller rated performance data
1306 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefCapCooling = state.dataIPShortCut->rNumericArgs(1);
1307 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefCapCooling == DataSizing::AutoSize) {
1308 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefCapCoolingWasAutoSized = true;
1309 : }
1310 1 : if (state.dataIPShortCut->rNumericArgs(1) == 0.0) {
1311 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1312 0 : ShowContinueError(state,
1313 0 : format("Entered in {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(1), state.dataIPShortCut->rNumericArgs(1)));
1314 0 : CHErrorsFound = true;
1315 : }
1316 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefCOPCooling = state.dataIPShortCut->rNumericArgs(2);
1317 1 : if (state.dataIPShortCut->rNumericArgs(2) == 0.0) {
1318 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1319 0 : ShowContinueError(state,
1320 0 : format("Entered in {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
1321 0 : CHErrorsFound = true;
1322 : }
1323 :
1324 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefEvapOutCooling = state.dataIPShortCut->rNumericArgs(3);
1325 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefCondInCooling = state.dataIPShortCut->rNumericArgs(4);
1326 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefCondOutCooling = state.dataIPShortCut->rNumericArgs(5);
1327 :
1328 : // Reference Heating Mode Ratios for Capacity and Power
1329 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ClgHtgToCoolingCapRatio = state.dataIPShortCut->rNumericArgs(6);
1330 1 : if (state.dataIPShortCut->rNumericArgs(6) == 0.0) {
1331 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1332 0 : ShowContinueError(state,
1333 0 : format("Entered in {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(6), state.dataIPShortCut->rNumericArgs(6)));
1334 0 : CHErrorsFound = true;
1335 : }
1336 :
1337 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ClgHtgtoCogPowerRatio = state.dataIPShortCut->rNumericArgs(7);
1338 1 : if (state.dataIPShortCut->rNumericArgs(7) == 0.0) {
1339 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1340 0 : ShowContinueError(state,
1341 0 : format("Entered in {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(7), state.dataIPShortCut->rNumericArgs(7)));
1342 0 : CHErrorsFound = true;
1343 : }
1344 :
1345 1 : if (!state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefCapCoolingWasAutoSized) {
1346 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefCapClgHtg =
1347 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ClgHtgToCoolingCapRatio *
1348 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefCapCooling;
1349 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefPowerClgHtg =
1350 0 : (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefCapCooling /
1351 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefCOPCooling) *
1352 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ClgHtgtoCogPowerRatio;
1353 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefCOPClgHtg =
1354 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefCapClgHtg /
1355 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).RefPowerClgHtg;
1356 : }
1357 :
1358 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefEvapOutClgHtg = state.dataIPShortCut->rNumericArgs(8);
1359 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefCondOutClgHtg = state.dataIPShortCut->rNumericArgs(9);
1360 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefCondInClgHtg = state.dataIPShortCut->rNumericArgs(10);
1361 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempLowLimitEvapOut = state.dataIPShortCut->rNumericArgs(11);
1362 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).EvapVolFlowRate = state.dataIPShortCut->rNumericArgs(12);
1363 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).EvapVolFlowRate == DataSizing::AutoSize) {
1364 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).EvapVolFlowRateWasAutoSized = true;
1365 : }
1366 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).CondVolFlowRate = state.dataIPShortCut->rNumericArgs(13);
1367 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).CondVolFlowRate == DataSizing::AutoSize) {
1368 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).CondVolFlowRateWasAutoSized = true;
1369 : }
1370 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).DesignHotWaterVolFlowRate = state.dataIPShortCut->rNumericArgs(14);
1371 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).OpenMotorEff = state.dataIPShortCut->rNumericArgs(15);
1372 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).OptPartLoadRatCooling = state.dataIPShortCut->rNumericArgs(16);
1373 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).OptPartLoadRatClgHtg = state.dataIPShortCut->rNumericArgs(17);
1374 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).SizFac = state.dataIPShortCut->rNumericArgs(18);
1375 :
1376 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).SizFac <= 0.0) {
1377 0 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).SizFac = 1.0;
1378 : }
1379 :
1380 2 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).OpenMotorEff < 0.0 ||
1381 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).OpenMotorEff > 1.0) {
1382 0 : ShowSevereError(state,
1383 0 : format("GetCurveInput: For {}: {}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1384 0 : ShowContinueError(state, format("{} = {:.3R}", state.dataIPShortCut->cNumericFieldNames(14), state.dataIPShortCut->rNumericArgs(14)));
1385 0 : ShowContinueError(state, format("{} must be greater than or equal to zero", state.dataIPShortCut->cNumericFieldNames(14)));
1386 0 : ShowContinueError(state, format("{} must be less than or equal to one", state.dataIPShortCut->cNumericFieldNames(14)));
1387 0 : CHErrorsFound = true;
1388 : }
1389 :
1390 : // Check the CAP-FT, EIR-FT, and PLR curves and warn user if different from 1.0 by more than +-10%
1391 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerCapFTCoolingIDX > 0) {
1392 4 : Real64 CurveVal = Curve::CurveValue(state,
1393 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerCapFTCoolingIDX,
1394 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefEvapOutCooling,
1395 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefCondInCooling);
1396 1 : if (CurveVal > 1.10 || CurveVal < 0.90) {
1397 0 : ShowWarningError(state, "Capacity ratio as a function of temperature curve output is not equal to 1.0");
1398 0 : ShowContinueError(state,
1399 0 : format("(+ or - 10%) at reference conditions for {}= {}",
1400 0 : state.dataIPShortCut->cCurrentModuleObject,
1401 0 : state.dataIPShortCut->cAlphaArgs(1)));
1402 0 : ShowContinueError(state, format("Curve output at reference conditions = {:.3T}", CurveVal));
1403 : }
1404 : }
1405 :
1406 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFTCoolingIDX > 0) {
1407 4 : Real64 CurveVal = Curve::CurveValue(state,
1408 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFTCoolingIDX,
1409 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefEvapOutCooling,
1410 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefCondInCooling);
1411 1 : if (CurveVal > 1.10 || CurveVal < 0.90) {
1412 0 : ShowWarningError(state, "Energy input ratio as a function of temperature curve output is not equal to 1.0");
1413 0 : ShowContinueError(state,
1414 0 : format("(+ or - 10%) at reference conditions for {}= {}",
1415 0 : state.dataIPShortCut->cCurrentModuleObject,
1416 0 : state.dataIPShortCut->cAlphaArgs(1)));
1417 0 : ShowContinueError(state, format("Curve output at reference conditions = {:.3T}", CurveVal));
1418 : }
1419 : }
1420 :
1421 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRCoolingIDX > 0) {
1422 1 : Real64 CurveVal = Curve::CurveValue(state, state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRCoolingIDX, 1.0);
1423 :
1424 1 : if (CurveVal > 1.10 || CurveVal < 0.90) {
1425 0 : ShowWarningError(state, "Energy input ratio as a function of part-load ratio curve output is not equal to 1.0");
1426 0 : ShowContinueError(state,
1427 0 : format("(+ or - 10%) at reference conditions for {}= {}",
1428 0 : state.dataIPShortCut->cCurrentModuleObject,
1429 0 : state.dataIPShortCut->cAlphaArgs(1)));
1430 0 : ShowContinueError(state, format("Curve output at reference conditions = {:.3T}", CurveVal));
1431 : }
1432 : }
1433 :
1434 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRCoolingIDX > 0) {
1435 1 : bool FoundNegValue = false;
1436 12 : for (int CurveCheck = 0; CurveCheck <= 10; ++CurveCheck) {
1437 33 : Real64 CurveValTmp = Curve::CurveValue(
1438 11 : state, state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRCoolingIDX, double(CurveCheck / 10.0));
1439 11 : if (CurveValTmp < 0.0) {
1440 0 : FoundNegValue = true;
1441 : }
1442 11 : CurveValArray(CurveCheck + 1) = int(CurveValTmp * 100.0) / 100.0;
1443 : }
1444 1 : if (FoundNegValue) {
1445 0 : ShowWarningError(state, "Energy input ratio as a function of part-load ratio curve shows negative values ");
1446 0 : ShowContinueError(state, format("for {}= {}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1447 0 : ShowContinueError(state, "EIR as a function of PLR curve output at various part-load ratios shown below:");
1448 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");
1449 :
1450 0 : ShowContinueError(state, fmt::format("Curve Output = {:7.2F}", fmt::join(CurveValArray, ",")));
1451 :
1452 0 : CHErrorsFound = true;
1453 : }
1454 : }
1455 :
1456 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerCapFTHeatingIDX > 0) {
1457 4 : Real64 CurveVal = Curve::CurveValue(state,
1458 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerCapFTHeatingIDX,
1459 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefEvapOutClgHtg,
1460 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefCondInClgHtg);
1461 1 : if (CurveVal > 1.10 || CurveVal < 0.90) {
1462 2 : ShowWarningError(state, "Capacity ratio as a function of temperature curve output is not equal to 1.0");
1463 2 : ShowContinueError(state,
1464 3 : format("(+ or - 10%) at reference conditions for {}= {}",
1465 1 : state.dataIPShortCut->cCurrentModuleObject,
1466 1 : state.dataIPShortCut->cAlphaArgs(1)));
1467 1 : ShowContinueError(state, format("Curve output at reference conditions = {:.3T}", CurveVal));
1468 : }
1469 : }
1470 :
1471 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFTHeatingIDX > 0) {
1472 4 : Real64 CurveVal = Curve::CurveValue(state,
1473 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFTHeatingIDX,
1474 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefEvapOutClgHtg,
1475 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).TempRefCondInClgHtg);
1476 1 : if (CurveVal > 1.10 || CurveVal < 0.90) {
1477 2 : ShowWarningError(state, "Energy input ratio as a function of temperature curve output is not equal to 1.0");
1478 2 : ShowContinueError(state,
1479 3 : format("(+ or - 10%) at reference conditions for {}= {}",
1480 1 : state.dataIPShortCut->cCurrentModuleObject,
1481 1 : state.dataIPShortCut->cAlphaArgs(1)));
1482 1 : ShowContinueError(state, format("Curve output at reference conditions = {:.3T}", CurveVal));
1483 : }
1484 : }
1485 :
1486 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRHeatingIDX > 0) {
1487 1 : Real64 CurveVal = Curve::CurveValue(state, state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRHeatingIDX, 1.0);
1488 :
1489 1 : if (CurveVal > 1.10 || CurveVal < 0.90) {
1490 0 : ShowWarningError(state, "Energy input ratio as a function of part-load ratio curve output is not equal to 1.0");
1491 0 : ShowContinueError(state,
1492 0 : format("(+ or - 10%) at reference conditions for {}= {}",
1493 0 : state.dataIPShortCut->cCurrentModuleObject,
1494 0 : state.dataIPShortCut->cAlphaArgs(1)));
1495 0 : ShowContinueError(state, format("Curve output at reference conditions = {:.3T}", CurveVal));
1496 : }
1497 : }
1498 :
1499 1 : if (state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRHeatingIDX > 0) {
1500 1 : bool FoundNegValue = false;
1501 12 : for (int CurveCheck = 0; CurveCheck <= 10; ++CurveCheck) {
1502 33 : Real64 CurveValTmp = Curve::CurveValue(
1503 11 : state, state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRHeatingIDX, double(CurveCheck / 10.0));
1504 11 : if (CurveValTmp < 0.0) {
1505 0 : FoundNegValue = true;
1506 : }
1507 11 : CurveValArray(CurveCheck + 1) = int(CurveValTmp * 100.0) / 100.0;
1508 : }
1509 1 : if (FoundNegValue) {
1510 0 : ShowWarningError(state, "Energy input ratio as a function of part-load ratio curve shows negative values ");
1511 0 : ShowContinueError(state, format("for {}= {}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1512 0 : ShowContinueError(state, "EIR as a function of PLR curve output at various part-load ratios shown below:");
1513 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");
1514 :
1515 0 : std::string const curve_output = fmt::format("Curve Output = {:7.2F}", fmt::join(CurveValArray, ","));
1516 0 : ShowContinueError(state, curve_output);
1517 :
1518 0 : CHErrorsFound = true;
1519 0 : }
1520 : }
1521 :
1522 1 : Curve::GetCurveMinMaxValues(state,
1523 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRHeatingIDX,
1524 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).MinPartLoadRatClgHtg,
1525 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).MaxPartLoadRatClgHtg);
1526 :
1527 1 : Curve::GetCurveMinMaxValues(state,
1528 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRCoolingIDX,
1529 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).MinPartLoadRatCooling,
1530 1 : state.dataPlantCentralGSHP->ChillerHeater(ChillerHeaterNum).MaxPartLoadRatCooling);
1531 : }
1532 :
1533 1 : if (CHErrorsFound) {
1534 0 : ShowFatalError(state, format("Errors found in processing input for {}", state.dataIPShortCut->cCurrentModuleObject));
1535 : }
1536 1 : }
1537 :
1538 0 : void WrapperSpecs::initialize(EnergyPlusData &state,
1539 : Real64 MyLoad, // Demand Load
1540 : int LoopNum // Loop Number Index
1541 : )
1542 : {
1543 : // SUBROUTINE INFORMATION:
1544 : // AUTHOR Daeho Kang, PNNL
1545 : // DATE WRITTEN Feb 2013
1546 : // MODIFIED na
1547 : // RE-ENGINEERED na
1548 :
1549 : // PURPOSE OF THIS SUBROUTINE:
1550 : // This subroutine is for initializations of the CentralHeatPumpSystem variables
1551 :
1552 : // METHODOLOGY EMPLOYED:
1553 : // Uses the status flags to trigger initializations.
1554 :
1555 : static constexpr std::string_view RoutineName("InitCGSHPHeatPump");
1556 :
1557 0 : if (this->setupOutputVarsFlag) {
1558 0 : this->setupOutputVars(state);
1559 0 : this->setupOutputVarsFlag = false;
1560 : }
1561 :
1562 0 : if (this->MyWrapperFlag) {
1563 : // Locate the chillers on the plant loops for later usage
1564 0 : bool errFlag = false;
1565 0 : PlantUtilities::ScanPlantLoopsForObject(state,
1566 : this->Name,
1567 : DataPlant::PlantEquipmentType::CentralGroundSourceHeatPump,
1568 0 : this->CWPlantLoc,
1569 : errFlag,
1570 : _,
1571 : _,
1572 : _,
1573 0 : this->CHWInletNodeNum,
1574 : _);
1575 :
1576 0 : PlantUtilities::ScanPlantLoopsForObject(state,
1577 : this->Name,
1578 : DataPlant::PlantEquipmentType::CentralGroundSourceHeatPump,
1579 0 : this->HWPlantLoc,
1580 : errFlag,
1581 : _,
1582 : _,
1583 : _,
1584 0 : this->HWInletNodeNum,
1585 : _);
1586 :
1587 0 : PlantUtilities::ScanPlantLoopsForObject(state,
1588 : this->Name,
1589 : DataPlant::PlantEquipmentType::CentralGroundSourceHeatPump,
1590 0 : this->GLHEPlantLoc,
1591 : errFlag,
1592 : _,
1593 : _,
1594 : _,
1595 0 : this->GLHEInletNodeNum,
1596 : _);
1597 :
1598 0 : PlantUtilities::InterConnectTwoPlantLoopSides(
1599 0 : state, this->CWPlantLoc, this->GLHEPlantLoc, DataPlant::PlantEquipmentType::CentralGroundSourceHeatPump, true);
1600 :
1601 0 : PlantUtilities::InterConnectTwoPlantLoopSides(
1602 0 : state, this->HWPlantLoc, this->GLHEPlantLoc, DataPlant::PlantEquipmentType::CentralGroundSourceHeatPump, true);
1603 :
1604 0 : PlantUtilities::InterConnectTwoPlantLoopSides(
1605 0 : state, this->CWPlantLoc, this->HWPlantLoc, DataPlant::PlantEquipmentType::CentralGroundSourceHeatPump, true);
1606 :
1607 0 : if (this->VariableFlowCH) {
1608 : // Reset flow priority
1609 0 : if (LoopNum == this->CWPlantLoc.loopNum) {
1610 0 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
1611 0 : } else if (LoopNum == this->HWPlantLoc.loopNum) {
1612 0 : DataPlant::CompData::getPlantComponent(state, this->HWPlantLoc).FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
1613 : }
1614 :
1615 : // check if setpoint on outlet node - chilled water loop
1616 0 : if (state.dataLoopNodes->Node(this->CHWOutletNodeNum).TempSetPoint == DataLoopNode::SensedNodeFlagValue) {
1617 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
1618 0 : if (!this->CoolSetPointErrDone) {
1619 0 : ShowWarningError(state,
1620 0 : format("Missing temperature setpoint on cooling side for CentralHeatPumpSystem named {}", this->Name));
1621 0 : ShowContinueError(state,
1622 : " A temperature setpoint is needed at the outlet node of a CentralHeatPumpSystem, use a SetpointManager");
1623 0 : ShowContinueError(state,
1624 : " The overall loop setpoint will be assumed for CentralHeatPumpSystem. The simulation continues ... ");
1625 0 : this->CoolSetPointErrDone = true;
1626 : }
1627 : } else {
1628 : // need call to EMS to check node
1629 0 : bool FatalError = false; // but not really fatal yet, but should be.
1630 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(state, this->CHWOutletNodeNum, HVAC::CtrlVarType::Temp, FatalError);
1631 0 : state.dataLoopNodes->NodeSetpointCheck(this->CHWOutletNodeNum).needsSetpointChecking = false;
1632 0 : if (FatalError) {
1633 0 : if (!this->CoolSetPointErrDone) {
1634 0 : ShowWarningError(state,
1635 0 : format("Missing temperature setpoint on cooling side for CentralHeatPumpSystem named {}", this->Name));
1636 0 : ShowContinueError(state, "A temperature setpoint is needed at the outlet node of a CentralHeatPumpSystem ");
1637 0 : ShowContinueError(state, "use a Setpoint Manager to establish a setpoint at the chiller side outlet node ");
1638 0 : ShowContinueError(state, "or use an EMS actuator to establish a setpoint at the outlet node ");
1639 0 : ShowContinueError(state, "The overall loop setpoint will be assumed for chiller side. The simulation continues ... ");
1640 0 : this->CoolSetPointErrDone = true;
1641 : }
1642 : }
1643 : }
1644 0 : this->CoolSetPointSetToLoop = true;
1645 0 : state.dataLoopNodes->Node(this->CHWOutletNodeNum).TempSetPoint =
1646 0 : state.dataLoopNodes->Node(this->CWPlantLoc.loop->TempSetPointNodeNum).TempSetPoint;
1647 : }
1648 :
1649 0 : if (state.dataLoopNodes->Node(this->HWOutletNodeNum).TempSetPoint == DataLoopNode::SensedNodeFlagValue) {
1650 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
1651 0 : if (!this->HeatSetPointErrDone) {
1652 0 : ShowWarningError(state,
1653 0 : format("Missing temperature setpoint on heating side for CentralHeatPumpSystem named {}", this->Name));
1654 0 : ShowContinueError(state,
1655 : " A temperature setpoint is needed at the outlet node of a CentralHeatPumpSystem, use a SetpointManager");
1656 0 : ShowContinueError(state,
1657 : " The overall loop setpoint will be assumed for CentralHeatPumpSystem. The simulation continues ... ");
1658 0 : this->HeatSetPointErrDone = true;
1659 : }
1660 : } else {
1661 : // need call to EMS to check node
1662 0 : bool FatalError = false; // but not really fatal yet, but should be.
1663 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(state, this->HWOutletNodeNum, HVAC::CtrlVarType::Temp, FatalError);
1664 0 : state.dataLoopNodes->NodeSetpointCheck(this->HWOutletNodeNum).needsSetpointChecking = false;
1665 0 : if (FatalError) {
1666 0 : if (!this->HeatSetPointErrDone) {
1667 0 : ShowWarningError(state,
1668 0 : format("Missing temperature setpoint on heating side for CentralHeatPumpSystem named {}", this->Name));
1669 0 : ShowContinueError(state, "A temperature setpoint is needed at the outlet node of a CentralHeatPumpSystem ");
1670 0 : ShowContinueError(state, "use a Setpoint Manager to establish a setpoint at the chiller side outlet node ");
1671 0 : ShowContinueError(state, "or use an EMS actuator to establish a setpoint at the outlet node ");
1672 0 : ShowContinueError(state, "The overall loop setpoint will be assumed for chiller side. The simulation continues ... ");
1673 0 : this->HeatSetPointErrDone = true;
1674 : }
1675 : }
1676 : }
1677 0 : this->HeatSetPointSetToLoop = true;
1678 0 : state.dataLoopNodes->Node(this->HWOutletNodeNum).TempSetPoint =
1679 0 : state.dataLoopNodes->Node(this->HWPlantLoc.loop->TempSetPointNodeNum).TempSetPoint;
1680 : }
1681 : }
1682 0 : this->MyWrapperFlag = false;
1683 : }
1684 :
1685 0 : if (this->MyWrapperEnvrnFlag && state.dataGlobal->BeginEnvrnFlag && (state.dataPlnt->PlantFirstSizesOkayToFinalize)) {
1686 :
1687 0 : if (this->ControlMode == CondenserType::SmartMixing) {
1688 :
1689 0 : this->CHWVolFlowRate = 0.0;
1690 0 : this->HWVolFlowRate = 0.0;
1691 0 : this->GLHEVolFlowRate = 0.0;
1692 :
1693 0 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
1694 0 : this->CHWVolFlowRate += this->ChillerHeater(ChillerHeaterNum).EvapVolFlowRate;
1695 0 : this->HWVolFlowRate += this->ChillerHeater(ChillerHeaterNum).DesignHotWaterVolFlowRate;
1696 0 : this->GLHEVolFlowRate += this->ChillerHeater(ChillerHeaterNum).CondVolFlowRate;
1697 : }
1698 :
1699 0 : Real64 rho = this->CWPlantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
1700 :
1701 0 : this->CHWMassFlowRateMax = this->CHWVolFlowRate * rho;
1702 0 : this->HWMassFlowRateMax = this->HWVolFlowRate * rho;
1703 0 : this->GLHEMassFlowRateMax = this->GLHEVolFlowRate * rho;
1704 :
1705 0 : PlantUtilities::InitComponentNodes(state, 0.0, this->CHWMassFlowRateMax, this->CHWInletNodeNum, this->CHWOutletNodeNum);
1706 0 : PlantUtilities::InitComponentNodes(state, 0.0, this->HWMassFlowRateMax, this->HWInletNodeNum, this->HWOutletNodeNum);
1707 0 : PlantUtilities::InitComponentNodes(state, 0.0, this->GLHEMassFlowRateMax, this->GLHEInletNodeNum, this->GLHEOutletNodeNum);
1708 :
1709 : // Initialize nodes for individual chiller heaters
1710 0 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
1711 0 : this->ChillerHeater(ChillerHeaterNum).EvapInletNode.MassFlowRateMin = 0.0;
1712 0 : this->ChillerHeater(ChillerHeaterNum).EvapInletNode.MassFlowRateMinAvail = 0.0;
1713 0 : this->ChillerHeater(ChillerHeaterNum).EvapInletNode.MassFlowRateMax = rho * this->ChillerHeater(ChillerHeaterNum).EvapVolFlowRate;
1714 0 : this->ChillerHeater(ChillerHeaterNum).EvapInletNode.MassFlowRateMaxAvail =
1715 0 : rho * this->ChillerHeater(ChillerHeaterNum).EvapVolFlowRate;
1716 0 : this->ChillerHeater(ChillerHeaterNum).EvapInletNode.MassFlowRate = 0.0;
1717 0 : this->ChillerHeater(ChillerHeaterNum).CondInletNode.MassFlowRateMin = 0.0;
1718 0 : this->ChillerHeater(ChillerHeaterNum).CondInletNode.MassFlowRateMinAvail = 0.0;
1719 0 : this->ChillerHeater(ChillerHeaterNum).CondInletNode.MassFlowRateMax = rho * this->ChillerHeater(ChillerHeaterNum).EvapVolFlowRate;
1720 0 : this->ChillerHeater(ChillerHeaterNum).CondInletNode.MassFlowRateMaxAvail =
1721 0 : rho * this->ChillerHeater(ChillerHeaterNum).EvapVolFlowRate;
1722 0 : this->ChillerHeater(ChillerHeaterNum).CondInletNode.MassFlowRate = 0.0;
1723 0 : this->ChillerHeater(ChillerHeaterNum).CondInletNode.MassFlowRateRequest = 0.0;
1724 : }
1725 : }
1726 0 : this->MyWrapperEnvrnFlag = false;
1727 : }
1728 :
1729 0 : if (!state.dataGlobal->BeginEnvrnFlag) {
1730 0 : this->MyWrapperEnvrnFlag = true;
1731 : }
1732 :
1733 0 : if (this->CoolSetPointSetToLoop) {
1734 : // IF (CurCoolingLoad > 0.0d0) THEN
1735 0 : state.dataLoopNodes->Node(this->CHWOutletNodeNum).TempSetPoint =
1736 0 : state.dataLoopNodes->Node(this->CWPlantLoc.loop->TempSetPointNodeNum).TempSetPoint;
1737 : }
1738 : // IF (CurHeatingLoad > 0.0d0) THEN
1739 0 : if (this->HeatSetPointSetToLoop) {
1740 0 : state.dataLoopNodes->Node(this->HWOutletNodeNum).TempSetPoint =
1741 0 : state.dataLoopNodes->Node(this->HWPlantLoc.loop->TempSetPointNodeNum).TempSetPoint;
1742 : // ENDIF
1743 : }
1744 :
1745 : Real64 mdotCHW; // Chilled water mass flow rate
1746 : Real64 mdotHW; // Hot water mass flow rate
1747 : Real64 mdotGLHE; // Condenser water mass flow rate
1748 :
1749 : // Switch over the mass flow rate to the condenser loop, i.e., ground heat exchanger
1750 0 : if (LoopNum == this->CWPlantLoc.loopNum) { // called for on cooling loop
1751 0 : if (MyLoad < -1.0) { // calling for cooling
1752 0 : mdotCHW = state.dataLoopNodes->Node(this->CHWInletNodeNum).MassFlowRateMax;
1753 : } else {
1754 0 : mdotCHW = 0.0;
1755 : }
1756 0 : if (this->WrapperHeatingLoad > 1.0) {
1757 0 : mdotHW = state.dataLoopNodes->Node(this->HWInletNodeNum).MassFlowRateMax;
1758 : } else {
1759 0 : mdotHW = 0.0;
1760 : }
1761 0 : if ((MyLoad < -1.0) || (this->WrapperHeatingLoad > 1.0)) {
1762 0 : mdotGLHE = state.dataLoopNodes->Node(this->GLHEInletNodeNum).MassFlowRateMax;
1763 : } else {
1764 0 : mdotGLHE = 0.0;
1765 : }
1766 :
1767 0 : } else if (LoopNum == this->HWPlantLoc.loopNum) {
1768 0 : if (MyLoad > 1.0) {
1769 0 : mdotHW = state.dataLoopNodes->Node(this->HWInletNodeNum).MassFlowRateMax;
1770 : } else {
1771 0 : mdotHW = 0.0;
1772 : }
1773 0 : if (this->WrapperCoolingLoad > 1.0) {
1774 0 : mdotCHW = state.dataLoopNodes->Node(this->CHWInletNodeNum).MassFlowRateMax;
1775 : } else {
1776 0 : mdotCHW = 0.0;
1777 : }
1778 0 : if ((MyLoad > 1.0) || (this->WrapperCoolingLoad > 1.0)) {
1779 0 : mdotGLHE = state.dataLoopNodes->Node(this->GLHEInletNodeNum).MassFlowRateMax;
1780 : } else {
1781 0 : mdotGLHE = 0.0;
1782 : }
1783 :
1784 0 : } else if (LoopNum == this->GLHEPlantLoc.loopNum) {
1785 0 : if (this->WrapperCoolingLoad > 1.0) {
1786 0 : mdotCHW = state.dataLoopNodes->Node(this->CHWInletNodeNum).MassFlowRateMax;
1787 : } else {
1788 0 : mdotCHW = 0.0;
1789 : }
1790 0 : if (this->WrapperHeatingLoad > 1.0) {
1791 0 : mdotHW = state.dataLoopNodes->Node(this->HWInletNodeNum).MassFlowRateMax;
1792 : } else {
1793 0 : mdotHW = 0.0;
1794 : }
1795 0 : if ((this->WrapperHeatingLoad > 1.0) || (this->WrapperCoolingLoad > 1.0)) {
1796 0 : mdotGLHE = state.dataLoopNodes->Node(this->GLHEInletNodeNum).MassFlowRateMax;
1797 : } else {
1798 0 : mdotGLHE = 0.0;
1799 : }
1800 : }
1801 :
1802 0 : PlantUtilities::SetComponentFlowRate(state, mdotCHW, this->CHWInletNodeNum, this->CHWOutletNodeNum, this->CWPlantLoc);
1803 :
1804 0 : PlantUtilities::SetComponentFlowRate(state, mdotHW, this->HWInletNodeNum, this->HWOutletNodeNum, this->HWPlantLoc);
1805 :
1806 0 : PlantUtilities::SetComponentFlowRate(state, mdotGLHE, this->GLHEInletNodeNum, this->GLHEOutletNodeNum, this->GLHEPlantLoc);
1807 0 : }
1808 :
1809 0 : void WrapperSpecs::CalcChillerModel(EnergyPlusData &state)
1810 : {
1811 : // SUBROUTINE INFORMATION:
1812 : // AUTHOR Daeho Kang, PNNL
1813 : // DATE WRITTEN Feb 2013
1814 : // MODIFIED na
1815 : // RE-ENGINEERED na
1816 :
1817 : // PURPOSE OF THIS SUBROUTINE:
1818 : // Simulate a ChillerHeaterPerformance:Electric:EIR using curve fit
1819 :
1820 : // METHODOLOGY EMPLOYED:
1821 : // Use empirical curve fits to model performance at off-reference conditions
1822 :
1823 : // REFERENCES:
1824 : // 1. DOE-2 Engineers Manual, Version 2.1A, November 1982, LBL-11353
1825 :
1826 : static constexpr std::string_view RoutineName("CalcChillerHeaterModel");
1827 : static constexpr std::string_view RoutineNameElecEIRChiller("CalcElectricEIRChillerModel");
1828 :
1829 : bool IsLoadCoolRemaining;
1830 0 : bool NextCompIndicator(false); // Component indicator when identical chiller heaters exist
1831 0 : int CompNum = 0; // Component number in the loop REAL(r64) :: FRAC
1832 0 : int IdenticalUnitCounter = 0; // Pointer to count number of identical unit passed
1833 0 : Real64 CurAvailCHWMassFlowRate(0.0); // Maximum available mass flow rate for current chiller heater
1834 :
1835 : // Cooling load evaporator should meet
1836 0 : Real64 EvaporatorLoad = this->WrapperCoolingLoad;
1837 :
1838 : // Chilled water inlet mass flow rate
1839 0 : Real64 CHWInletMassFlowRate = state.dataLoopNodes->Node(this->CHWInletNodeNum).MassFlowRate;
1840 :
1841 0 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
1842 :
1843 : // Initialize local variables for each chiller heater
1844 0 : int CurrentMode = 0;
1845 0 : state.dataPlantCentralGSHP->ChillerCapFT = 0.0;
1846 0 : state.dataPlantCentralGSHP->ChillerEIRFT = 0.0;
1847 0 : state.dataPlantCentralGSHP->ChillerEIRFPLR = 0.0;
1848 0 : state.dataPlantCentralGSHP->ChillerPartLoadRatio = 0.0;
1849 0 : state.dataPlantCentralGSHP->ChillerCyclingRatio = 0.0;
1850 0 : state.dataPlantCentralGSHP->ChillerFalseLoadRate = 0.0;
1851 :
1852 0 : Real64 CHPower = 0.0;
1853 0 : Real64 QCondenser = 0.0;
1854 0 : Real64 QEvaporator = 0.0;
1855 0 : Real64 FRAC = 1.0;
1856 0 : Real64 ActualCOP = 0.0;
1857 0 : Real64 EvapInletTemp = state.dataLoopNodes->Node(this->CHWInletNodeNum).Temp;
1858 0 : Real64 CondInletTemp = state.dataLoopNodes->Node(this->GLHEInletNodeNum).Temp;
1859 0 : Real64 EvapOutletTemp = EvapInletTemp;
1860 0 : Real64 CondOutletTemp = CondInletTemp;
1861 0 : this->ChillerHeater(ChillerHeaterNum).Report.CurrentMode = 0;
1862 :
1863 : // Find proper schedule values
1864 0 : if (this->NumOfComp != this->ChillerHeaterNums) { // Identical units exist
1865 0 : if (ChillerHeaterNum == 1) {
1866 0 : IdenticalUnitCounter = 0;
1867 0 : NextCompIndicator = false;
1868 0 : CompNum = ChillerHeaterNum;
1869 : }
1870 0 : if (NextCompIndicator) {
1871 0 : ++CompNum;
1872 : }
1873 0 : if (CompNum == 1) {
1874 0 : if (ChillerHeaterNum != this->WrapperComp(CompNum).WrapperIdenticalObjectNum) {
1875 0 : NextCompIndicator = false;
1876 0 : } else if (ChillerHeaterNum == this->WrapperComp(CompNum).WrapperIdenticalObjectNum) {
1877 0 : NextCompIndicator = true;
1878 : }
1879 0 : } else if (CompNum > 1) {
1880 0 : if ((ChillerHeaterNum - ((ChillerHeaterNum - 1) - IdenticalUnitCounter)) != this->WrapperComp(CompNum).WrapperIdenticalObjectNum) {
1881 0 : NextCompIndicator = false;
1882 0 : } else if ((ChillerHeaterNum - ((ChillerHeaterNum - 1) - IdenticalUnitCounter)) ==
1883 0 : this->WrapperComp(CompNum).WrapperIdenticalObjectNum) {
1884 0 : NextCompIndicator = true;
1885 : }
1886 : }
1887 0 : ++IdenticalUnitCounter;
1888 0 : int IdenticalUnitRemaining = this->WrapperComp(CompNum).WrapperIdenticalObjectNum - IdenticalUnitCounter;
1889 0 : if (IdenticalUnitRemaining == 0) {
1890 0 : IdenticalUnitCounter = 0;
1891 : }
1892 0 : } else if (this->NumOfComp == this->ChillerHeaterNums) {
1893 0 : ++CompNum;
1894 : }
1895 :
1896 0 : if (CompNum > this->NumOfComp) {
1897 0 : ShowSevereError(state, format("CalcChillerModel: ChillerHeater=\"{}\", calculated component number too big.", this->Name));
1898 0 : ShowContinueError(state, format("Max number of components=[{}], indicated component number=[{}].", this->NumOfComp, CompNum));
1899 0 : ShowFatalError(state, "Program terminates due to preceding condition.");
1900 : }
1901 :
1902 : Real64 EvapMassFlowRate; // Actual evaporator mass flow rate
1903 : Real64 CondMassFlowRate; // Condenser mass flow rate
1904 :
1905 : // Check whether this chiller heater needs to run
1906 0 : if (EvaporatorLoad > 0.0 && (this->WrapperComp(CompNum).chSched->getCurrentVal() > 0.0)) {
1907 0 : IsLoadCoolRemaining = true;
1908 :
1909 : // Calculate density ratios to adjust mass flow rates from initialized ones
1910 : // Hot water temperature is known, but evaporator mass flow rates will be adjusted in the following "Do" loop
1911 0 : Real64 InitDensity = this->CWPlantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
1912 0 : Real64 EvapDensity = this->CWPlantLoc.loop->glycol->getDensity(state, EvapInletTemp, RoutineName);
1913 0 : Real64 CondDensity = this->CWPlantLoc.loop->glycol->getDensity(state, CondInletTemp, RoutineName);
1914 :
1915 : // Calculate density ratios to adjust mass flow rates from initialized ones
1916 :
1917 : // Fraction between standardized density and local density in the chilled water side
1918 0 : Real64 CHWDensityRatio = EvapDensity / InitDensity;
1919 :
1920 : // Fraction between standardized density and local density in the condenser side
1921 0 : Real64 GLHEDensityRatio = CondDensity / InitDensity;
1922 0 : CondMassFlowRate = this->ChillerHeater(ChillerHeaterNum).CondInletNode.MassFlowRateMaxAvail;
1923 0 : EvapMassFlowRate = this->ChillerHeater(ChillerHeaterNum).EvapInletNode.MassFlowRateMaxAvail;
1924 0 : EvapMassFlowRate *= CHWDensityRatio;
1925 0 : CondMassFlowRate *= GLHEDensityRatio;
1926 :
1927 : // Check available flows from plant and then adjust as necessary
1928 0 : if (CurAvailCHWMassFlowRate == 0) { // The very first chiller heater to operate
1929 0 : CurAvailCHWMassFlowRate = CHWInletMassFlowRate;
1930 0 : } else if (ChillerHeaterNum > 1) {
1931 0 : CurAvailCHWMassFlowRate -= this->ChillerHeater(ChillerHeaterNum - 1).EvapOutletNode.MassFlowRate;
1932 : }
1933 0 : EvapMassFlowRate = min(CurAvailCHWMassFlowRate, EvapMassFlowRate);
1934 : } else {
1935 0 : IsLoadCoolRemaining = false;
1936 0 : EvapMassFlowRate = 0.0;
1937 0 : CondMassFlowRate = 0.0;
1938 0 : CurrentMode = 0;
1939 : }
1940 :
1941 : // Chiller heater is on when cooling load for this chiller heater remains and chilled water available
1942 0 : if (IsLoadCoolRemaining && (EvapMassFlowRate > 0) && (this->WrapperComp(CompNum).chSched->getCurrentVal() > 0)) {
1943 : // Indicate current mode is cooling-only mode. Simultaneous clg/htg mode will be set later
1944 0 : CurrentMode = 1;
1945 :
1946 : // Assign proper performance curve information depending on the control mode
1947 : // Cooling curve is used only for cooling-only mode, and the others (Simultaneous and heating) read the heating curve
1948 0 : if (this->SimulClgDominant || this->SimulHtgDominant) {
1949 0 : this->ChillerHeater(ChillerHeaterNum).RefCap = this->ChillerHeater(ChillerHeaterNum).RefCapClgHtg;
1950 0 : this->ChillerHeater(ChillerHeaterNum).RefCOP = this->ChillerHeater(ChillerHeaterNum).RefCOPClgHtg;
1951 0 : this->ChillerHeater(ChillerHeaterNum).TempRefEvapOut = this->ChillerHeater(ChillerHeaterNum).TempRefEvapOutClgHtg;
1952 0 : this->ChillerHeater(ChillerHeaterNum).TempRefCondIn = this->ChillerHeater(ChillerHeaterNum).TempRefCondInClgHtg;
1953 0 : this->ChillerHeater(ChillerHeaterNum).TempRefCondOut = this->ChillerHeater(ChillerHeaterNum).TempRefCondOutClgHtg;
1954 0 : this->ChillerHeater(ChillerHeaterNum).OptPartLoadRat = this->ChillerHeater(ChillerHeaterNum).OptPartLoadRatClgHtg;
1955 0 : this->ChillerHeater(ChillerHeaterNum).CondMode = this->ChillerHeater(ChillerHeaterNum).CondModeHeating;
1956 0 : this->ChillerHeater(ChillerHeaterNum).ChillerCapFTIDX = this->ChillerHeater(ChillerHeaterNum).ChillerCapFTHeatingIDX;
1957 0 : this->ChillerHeater(ChillerHeaterNum).ChillerEIRFTIDX = this->ChillerHeater(ChillerHeaterNum).ChillerEIRFTHeatingIDX;
1958 0 : this->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRIDX = this->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRHeatingIDX;
1959 : } else {
1960 0 : this->ChillerHeater(ChillerHeaterNum).RefCap = this->ChillerHeater(ChillerHeaterNum).RefCapCooling;
1961 0 : this->ChillerHeater(ChillerHeaterNum).RefCOP = this->ChillerHeater(ChillerHeaterNum).RefCOPCooling;
1962 0 : this->ChillerHeater(ChillerHeaterNum).TempRefEvapOut = this->ChillerHeater(ChillerHeaterNum).TempRefEvapOutCooling;
1963 0 : this->ChillerHeater(ChillerHeaterNum).TempRefCondIn = this->ChillerHeater(ChillerHeaterNum).TempRefCondInCooling;
1964 0 : this->ChillerHeater(ChillerHeaterNum).TempRefCondOut = this->ChillerHeater(ChillerHeaterNum).TempRefCondOutCooling;
1965 0 : this->ChillerHeater(ChillerHeaterNum).OptPartLoadRat = this->ChillerHeater(ChillerHeaterNum).OptPartLoadRatCooling;
1966 0 : this->ChillerHeater(ChillerHeaterNum).CondMode = this->ChillerHeater(ChillerHeaterNum).CondModeCooling;
1967 0 : this->ChillerHeater(ChillerHeaterNum).ChillerCapFTIDX = this->ChillerHeater(ChillerHeaterNum).ChillerCapFTCoolingIDX;
1968 0 : this->ChillerHeater(ChillerHeaterNum).ChillerEIRFTIDX = this->ChillerHeater(ChillerHeaterNum).ChillerEIRFTCoolingIDX;
1969 0 : this->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRIDX = this->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRCoolingIDX;
1970 : }
1971 :
1972 : // Only used to read curve values
1973 0 : CondOutletTemp = this->ChillerHeater(ChillerHeaterNum).TempRefCondOutCooling;
1974 0 : Real64 CondTempforCurve = this->setChillerHeaterCondTemp(state, ChillerHeaterNum, CondInletTemp, CondOutletTemp);
1975 :
1976 : // Chiller reference capacity
1977 0 : Real64 ChillerRefCap = this->ChillerHeater(ChillerHeaterNum).RefCap;
1978 0 : Real64 ReferenceCOP = this->ChillerHeater(ChillerHeaterNum).RefCOP;
1979 0 : Real64 TempLowLimitEout = this->ChillerHeater(ChillerHeaterNum).TempLowLimitEvapOut;
1980 0 : Real64 EvapOutletTempSetPoint = this->ChillerHeater(ChillerHeaterNum).TempRefEvapOutCooling;
1981 :
1982 : // Calculate Chiller Capacity as a function of temperature and error check
1983 0 : state.dataPlantCentralGSHP->ChillerCapFT = this->calcChillerCapFT(state, ChillerHeaterNum, EvapOutletTempSetPoint, CondTempforCurve);
1984 :
1985 : // Calculate the specific heat of chilled water
1986 0 : Real64 Cp = this->CWPlantLoc.loop->glycol->getSpecificHeat(state, EvapInletTemp, RoutineName);
1987 :
1988 : // Calculate cooling load this chiller should meet and the other chillers are demanded
1989 0 : EvapOutletTempSetPoint = state.dataLoopNodes->Node(this->CWPlantLoc.loop->TempSetPointNodeNum).TempSetPoint;
1990 :
1991 : // Minimum capacity of the evaporator
1992 : Real64 EvaporatorCapMin =
1993 0 : this->ChillerHeater(ChillerHeaterNum).MinPartLoadRatCooling * this->ChillerHeater(ChillerHeaterNum).RefCapCooling;
1994 :
1995 : // Remaining cooling load the other chiller heaters should meet
1996 0 : Real64 CoolingLoadToMeet = min(this->ChillerHeater(ChillerHeaterNum).RefCapCooling, max(std::abs(EvaporatorLoad), EvaporatorCapMin));
1997 :
1998 : // Available chiller capacity as a function of temperature
1999 : // Chiller available capacity at current operating conditions [W]
2000 0 : Real64 AvailChillerCap = ChillerRefCap * state.dataPlantCentralGSHP->ChillerCapFT;
2001 :
2002 : Real64 PartLoadRat; // Operating part load ratio
2003 : Real64 MinPartLoadRat; // Min allowed operating fraction of full load
2004 : Real64 MaxPartLoadRat; // Max allowed operating fraction of full load
2005 :
2006 0 : Curve::GetCurveMinMaxValues(state, this->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRIDX, MinPartLoadRat, MaxPartLoadRat);
2007 :
2008 : // Set load this chiller heater should meet
2009 0 : QEvaporator = min(CoolingLoadToMeet, (AvailChillerCap * MaxPartLoadRat));
2010 0 : EvapOutletTemp = EvapOutletTempSetPoint;
2011 0 : Real64 EvapDeltaTemp = EvapInletTemp - EvapOutletTemp;
2012 :
2013 : // Calculate temperatures for constant flow and mass flow rates for variable flow
2014 0 : if (EvapMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
2015 0 : if (this->SimulHtgDominant) { // Evaporator operates at full capacity for heating
2016 0 : PartLoadRat = max(0.0, min((ChillerRefCap / AvailChillerCap), MaxPartLoadRat));
2017 0 : QEvaporator = AvailChillerCap * PartLoadRat;
2018 0 : EvapDeltaTemp = QEvaporator / EvapMassFlowRate / Cp;
2019 0 : EvapOutletTemp = EvapInletTemp - EvapDeltaTemp;
2020 : } else { // Cooling only mode or cooling dominant simultaneous htg/clg mode
2021 0 : if (this->VariableFlowCH) { // Variable flow
2022 0 : Real64 EvapMassFlowRateCalc = QEvaporator / EvapDeltaTemp / Cp;
2023 0 : if (EvapMassFlowRateCalc > EvapMassFlowRate) {
2024 0 : EvapMassFlowRateCalc = EvapMassFlowRate;
2025 0 : Real64 EvapDeltaTempCalc = QEvaporator / EvapMassFlowRate / Cp;
2026 0 : EvapOutletTemp = EvapInletTemp - EvapDeltaTempCalc;
2027 0 : if (EvapDeltaTempCalc > EvapDeltaTemp) {
2028 0 : QEvaporator = EvapMassFlowRate * Cp * EvapDeltaTemp;
2029 : }
2030 : }
2031 0 : EvapMassFlowRate = EvapMassFlowRateCalc;
2032 : } else { // Constant Flow
2033 0 : Real64 EvapOutletTempCalc = EvapInletTemp - EvapDeltaTemp;
2034 0 : if (EvapOutletTempCalc > EvapOutletTemp) { // Load to meet should be adjusted
2035 0 : EvapOutletTempCalc = EvapOutletTemp;
2036 0 : QEvaporator = EvapMassFlowRate * Cp * EvapDeltaTemp;
2037 : }
2038 0 : EvapOutletTemp = EvapOutletTempCalc;
2039 : } // End of flow control decision
2040 : } // End of operation mode
2041 : } else {
2042 0 : QEvaporator = 0.0;
2043 0 : EvapOutletTemp = EvapInletTemp;
2044 : }
2045 :
2046 : // Run evaporator checks and adjust outlet temp and QEvaporator if necessary
2047 0 : WrapperSpecs::checkEvapOutletTemp(
2048 : state, ChillerHeaterNum, EvapOutletTemp, TempLowLimitEout, EvapInletTemp, QEvaporator, EvapMassFlowRate, Cp);
2049 :
2050 : // Calculate part load once more since evaporator capacity might be modified
2051 0 : WrapperSpecs::calcPLRAndCyclingRatio(state, AvailChillerCap, PartLoadRat, MinPartLoadRat, MaxPartLoadRat, QEvaporator, FRAC);
2052 :
2053 : // Determine chiller compressor power and transfer heat calculation
2054 0 : state.dataPlantCentralGSHP->ChillerEIRFT =
2055 0 : max(0.0, Curve::CurveValue(state, this->ChillerHeater(ChillerHeaterNum).ChillerEIRFTIDX, EvapOutletTemp, CondTempforCurve));
2056 0 : state.dataPlantCentralGSHP->ChillerEIRFPLR =
2057 0 : max(0.0, Curve::CurveValue(state, this->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRIDX, PartLoadRat));
2058 :
2059 0 : if (ReferenceCOP <= 0.0) {
2060 0 : CHPower = 0.0;
2061 : } else {
2062 0 : CHPower =
2063 0 : (AvailChillerCap / ReferenceCOP) * state.dataPlantCentralGSHP->ChillerEIRFPLR * state.dataPlantCentralGSHP->ChillerEIRFT * FRAC;
2064 : }
2065 :
2066 0 : QCondenser =
2067 0 : CHPower * this->ChillerHeater(ChillerHeaterNum).OpenMotorEff + QEvaporator + state.dataPlantCentralGSHP->ChillerFalseLoadRate;
2068 :
2069 0 : if (CHPower == 0.0) {
2070 0 : ActualCOP = 0.0;
2071 : } else {
2072 0 : ActualCOP = (QEvaporator + state.dataPlantCentralGSHP->ChillerFalseLoadRate) / CHPower;
2073 : }
2074 :
2075 0 : if (CondMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
2076 0 : Cp = this->GLHEPlantLoc.loop->glycol->getSpecificHeat(state, CondInletTemp, RoutineNameElecEIRChiller);
2077 0 : CondOutletTemp = QCondenser / CondMassFlowRate / Cp + CondInletTemp;
2078 : } else {
2079 0 : ShowSevereError(
2080 0 : state, format("CalcChillerheaterModel: Condenser flow = 0, for Chillerheater={}", this->ChillerHeater(ChillerHeaterNum).Name));
2081 0 : ShowContinueErrorTimeStamp(state, "");
2082 : }
2083 :
2084 : // Determine load next chillers should meet
2085 0 : if (EvaporatorLoad < QEvaporator) {
2086 0 : EvaporatorLoad = 0.0; // No remaining load so the rest will be off
2087 : } else {
2088 0 : EvaporatorLoad -= QEvaporator;
2089 : }
2090 :
2091 : // Initialize reporting variable when this chiller doesn't need to operate
2092 0 : if (QEvaporator == 0.0) {
2093 0 : CurrentMode = 0;
2094 0 : state.dataPlantCentralGSHP->ChillerPartLoadRatio = 0.0;
2095 0 : state.dataPlantCentralGSHP->ChillerCyclingRatio = 0.0;
2096 0 : state.dataPlantCentralGSHP->ChillerFalseLoadRate = 0.0;
2097 0 : EvapMassFlowRate = 0.0;
2098 0 : CondMassFlowRate = 0.0;
2099 0 : CHPower = 0.0;
2100 0 : QCondenser = 0.0;
2101 0 : EvapOutletTemp = EvapInletTemp;
2102 0 : CondOutletTemp = CondInletTemp;
2103 0 : EvaporatorLoad = 0.0;
2104 : }
2105 :
2106 : } // End of calculation for cooling
2107 :
2108 : // Set variables to the arrays
2109 0 : this->ChillerHeater(ChillerHeaterNum).EvapOutletNode.MassFlowRate = EvapMassFlowRate;
2110 0 : this->ChillerHeater(ChillerHeaterNum).CondOutletNode.MassFlowRate = CondMassFlowRate;
2111 0 : this->ChillerHeater(ChillerHeaterNum).EvapOutletNode.Temp = EvapOutletTemp;
2112 0 : this->ChillerHeater(ChillerHeaterNum).EvapInletNode.Temp = EvapInletTemp;
2113 0 : this->ChillerHeater(ChillerHeaterNum).CondOutletNode.Temp = CondOutletTemp;
2114 0 : this->ChillerHeater(ChillerHeaterNum).CondInletNode.Temp = CondInletTemp;
2115 0 : this->ChillerHeater(ChillerHeaterNum).Report.CurrentMode = CurrentMode;
2116 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerPartLoadRatio = state.dataPlantCentralGSHP->ChillerPartLoadRatio;
2117 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerCyclingRatio = state.dataPlantCentralGSHP->ChillerCyclingRatio;
2118 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoadRate = state.dataPlantCentralGSHP->ChillerFalseLoadRate;
2119 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerCapFT = state.dataPlantCentralGSHP->ChillerCapFT;
2120 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFT = state.dataPlantCentralGSHP->ChillerEIRFT;
2121 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFPLR = state.dataPlantCentralGSHP->ChillerEIRFPLR;
2122 0 : this->ChillerHeater(ChillerHeaterNum).Report.CoolingPower = CHPower;
2123 0 : this->ChillerHeater(ChillerHeaterNum).Report.HeatingPower = 0.0;
2124 0 : this->ChillerHeater(ChillerHeaterNum).Report.QEvap = QEvaporator;
2125 0 : this->ChillerHeater(ChillerHeaterNum).Report.QCond = QCondenser;
2126 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapOutletTemp = EvapOutletTemp;
2127 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapInletTemp = EvapInletTemp;
2128 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondOutletTemp = CondOutletTemp;
2129 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondInletTemp = CondInletTemp;
2130 0 : this->ChillerHeater(ChillerHeaterNum).Report.Evapmdot = EvapMassFlowRate;
2131 0 : this->ChillerHeater(ChillerHeaterNum).Report.Condmdot = CondMassFlowRate;
2132 0 : this->ChillerHeater(ChillerHeaterNum).Report.ActualCOP = ActualCOP;
2133 :
2134 0 : if (this->SimulClgDominant || this->SimulHtgDominant) { // Store for using these cooling side data in the hot water loop
2135 0 : this->ChillerHeater(ChillerHeaterNum).Report.CurrentMode = CurrentMode;
2136 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerPartLoadRatioSimul = state.dataPlantCentralGSHP->ChillerPartLoadRatio;
2137 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerCyclingRatioSimul = state.dataPlantCentralGSHP->ChillerCyclingRatio;
2138 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoadRateSimul = state.dataPlantCentralGSHP->ChillerFalseLoadRate;
2139 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerCapFTSimul = state.dataPlantCentralGSHP->ChillerCapFT;
2140 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFTSimul = state.dataPlantCentralGSHP->ChillerEIRFT;
2141 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFPLRSimul = state.dataPlantCentralGSHP->ChillerEIRFPLR;
2142 0 : this->ChillerHeater(ChillerHeaterNum).Report.CoolingPowerSimul = CHPower;
2143 0 : this->ChillerHeater(ChillerHeaterNum).Report.QEvapSimul = QEvaporator;
2144 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapOutletTempSimul = EvapOutletTemp;
2145 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapInletTempSimul = EvapInletTemp;
2146 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapmdotSimul = EvapMassFlowRate;
2147 0 : if (this->SimulClgDominant) {
2148 0 : this->ChillerHeater(ChillerHeaterNum).Report.QCondSimul = QCondenser;
2149 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondOutletTempSimul = CondOutletTemp;
2150 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondInletTempSimul = CondInletTemp;
2151 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondmdotSimul = CondMassFlowRate;
2152 : }
2153 : }
2154 : }
2155 0 : }
2156 :
2157 0 : void WrapperSpecs::CalcChillerHeaterModel(EnergyPlusData &state)
2158 : {
2159 : // SUBROUTINE INFORMATION:
2160 : // AUTHOR Daeho Kang, PNNL
2161 : // DATE WRITTEN Feb 2013
2162 : // MODIFIED na
2163 : // RE-ENGINEERED na
2164 :
2165 : // PURPOSE OF THIS SUBROUTINE:
2166 : // Simulate a ChillerHeaterPerformance:Electric:EIR using curve fit
2167 :
2168 : // METHODOLOGY EMPLOYED:
2169 : // Use empirical curve fits to model performance at off-reference conditions
2170 :
2171 : // REFERENCES:
2172 : // 1. DOE-2 Engineers Manual, Version 2.1A, November 1982, LBL-11353
2173 :
2174 : static constexpr std::string_view RoutineName("CalcChillerHeaterModel");
2175 :
2176 : bool IsLoadHeatRemaining; // Ture if heating load remains for this chiller heater
2177 0 : bool NextCompIndicator(false); // Component indicator when identical chiller heaters exist
2178 0 : int CompNum(0); // Component number
2179 0 : int IdenticalUnitCounter = 0; // Pointer to count number of identical unit passed
2180 : int IdenticalUnitRemaining; // Pointer to count number of identical unit available for a component
2181 0 : Real64 CondenserLoad(0.0); // Remaining heating load that this wrapper should meet
2182 0 : Real64 CurAvailHWMassFlowRate(0.0); // Maximum available hot water mass within the wrapper bank
2183 :
2184 0 : CondenserLoad = this->WrapperHeatingLoad;
2185 0 : Real64 HWInletMassFlowRate = state.dataLoopNodes->Node(this->HWInletNodeNum).MassFlowRate;
2186 :
2187 0 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
2188 :
2189 : // Set module level inlet and outlet nodes and initialize other local variables
2190 0 : int CurrentMode = 0;
2191 0 : state.dataPlantCentralGSHP->ChillerPartLoadRatio = 0.0;
2192 0 : state.dataPlantCentralGSHP->ChillerCyclingRatio = 0.0;
2193 0 : state.dataPlantCentralGSHP->ChillerFalseLoadRate = 0.0;
2194 0 : Real64 CHPower = 0.0;
2195 0 : Real64 QCondenser = 0.0;
2196 0 : Real64 QEvaporator = 0.0;
2197 0 : Real64 FRAC = 1.0;
2198 0 : Real64 CondDeltaTemp = 0.0;
2199 0 : Real64 CoolingPower = 0.0;
2200 0 : Real64 ActualCOP = 0.0;
2201 0 : Real64 EvapInletTemp = state.dataLoopNodes->Node(this->GLHEInletNodeNum).Temp;
2202 0 : Real64 CondInletTemp = state.dataLoopNodes->Node(this->HWInletNodeNum).Temp;
2203 0 : Real64 EvapOutletTemp = EvapInletTemp;
2204 0 : Real64 CondOutletTemp = CondInletTemp;
2205 :
2206 : // Find proper schedule values
2207 0 : if (this->NumOfComp != this->ChillerHeaterNums) { // Identical units exist
2208 0 : if (ChillerHeaterNum == 1) {
2209 0 : IdenticalUnitCounter = 0;
2210 0 : NextCompIndicator = false;
2211 0 : CompNum = ChillerHeaterNum;
2212 : }
2213 0 : if (NextCompIndicator) {
2214 0 : ++CompNum;
2215 : }
2216 0 : if (CompNum == 1) {
2217 0 : if (ChillerHeaterNum != this->WrapperComp(CompNum).WrapperIdenticalObjectNum) {
2218 0 : NextCompIndicator = false;
2219 0 : } else if (ChillerHeaterNum == this->WrapperComp(CompNum).WrapperIdenticalObjectNum) {
2220 0 : NextCompIndicator = true;
2221 : }
2222 0 : } else if (CompNum > 1) {
2223 0 : if ((ChillerHeaterNum - ((ChillerHeaterNum - 1) - IdenticalUnitCounter)) != this->WrapperComp(CompNum).WrapperIdenticalObjectNum) {
2224 0 : NextCompIndicator = false;
2225 0 : } else if ((ChillerHeaterNum - ((ChillerHeaterNum - 1) - IdenticalUnitCounter)) ==
2226 0 : this->WrapperComp(CompNum).WrapperIdenticalObjectNum) {
2227 0 : NextCompIndicator = true;
2228 : }
2229 : }
2230 0 : ++IdenticalUnitCounter;
2231 0 : IdenticalUnitRemaining = this->WrapperComp(CompNum).WrapperIdenticalObjectNum - IdenticalUnitCounter;
2232 0 : if (IdenticalUnitRemaining == 0) {
2233 0 : IdenticalUnitCounter = 0;
2234 : }
2235 0 : } else if (this->NumOfComp == this->ChillerHeaterNums) {
2236 0 : ++CompNum;
2237 : }
2238 :
2239 : Real64 CondMassFlowRate; // Condenser mass flow rate through this chiller heater
2240 : Real64 EvapMassFlowRate; // Evaporator mass flow rate through this chiller heater
2241 :
2242 : // Check to see if this chiller heater needs to run
2243 0 : if (CondenserLoad > 0.0 && (this->WrapperComp(CompNum).chSched->getCurrentVal() > 0)) {
2244 0 : IsLoadHeatRemaining = true;
2245 :
2246 : // Calculate density ratios to adjust mass flow rates from initialized ones
2247 : // Hot water temperature is known, but condenser mass flow rates will be adjusted in the following "Do" loop
2248 0 : Real64 InitDensity = this->CWPlantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
2249 0 : Real64 EvapDensity = this->CWPlantLoc.loop->glycol->getDensity(state, EvapInletTemp, RoutineName);
2250 0 : Real64 CondDensity = this->CWPlantLoc.loop->glycol->getDensity(state, CondInletTemp, RoutineName);
2251 :
2252 : // Calculate density ratios to adjust mass flow rates from initialized ones
2253 0 : Real64 HWDensityRatio = CondDensity / InitDensity;
2254 0 : Real64 GLHEDensityRatio = EvapDensity / InitDensity;
2255 0 : EvapMassFlowRate = this->ChillerHeater(ChillerHeaterNum).EvapInletNode.MassFlowRateMaxAvail;
2256 0 : CondMassFlowRate = this->ChillerHeater(ChillerHeaterNum).CondInletNode.MassFlowRateMaxAvail;
2257 0 : EvapMassFlowRate *= GLHEDensityRatio;
2258 0 : CondMassFlowRate *= HWDensityRatio;
2259 :
2260 : // Check flows from plant to adjust as necessary
2261 0 : if (CurAvailHWMassFlowRate == 0) { // First chiller heater which is on
2262 0 : CurAvailHWMassFlowRate = HWInletMassFlowRate;
2263 0 : } else if (ChillerHeaterNum > 1) {
2264 0 : CurAvailHWMassFlowRate -= this->ChillerHeater(ChillerHeaterNum - 1).CondOutletNode.MassFlowRate;
2265 : }
2266 0 : CondMassFlowRate = min(CurAvailHWMassFlowRate, CondMassFlowRate);
2267 :
2268 : // It is not enforced to be the smaller of CH max temperature and plant temp setpoint.
2269 : // Hot water temperatures at the individual CHs' outlet may be greater than plant setpoint temp,
2270 : // but should be lower than the CHs max temp
2271 0 : CondOutletTemp = this->ChillerHeater(ChillerHeaterNum).TempRefCondOutClgHtg;
2272 0 : CondDeltaTemp = CondOutletTemp - CondInletTemp;
2273 :
2274 0 : if (CondDeltaTemp < 0.0) { // Hot water temperature is greater than the maximum
2275 0 : if (this->ChillerHeater(ChillerHeaterNum).ChillerEIRRefTempErrorIndex == 0) {
2276 0 : ShowSevereMessage(state,
2277 0 : format("CalcChillerHeaterModel: ChillerHeaterPerformance:Electric:EIR=\"{}\", DeltaTemp < 0",
2278 0 : this->ChillerHeater(ChillerHeaterNum).Name));
2279 0 : ShowContinueError(
2280 0 : state, format(" Reference Simultaneous Cooling-Heating Mode Leaving Condenser Water Temperature [{:.1R}]", CondOutletTemp));
2281 0 : ShowContinueError(state, format("is below condenser inlet temperature of [{:.1R}].", CondInletTemp));
2282 0 : ShowContinueErrorTimeStamp(state, "");
2283 0 : ShowContinueError(state, " Reset reference temperature to one greater than the inlet temperature ");
2284 : }
2285 0 : ShowRecurringSevereErrorAtEnd(state,
2286 0 : "ChillerHeaterPerformance:Electric:EIR=\"" + this->ChillerHeater(ChillerHeaterNum).Name +
2287 : "\": Reference temperature problems continue.",
2288 0 : this->ChillerHeater(ChillerHeaterNum).ChillerEIRRefTempErrorIndex,
2289 : CondDeltaTemp,
2290 : CondDeltaTemp,
2291 : _,
2292 : "deltaC",
2293 : "deltaC");
2294 0 : QCondenser = 0.0;
2295 0 : IsLoadHeatRemaining = false;
2296 : }
2297 :
2298 0 : if (ChillerHeaterNum > 1) {
2299 : // Operation mode needs to be set in a simultaneous clg/htg mode
2300 : // Always off even heating load remains if this CH is assumed to be off in the loop 1
2301 0 : if (this->SimulClgDominant) {
2302 0 : if (this->ChillerHeater(ChillerHeaterNum).Report.QEvapSimul == 0.0) {
2303 0 : CurrentMode = 0;
2304 0 : IsLoadHeatRemaining = false;
2305 : } else { // Heat recovery
2306 0 : CurrentMode = 3;
2307 : }
2308 : }
2309 : } // End of simulataneous clg/htg mode detemination
2310 :
2311 : } else { // chiller heater is off
2312 0 : IsLoadHeatRemaining = false;
2313 0 : CondMassFlowRate = 0.0;
2314 0 : EvapMassFlowRate = 0.0;
2315 0 : CurrentMode = 0;
2316 0 : if (this->SimulClgDominant) {
2317 0 : if (this->ChillerHeater(ChillerHeaterNum).Report.QEvapSimul > 0.0) {
2318 0 : CurrentMode = 4; // Simultaneous cooling dominant mode: 4
2319 : }
2320 : } // End of mode determination
2321 : } // End of system operation determinatoin
2322 :
2323 0 : if (IsLoadHeatRemaining && CondMassFlowRate > 0.0 && (this->WrapperComp(CompNum).chSched->getCurrentVal() > 0)) { // System is on
2324 : // Operation mode
2325 0 : if (this->SimulHtgDominant) {
2326 0 : if (this->ChillerHeater(ChillerHeaterNum).Report.QEvapSimul == 0.0) {
2327 0 : CurrentMode = 5; // No cooling necessary // Why is this not an enum?
2328 : } else { // Heat recovery mode. Both chilled water and hot water loops are connected. No condenser flow.
2329 0 : CurrentMode = 3;
2330 : }
2331 : }
2332 :
2333 : // Mode 3 and 5 use cooling side data stored from the chilled water loop
2334 : // Mode 4 uses all data from the chilled water loop due to no heating demand
2335 : // Fix for Defect #10065: When the heating load is dominant and the Current Mode is 3,
2336 : // simulation must go through the "heating" side to properly update the power consumption.
2337 : // Otherwise, the power consumption could come back zero for heating and cooling.
2338 0 : if (this->SimulClgDominant || (CurrentMode == 3 && !this->SimulHtgDominant)) {
2339 0 : CurrentMode = 3;
2340 0 : QCondenser = this->ChillerHeater(ChillerHeaterNum).Report.QCondSimul;
2341 0 : this->adjustChillerHeaterCondFlowTemp(state, QCondenser, CondMassFlowRate, CondOutletTemp, CondInletTemp, CondDeltaTemp);
2342 : } else { // Either Mode 2 or 3 (heating dominant) or 5
2343 0 : if (this->SimulHtgDominant) {
2344 0 : CurrentMode = 5;
2345 : } else {
2346 0 : CurrentMode = 2;
2347 : }
2348 :
2349 0 : state.dataPlantCentralGSHP->ChillerCapFT = 0.0;
2350 0 : state.dataPlantCentralGSHP->ChillerEIRFT = 0.0;
2351 0 : state.dataPlantCentralGSHP->ChillerEIRFPLR = 0.0;
2352 :
2353 : // Assign curve values to local data array
2354 0 : this->ChillerHeater(ChillerHeaterNum).RefCap = this->ChillerHeater(ChillerHeaterNum).RefCapClgHtg;
2355 0 : this->ChillerHeater(ChillerHeaterNum).RefCOP = this->ChillerHeater(ChillerHeaterNum).RefCOPClgHtg;
2356 0 : this->ChillerHeater(ChillerHeaterNum).TempRefEvapOut = this->ChillerHeater(ChillerHeaterNum).TempRefEvapOutClgHtg;
2357 0 : this->ChillerHeater(ChillerHeaterNum).TempRefCondOut = this->ChillerHeater(ChillerHeaterNum).TempRefCondOutClgHtg;
2358 0 : this->ChillerHeater(ChillerHeaterNum).OptPartLoadRat = this->ChillerHeater(ChillerHeaterNum).OptPartLoadRatClgHtg;
2359 0 : this->ChillerHeater(ChillerHeaterNum).CondMode = this->ChillerHeater(ChillerHeaterNum).CondModeHeating;
2360 0 : this->ChillerHeater(ChillerHeaterNum).ChillerCapFTIDX = this->ChillerHeater(ChillerHeaterNum).ChillerCapFTHeatingIDX;
2361 0 : this->ChillerHeater(ChillerHeaterNum).ChillerEIRFTIDX = this->ChillerHeater(ChillerHeaterNum).ChillerEIRFTHeatingIDX;
2362 0 : this->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRIDX = this->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRHeatingIDX;
2363 :
2364 : // Reference condenser temperature for the performance curve reading: set to entering or leaving condenser temperature based on user
2365 : // input
2366 0 : Real64 CondTempforCurve = this->setChillerHeaterCondTemp(
2367 0 : state, ChillerHeaterNum, CondInletTemp, this->ChillerHeater(ChillerHeaterNum).TempRefCondOutClgHtg);
2368 :
2369 0 : Real64 ChillerRefCap = this->ChillerHeater(ChillerHeaterNum).RefCap;
2370 0 : Real64 ReferenceCOP = this->ChillerHeater(ChillerHeaterNum).RefCOP;
2371 0 : EvapOutletTemp = this->ChillerHeater(ChillerHeaterNum).TempRefEvapOutClgHtg;
2372 0 : Real64 TempLowLimitEout = this->ChillerHeater(ChillerHeaterNum).TempLowLimitEvapOut;
2373 0 : Real64 EvapOutletTempSetPoint = this->ChillerHeater(ChillerHeaterNum).TempRefEvapOutClgHtg;
2374 :
2375 : // Calculate Chiller Capacity as a function of temperature and error check
2376 0 : state.dataPlantCentralGSHP->ChillerCapFT = this->calcChillerCapFT(state, ChillerHeaterNum, EvapOutletTempSetPoint, CondTempforCurve);
2377 :
2378 : // Available chiller capacity as a function of temperature
2379 0 : Real64 AvailChillerCap = ChillerRefCap * state.dataPlantCentralGSHP->ChillerCapFT;
2380 :
2381 : Real64 PartLoadRat; // Operating part load ratio
2382 : Real64 MinPartLoadRat; // Min allowed operating fraction of full load
2383 : Real64 MaxPartLoadRat; // Max allowed operating fraction of full load
2384 0 : Curve::GetCurveMinMaxValues(state, this->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRIDX, MinPartLoadRat, MaxPartLoadRat);
2385 :
2386 : // Part load ratio based on reference capacity and available chiller capacity
2387 0 : if (AvailChillerCap > 0) {
2388 0 : PartLoadRat = max(0.0, min((ChillerRefCap / AvailChillerCap), MaxPartLoadRat));
2389 : } else {
2390 0 : PartLoadRat = 0.0;
2391 : }
2392 :
2393 : Real64 Cp =
2394 0 : this->HWPlantLoc.loop->glycol->getSpecificHeat(state, this->ChillerHeater(ChillerHeaterNum).EvapInletNode.Temp, RoutineName);
2395 :
2396 : // Calculate evaporator heat transfer
2397 0 : if (EvapMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
2398 0 : QEvaporator = AvailChillerCap * PartLoadRat;
2399 0 : Real64 EvapDeltaTemp = QEvaporator / EvapMassFlowRate / Cp;
2400 0 : EvapOutletTemp = EvapInletTemp - EvapDeltaTemp;
2401 : }
2402 :
2403 : // Run evaporator checks and adjust outlet temp and QEvaporator if necessary
2404 0 : WrapperSpecs::checkEvapOutletTemp(state,
2405 : ChillerHeaterNum,
2406 : EvapOutletTemp,
2407 : TempLowLimitEout,
2408 0 : this->ChillerHeater(ChillerHeaterNum).EvapInletNode.Temp,
2409 : QEvaporator,
2410 : EvapMassFlowRate,
2411 : Cp);
2412 :
2413 0 : WrapperSpecs::calcPLRAndCyclingRatio(state, AvailChillerCap, PartLoadRat, MinPartLoadRat, MaxPartLoadRat, QEvaporator, FRAC);
2414 :
2415 0 : state.dataPlantCentralGSHP->ChillerEIRFT =
2416 0 : max(0.0, Curve::CurveValue(state, this->ChillerHeater(ChillerHeaterNum).ChillerEIRFTIDX, EvapOutletTemp, CondTempforCurve));
2417 0 : state.dataPlantCentralGSHP->ChillerEIRFPLR =
2418 0 : max(0.0, Curve::CurveValue(state, this->ChillerHeater(ChillerHeaterNum).ChillerEIRFPLRIDX, PartLoadRat));
2419 0 : CHPower =
2420 0 : (AvailChillerCap / ReferenceCOP) * state.dataPlantCentralGSHP->ChillerEIRFPLR * state.dataPlantCentralGSHP->ChillerEIRFT * FRAC;
2421 :
2422 0 : if (CHPower <= 0.0) {
2423 0 : ActualCOP = 0.0;
2424 : } else {
2425 0 : ActualCOP = (QEvaporator + state.dataPlantCentralGSHP->ChillerFalseLoadRate) / CHPower;
2426 : }
2427 :
2428 0 : QCondenser =
2429 0 : CHPower * this->ChillerHeater(ChillerHeaterNum).OpenMotorEff + QEvaporator + state.dataPlantCentralGSHP->ChillerFalseLoadRate;
2430 0 : Real64 qCondenserFullLoad = QCondenser;
2431 :
2432 : // Determine heating load for this heater and pass the remaining load to the next chiller heater
2433 0 : Real64 CondenserCapMin = QCondenser * MinPartLoadRat;
2434 0 : Real64 HeatingLoadToMeet = min(QCondenser, max(std::abs(CondenserLoad), CondenserCapMin));
2435 :
2436 : // Set load this chiller heater should meet and temperatures given
2437 0 : QCondenser = min(HeatingLoadToMeet, QCondenser);
2438 :
2439 : // Calculate outlet temperature for constant flow and mass flow rate for variable flow
2440 : // Limit mass flow rate for this chiller heater to the available mass at given temperature conditions
2441 : // when mass flow rate calculated to meet the load is greater than the maximum available
2442 : // then recalculate heating load this chiller heater can meet
2443 0 : if (CurrentMode == 2 || this->SimulHtgDominant) {
2444 0 : if (CondMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance && CondDeltaTemp > 0.0) {
2445 0 : this->adjustChillerHeaterCondFlowTemp(state, QCondenser, CondMassFlowRate, CondOutletTemp, CondInletTemp, CondDeltaTemp);
2446 0 : if (qCondenserFullLoad > 0.0) {
2447 0 : Real64 constexpr diffTolerance = 0.0001;
2448 0 : if (((qCondenserFullLoad - QCondenser) / qCondenserFullLoad) > diffTolerance) {
2449 : // QCondenser was reduced, so reduce evaporator side quantities by a factor of the condenser based PLR
2450 0 : PartLoadRat = max(MinPartLoadRat, min((QCondenser / qCondenserFullLoad), MaxPartLoadRat));
2451 0 : QCondenser = PartLoadRat * qCondenserFullLoad;
2452 0 : this->adjustChillerHeaterCondFlowTemp(
2453 : state, QCondenser, CondMassFlowRate, CondOutletTemp, CondInletTemp, CondDeltaTemp);
2454 : // In most situations here, QCondenser will not be reduced here, but it has to be taken into account. This will
2455 : // potentially violate the minPLR but this will keep the solution simple for now.
2456 : // So, basically multiply all terms in the energy balance by the same factor to maintain the energy balance.
2457 0 : Real64 modifiedPLR = QCondenser / qCondenserFullLoad;
2458 0 : QEvaporator *= modifiedPLR;
2459 0 : CHPower *= modifiedPLR;
2460 0 : PartLoadRat = modifiedPLR;
2461 0 : state.dataPlantCentralGSHP->ChillerFalseLoadRate *= modifiedPLR;
2462 : // Now re-adjust things on the evaporator side to get the correct flows/temperatures
2463 0 : this->adjustChillerHeaterEvapFlowTemp(state, QEvaporator, EvapMassFlowRate, EvapOutletTemp, EvapInletTemp);
2464 : }
2465 : }
2466 0 : } else {
2467 0 : QCondenser = 0.0;
2468 0 : CondOutletTemp = CondInletTemp;
2469 : }
2470 0 : state.dataPlantCentralGSHP->ChillerPartLoadRatio = PartLoadRat;
2471 : }
2472 :
2473 : } // End of calculation depending on the modes
2474 :
2475 : // Determine load next chiller heater meets
2476 0 : if (CondenserLoad < QCondenser) { // Heating load is met by this chiller heater
2477 0 : CondenserLoad = 0.0;
2478 : } else {
2479 0 : CondenserLoad -= QCondenser;
2480 : }
2481 :
2482 0 : if (QCondenser == 0.0) {
2483 0 : CurrentMode = 0;
2484 0 : state.dataPlantCentralGSHP->ChillerPartLoadRatio = 0.0;
2485 0 : state.dataPlantCentralGSHP->ChillerCyclingRatio = 0.0;
2486 0 : state.dataPlantCentralGSHP->ChillerFalseLoadRate = 0.0;
2487 0 : EvapMassFlowRate = 0.0;
2488 0 : CondMassFlowRate = 0.0;
2489 0 : CHPower = 0.0;
2490 0 : QEvaporator = 0.0;
2491 0 : EvapOutletTemp = EvapInletTemp;
2492 0 : CondOutletTemp = CondInletTemp;
2493 0 : CondenserLoad = 0.0;
2494 : }
2495 :
2496 : // Heat recovery or cooling dominant modes need to use the evaporator side information
2497 0 : if (CurrentMode == 3 || CurrentMode == 4) {
2498 0 : state.dataPlantCentralGSHP->ChillerPartLoadRatio = this->ChillerHeater(ChillerHeaterNum).Report.ChillerPartLoadRatioSimul;
2499 0 : state.dataPlantCentralGSHP->ChillerCyclingRatio = this->ChillerHeater(ChillerHeaterNum).Report.ChillerCyclingRatioSimul;
2500 0 : state.dataPlantCentralGSHP->ChillerFalseLoadRate = this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoadRateSimul;
2501 0 : state.dataPlantCentralGSHP->ChillerCapFT = this->ChillerHeater(ChillerHeaterNum).Report.ChillerCapFTSimul;
2502 0 : state.dataPlantCentralGSHP->ChillerEIRFT = this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFTSimul;
2503 0 : state.dataPlantCentralGSHP->ChillerEIRFPLR = this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFPLRSimul;
2504 0 : QEvaporator = this->ChillerHeater(ChillerHeaterNum).Report.QEvapSimul;
2505 0 : EvapOutletTemp = this->ChillerHeater(ChillerHeaterNum).Report.EvapOutletTempSimul;
2506 0 : EvapInletTemp = this->ChillerHeater(ChillerHeaterNum).Report.EvapInletTempSimul;
2507 0 : EvapMassFlowRate = this->ChillerHeater(ChillerHeaterNum).Report.EvapmdotSimul;
2508 0 : if (this->SimulClgDominant) {
2509 0 : CHPower = this->ChillerHeater(ChillerHeaterNum).Report.CoolingPowerSimul;
2510 0 : this->ChillerHeater(ChillerHeaterNum).Report.HeatingPower = 0.0;
2511 : }
2512 : }
2513 : }
2514 :
2515 : // Check if it is mode 4, then skip binding local variables
2516 0 : if (CurrentMode == 4) {
2517 0 : this->ChillerHeater(ChillerHeaterNum).Report.CurrentMode = CurrentMode;
2518 : } else {
2519 0 : this->ChillerHeater(ChillerHeaterNum).EvapOutletNode.MassFlowRate = EvapMassFlowRate;
2520 0 : this->ChillerHeater(ChillerHeaterNum).CondOutletNode.MassFlowRate = CondMassFlowRate;
2521 0 : this->ChillerHeater(ChillerHeaterNum).EvapOutletNode.Temp = EvapOutletTemp;
2522 0 : this->ChillerHeater(ChillerHeaterNum).EvapInletNode.Temp = EvapInletTemp;
2523 0 : this->ChillerHeater(ChillerHeaterNum).CondOutletNode.Temp = CondOutletTemp;
2524 0 : this->ChillerHeater(ChillerHeaterNum).CondInletNode.Temp = CondInletTemp;
2525 0 : this->ChillerHeater(ChillerHeaterNum).Report.CurrentMode = CurrentMode;
2526 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerPartLoadRatio = state.dataPlantCentralGSHP->ChillerPartLoadRatio;
2527 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerCyclingRatio = state.dataPlantCentralGSHP->ChillerCyclingRatio;
2528 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoadRate = state.dataPlantCentralGSHP->ChillerFalseLoadRate;
2529 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerCapFT = state.dataPlantCentralGSHP->ChillerCapFT;
2530 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFT = state.dataPlantCentralGSHP->ChillerEIRFT;
2531 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFPLR = state.dataPlantCentralGSHP->ChillerEIRFPLR;
2532 0 : this->ChillerHeater(ChillerHeaterNum).Report.CoolingPower = CoolingPower;
2533 0 : this->ChillerHeater(ChillerHeaterNum).Report.HeatingPower = CHPower;
2534 0 : this->ChillerHeater(ChillerHeaterNum).Report.QEvap = QEvaporator;
2535 0 : this->ChillerHeater(ChillerHeaterNum).Report.QCond = QCondenser;
2536 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapOutletTemp = EvapOutletTemp;
2537 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapInletTemp = EvapInletTemp;
2538 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondOutletTemp = CondOutletTemp;
2539 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondInletTemp = CondInletTemp;
2540 0 : this->ChillerHeater(ChillerHeaterNum).Report.Evapmdot = EvapMassFlowRate;
2541 0 : this->ChillerHeater(ChillerHeaterNum).Report.Condmdot = CondMassFlowRate;
2542 0 : this->ChillerHeater(ChillerHeaterNum).Report.ActualCOP = ActualCOP;
2543 : }
2544 : }
2545 0 : }
2546 :
2547 4 : void WrapperSpecs::adjustChillerHeaterCondFlowTemp(EnergyPlusData &state,
2548 : Real64 &QCondenser,
2549 : Real64 &CondMassFlowRate,
2550 : Real64 &CondOutletTemp,
2551 : Real64 const CondInletTemp,
2552 : Real64 const CondDeltaTemp)
2553 : {
2554 : // Based on whether this is variable or constant flow, adjust either flow or outlet temperature and also the load
2555 : static constexpr std::string_view RoutineName("adjustChillerHeaterCondFlowTemp");
2556 4 : Real64 Cp = this->HWPlantLoc.loop->glycol->getSpecificHeat(state, CondInletTemp, RoutineName);
2557 :
2558 4 : if (this->VariableFlowCH) { // Variable Flow (adjust flow and condenser load as needed)
2559 2 : Real64 CondMassFlowRateCalc = QCondenser / CondDeltaTemp / Cp;
2560 2 : if (CondMassFlowRateCalc > CondMassFlowRate) {
2561 1 : CondMassFlowRateCalc = CondMassFlowRate;
2562 1 : Real64 CondDeltaTempCalc = QCondenser / CondMassFlowRate / Cp;
2563 1 : if (CondDeltaTempCalc > CondDeltaTemp) { // Load to meet should be adjusted
2564 1 : QCondenser = CondMassFlowRate * Cp * CondDeltaTemp;
2565 : }
2566 : }
2567 2 : CondMassFlowRate = CondMassFlowRateCalc;
2568 : } else { // Constant Flow (adjust outlet temperature and condenser load as needed)
2569 2 : Real64 CondDeltaTempCalc = QCondenser / CondMassFlowRate / Cp;
2570 2 : Real64 CondOutletTempCalc = CondDeltaTempCalc + CondInletTemp;
2571 2 : if (CondOutletTempCalc > CondOutletTemp) { // Load to meet should be adjusted
2572 1 : CondOutletTempCalc = CondOutletTemp;
2573 1 : QCondenser = CondMassFlowRate * Cp * CondDeltaTemp;
2574 : }
2575 2 : CondOutletTemp = CondOutletTempCalc;
2576 : }
2577 4 : }
2578 :
2579 5 : void WrapperSpecs::adjustChillerHeaterEvapFlowTemp(
2580 : EnergyPlusData &state, Real64 const qEvaporator, Real64 &evapMassFlowRate, Real64 &evapOutletTemp, Real64 const evapInletTemp)
2581 : {
2582 : // Adjust flow and outlet temperature for the evaporator side without modifying the heat transfer rate
2583 5 : Real64 constexpr lowLoad = 0.001;
2584 : static constexpr std::string_view routineName("adjustChillerHeaterEvapFlowTemp");
2585 5 : Real64 Cp = this->HWPlantLoc.loop->glycol->getSpecificHeat(state, evapInletTemp, routineName);
2586 5 : Real64 evapDeltaTemp = evapInletTemp - evapOutletTemp;
2587 :
2588 5 : if ((qEvaporator < lowLoad) || (evapDeltaTemp <= 0.0)) {
2589 2 : evapMassFlowRate = 0.0;
2590 2 : evapOutletTemp = evapInletTemp;
2591 : } else {
2592 3 : if (this->VariableFlowCH) { // for variable flow, adjust flow if higher than max value passed in
2593 2 : Real64 evapMassFlowRateCalc = qEvaporator / evapDeltaTemp / Cp;
2594 2 : if (evapMassFlowRateCalc > evapMassFlowRate) {
2595 1 : evapMassFlowRateCalc = evapMassFlowRate;
2596 : }
2597 2 : evapMassFlowRate = evapMassFlowRateCalc;
2598 : }
2599 : // Adjust temperature for either flow type to maintain agreement with qEvaporator
2600 3 : evapDeltaTemp = qEvaporator / evapMassFlowRate / Cp;
2601 3 : evapOutletTemp = evapInletTemp - evapDeltaTemp;
2602 : }
2603 5 : }
2604 :
2605 2 : Real64 WrapperSpecs::setChillerHeaterCondTemp([[maybe_unused]] EnergyPlusData &state,
2606 : int const numChillerHeater,
2607 : Real64 const condEnteringTemp,
2608 : Real64 const condLeavingTemp)
2609 : {
2610 : Real64 setChillerHeaterCondTemp;
2611 2 : if (this->ChillerHeater(numChillerHeater).CondMode == CondenserModeTemperature::EnteringCondenser) {
2612 1 : setChillerHeaterCondTemp = condEnteringTemp;
2613 : } else { // by default, if not EnteringCondenser, then this can only be LeavingCondenser
2614 1 : setChillerHeaterCondTemp = condLeavingTemp;
2615 : }
2616 2 : return setChillerHeaterCondTemp;
2617 : }
2618 :
2619 0 : Real64 WrapperSpecs::calcChillerCapFT(EnergyPlusData &state, int const numChillerHeater, Real64 const evapOutletTemp, Real64 const condTemp)
2620 : {
2621 : // Calculate the chiller capacity as a function of temperature
2622 0 : Real64 chillCapFT = Curve::CurveValue(state, this->ChillerHeater(numChillerHeater).ChillerCapFTIDX, evapOutletTemp, condTemp);
2623 :
2624 : // Tracks errors for when the capacity is calculated as less than zero
2625 0 : if (chillCapFT < 0) {
2626 0 : if (this->ChillerHeater(numChillerHeater).ChillerCapFTError < 1 && !state.dataGlobal->WarmupFlag) {
2627 0 : ++this->ChillerHeater(numChillerHeater).ChillerCapFTError;
2628 0 : ShowWarningError(state, format("ChillerHeaterPerformance:Electric:EIR \"{}\":", this->ChillerHeater(numChillerHeater).Name));
2629 0 : ShowContinueError(state, format(" ChillerHeater Capacity as a Function of Temperature curve output is negative ({:.3R}).", chillCapFT));
2630 0 : ShowContinueError(state,
2631 0 : format(" Negative value occurs using an Evaporator Outlet Temp of {:.1R} and a Condenser Inlet Temp of {:.1R}.",
2632 : evapOutletTemp,
2633 : condTemp));
2634 0 : ShowContinueErrorTimeStamp(state, " Resetting curve output to zero and continuing simulation.");
2635 0 : } else if (!state.dataGlobal->WarmupFlag) {
2636 0 : ++this->ChillerHeater(numChillerHeater).ChillerCapFTError;
2637 0 : ShowRecurringWarningErrorAtEnd(
2638 : state,
2639 0 : "ChillerHeaterPerformance:Electric:EIR \"" + this->ChillerHeater(numChillerHeater).Name +
2640 : "\": ChillerHeater Capacity as a Function of Temperature curve output is negative warning continues...",
2641 0 : this->ChillerHeater(numChillerHeater).ChillerCapFTErrorIndex,
2642 : chillCapFT,
2643 : chillCapFT);
2644 : }
2645 0 : chillCapFT = 0.0;
2646 : }
2647 0 : return chillCapFT;
2648 : }
2649 :
2650 5 : void WrapperSpecs::checkEvapOutletTemp([[maybe_unused]] EnergyPlusData &state,
2651 : int const numChillerHeater,
2652 : Real64 &evapOutletTemp,
2653 : Real64 const lowTempLimitEout,
2654 : Real64 const evapInletTemp,
2655 : Real64 &qEvaporator,
2656 : Real64 const evapMassFlowRate,
2657 : Real64 const Cp)
2658 : {
2659 : // Check evaporator temperature low limit and adjust capacity if needed
2660 5 : if (evapOutletTemp < lowTempLimitEout) {
2661 2 : if ((evapInletTemp - lowTempLimitEout) > DataPlant::DeltaTempTol) {
2662 1 : evapOutletTemp = lowTempLimitEout;
2663 1 : Real64 evapDeltaTemp = evapInletTemp - evapOutletTemp;
2664 1 : qEvaporator = evapMassFlowRate * Cp * evapDeltaTemp;
2665 : } else {
2666 1 : qEvaporator = 0.0;
2667 1 : evapOutletTemp = evapInletTemp;
2668 : }
2669 : }
2670 :
2671 : // Check if the outlet temperature exceeds the node minimum temperature and adjust capacity if needed
2672 5 : if (evapOutletTemp < this->ChillerHeater(numChillerHeater).EvapOutletNode.TempMin) {
2673 2 : if ((evapInletTemp - this->ChillerHeater(numChillerHeater).EvapOutletNode.TempMin) > DataPlant::DeltaTempTol) {
2674 1 : evapOutletTemp = this->ChillerHeater(numChillerHeater).EvapOutletNode.TempMin;
2675 1 : Real64 evapDeltaTemp = evapInletTemp - evapOutletTemp;
2676 1 : qEvaporator = evapMassFlowRate * Cp * evapDeltaTemp;
2677 : } else {
2678 1 : qEvaporator = 0.0;
2679 1 : evapOutletTemp = evapInletTemp;
2680 : }
2681 : }
2682 5 : }
2683 :
2684 5 : void WrapperSpecs::calcPLRAndCyclingRatio(EnergyPlusData &state,
2685 : Real64 const availChillerCap,
2686 : Real64 &actualPartLoadRatio,
2687 : Real64 const minPartLoadRatio,
2688 : Real64 const maxPartLoadRatio,
2689 : Real64 const qEvaporator,
2690 : Real64 &frac)
2691 : {
2692 : // Calculate PLR (actualPartLoadRatio) based on evaporator load and available capacity, factoring in max PLR
2693 5 : if (availChillerCap <= 0.0) {
2694 1 : actualPartLoadRatio = 0;
2695 1 : frac = 1.0;
2696 : } else {
2697 4 : actualPartLoadRatio = max(0.0, min((qEvaporator / availChillerCap), maxPartLoadRatio));
2698 : // If chiller cycles below minimum part load ratio, frac = amount of time chiller is ON during this time step
2699 4 : if (minPartLoadRatio > 0.0) {
2700 3 : frac = min(1.0, (actualPartLoadRatio / minPartLoadRatio));
2701 : } else {
2702 1 : frac = 1.0;
2703 : }
2704 4 : actualPartLoadRatio = max(actualPartLoadRatio, minPartLoadRatio);
2705 : }
2706 :
2707 5 : state.dataPlantCentralGSHP->ChillerCyclingRatio = frac;
2708 :
2709 : // Evaporator part load ratio
2710 5 : state.dataPlantCentralGSHP->ChillerPartLoadRatio = actualPartLoadRatio;
2711 :
2712 : // Calculate the load due to false loading on chiller over and above water side load
2713 5 : state.dataPlantCentralGSHP->ChillerFalseLoadRate = (availChillerCap * actualPartLoadRatio * frac) - qEvaporator;
2714 5 : if (state.dataPlantCentralGSHP->ChillerFalseLoadRate < HVAC::SmallLoad) {
2715 5 : state.dataPlantCentralGSHP->ChillerFalseLoadRate = 0.0;
2716 : }
2717 5 : }
2718 :
2719 0 : void WrapperSpecs::CalcWrapperModel(EnergyPlusData &state, Real64 &MyLoad, int const LoopNum)
2720 : {
2721 : // SUBROUTINE INFORMATION:
2722 : // AUTHOR Daeho Kang, PNNL
2723 : // DATE WRITTEN Feb 2013
2724 : // MODIFIED na
2725 : // RE-ENGINEERED na
2726 :
2727 : // PURPOSE OF THIS SUBROUTINE:
2728 : // Calculate node information connected to plant & condenser loop
2729 :
2730 : // METHODOLOGY EMPLOYED:
2731 : // Use empirical curve fits to model performance at off-reference conditions
2732 :
2733 0 : Real64 CurHeatingLoad = 0.0; // Total heating load chiller heater bank (wrapper) meets
2734 : Real64 CHWOutletTemp; // Chiller heater bank chilled water outlet temperature
2735 : Real64 CHWOutletMassFlowRate; // Chiller heater bank chilled water outlet mass flow rate
2736 : Real64 HWOutletTemp; // Chiller heater bank hot water outlet temperature
2737 : Real64 GLHEOutletTemp; // Chiller heater bank condenser loop outlet temperature
2738 : Real64 GLHEOutletMassFlowRate; // Chiller heater bank condenser loop outlet mass flow rate
2739 0 : Real64 WrapperElecPowerCool(0.0); // Chiller heater bank total cooling electricity [W]
2740 0 : Real64 WrapperElecPowerHeat(0.0); // Chiller heater bank total heating electricity [W]
2741 0 : Real64 WrapperCoolRate(0.0); // Chiller heater bank total cooling rate [W]
2742 0 : Real64 WrapperHeatRate(0.0); // Chiller heater bank total heating rate [W]
2743 0 : Real64 WrapperGLHERate(0.0); // Chiller heater bank total condenser heat transfer rate [W]
2744 0 : Real64 WrapperElecEnergyCool(0.0); // Chiller heater bank total electric cooling energy [J]
2745 0 : Real64 WrapperElecEnergyHeat(0.0); // Chiller heater bank total electric heating energy [J]
2746 0 : Real64 WrapperCoolEnergy(0.0); // Chiller heater bank total cooling energy [J]
2747 0 : Real64 WrapperHeatEnergy(0.0); // Chiller heater bank total heating energy [J]
2748 0 : Real64 WrapperGLHEEnergy(0.0); // Chiller heater bank total condenser heat transfer energy [J]
2749 :
2750 : // Chiller heater bank chilled water inlet mass flow rate
2751 0 : Real64 CHWInletMassFlowRate = 0.0;
2752 :
2753 0 : Real64 HWInletMassFlowRate = 0.0;
2754 0 : Real64 GLHEInletMassFlowRate = 0.0;
2755 0 : Real64 CHWInletTemp = state.dataLoopNodes->Node(this->CHWInletNodeNum).Temp;
2756 :
2757 : // Chiller heater bank hot water inlet temperature
2758 0 : Real64 HWInletTemp = state.dataLoopNodes->Node(this->HWInletNodeNum).Temp;
2759 :
2760 : // Chiller heater bank condenser loop inlet temperature
2761 0 : Real64 GLHEInletTemp = state.dataLoopNodes->Node(this->GLHEInletNodeNum).Temp;
2762 :
2763 0 : Real64 CurCoolingLoad = 0.0; // Total cooling load chiller heater bank (wrapper) meets
2764 :
2765 : // Initiate loads and inlet temperatures each loop
2766 0 : if (LoopNum == this->CWPlantLoc.loopNum) {
2767 0 : CHWInletMassFlowRate = state.dataLoopNodes->Node(this->CHWInletNodeNum).MassFlowRateMaxAvail;
2768 0 : HWInletMassFlowRate = state.dataLoopNodes->Node(this->HWInletNodeNum).MassFlowRate;
2769 0 : GLHEInletMassFlowRate = state.dataLoopNodes->Node(this->GLHEInletNodeNum).MassFlowRateMaxAvail;
2770 0 : DataPlant::LoopSideLocation LoopSideNum = this->CWPlantLoc.loopSideNum;
2771 0 : this->WrapperCoolingLoad = 0.0;
2772 0 : CurCoolingLoad = std::abs(MyLoad);
2773 0 : this->WrapperCoolingLoad = CurCoolingLoad;
2774 : // Set actual mass flow rate at the nodes when it's locked
2775 0 : if (state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).FlowLock == DataPlant::FlowLock::Locked) {
2776 0 : CHWInletMassFlowRate = state.dataLoopNodes->Node(this->CHWInletNodeNum).MassFlowRate;
2777 : }
2778 0 : if (CHWInletMassFlowRate == 0.0) {
2779 0 : GLHEInletMassFlowRate = 0.0;
2780 : }
2781 :
2782 0 : } else if (LoopNum == this->HWPlantLoc.loopNum) {
2783 0 : CHWInletMassFlowRate = state.dataLoopNodes->Node(this->CHWInletNodeNum).MassFlowRate;
2784 0 : HWInletMassFlowRate = state.dataLoopNodes->Node(this->HWInletNodeNum).MassFlowRateMaxAvail;
2785 0 : GLHEInletMassFlowRate = state.dataLoopNodes->Node(this->GLHEInletNodeNum).MassFlowRateMaxAvail;
2786 0 : DataPlant::LoopSideLocation LoopSideNum = this->HWPlantLoc.loopSideNum;
2787 0 : this->WrapperHeatingLoad = 0.0;
2788 0 : CurHeatingLoad = MyLoad;
2789 0 : this->WrapperHeatingLoad = CurHeatingLoad;
2790 : // Set actual mass flow rate at the nodes when it's locked
2791 0 : if (state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).FlowLock == DataPlant::FlowLock::Locked) {
2792 0 : HWInletMassFlowRate = state.dataLoopNodes->Node(this->HWInletNodeNum).MassFlowRate;
2793 : }
2794 0 : if (HWInletMassFlowRate == 0.0) {
2795 0 : GLHEInletMassFlowRate = 0.0;
2796 : }
2797 : }
2798 :
2799 0 : if (LoopNum == this->CWPlantLoc.loopNum) {
2800 0 : if (this->ControlMode == CondenserType::SmartMixing) {
2801 0 : if (CurCoolingLoad > 0.0 && CHWInletMassFlowRate > 0.0 && GLHEInletMassFlowRate > 0) {
2802 :
2803 0 : this->CalcChillerModel(state);
2804 0 : this->UpdateChillerRecords(state);
2805 :
2806 : // Initialize local variables only for calculating mass-weighed temperatures
2807 0 : CHWOutletTemp = 0.0;
2808 0 : GLHEOutletTemp = 0.0;
2809 0 : CHWOutletMassFlowRate = 0.0;
2810 0 : GLHEOutletMassFlowRate = 0.0;
2811 :
2812 0 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
2813 :
2814 : // Calculated mass flow rate used by individual chiller heater and bypasses
2815 0 : CHWOutletMassFlowRate += this->ChillerHeater(ChillerHeaterNum).Report.Evapmdot;
2816 0 : CHWOutletTemp += this->ChillerHeater(ChillerHeaterNum).Report.EvapOutletTemp *
2817 0 : (this->ChillerHeater(ChillerHeaterNum).Report.Evapmdot / CHWInletMassFlowRate);
2818 0 : WrapperElecPowerCool += this->ChillerHeater(ChillerHeaterNum).Report.CoolingPower;
2819 0 : WrapperCoolRate += this->ChillerHeater(ChillerHeaterNum).Report.QEvap;
2820 0 : WrapperElecEnergyCool += this->ChillerHeater(ChillerHeaterNum).Report.CoolingEnergy;
2821 0 : WrapperCoolEnergy += this->ChillerHeater(ChillerHeaterNum).Report.EvapEnergy;
2822 0 : if (GLHEInletMassFlowRate > 0.0) {
2823 0 : GLHEOutletMassFlowRate += this->ChillerHeater(ChillerHeaterNum).Report.Condmdot;
2824 0 : if (GLHEOutletMassFlowRate > GLHEInletMassFlowRate) {
2825 0 : GLHEOutletMassFlowRate = GLHEInletMassFlowRate;
2826 : }
2827 0 : GLHEOutletTemp += this->ChillerHeater(ChillerHeaterNum).Report.CondOutletTemp *
2828 0 : (this->ChillerHeater(ChillerHeaterNum).Report.Condmdot / GLHEInletMassFlowRate);
2829 0 : WrapperGLHERate += this->ChillerHeater(ChillerHeaterNum).Report.QCond;
2830 0 : WrapperGLHEEnergy += this->ChillerHeater(ChillerHeaterNum).Report.CondEnergy;
2831 : } else {
2832 0 : GLHEInletMassFlowRate = 0.0;
2833 0 : GLHEOutletMassFlowRate = 0.0;
2834 0 : GLHEOutletTemp = GLHEInletTemp;
2835 0 : WrapperGLHERate = 0.0;
2836 0 : WrapperGLHEEnergy = 0.0;
2837 : }
2838 : } // End of summation of mass flow rates and mass weighted temperatrue
2839 :
2840 : // Calculate temperatures for the mixed flows in the chiller bank
2841 0 : Real64 CHWBypassMassFlowRate = CHWInletMassFlowRate - CHWOutletMassFlowRate;
2842 0 : if (CHWBypassMassFlowRate > 0.0) {
2843 0 : CHWOutletTemp += CHWInletTemp * CHWBypassMassFlowRate / CHWInletMassFlowRate;
2844 : } else {
2845 : // CHWOutletTemp = CHWOutletTemp; // Self-assignment commented out
2846 : }
2847 :
2848 0 : if (GLHEInletMassFlowRate > 0.0) {
2849 0 : Real64 GLHEBypassMassFlowRate = GLHEInletMassFlowRate - GLHEOutletMassFlowRate;
2850 0 : if (GLHEBypassMassFlowRate > 0.0) {
2851 0 : GLHEOutletTemp += GLHEInletTemp * GLHEBypassMassFlowRate / GLHEInletMassFlowRate;
2852 : } else {
2853 : // GLHEOutletTemp = GLHEOutletTemp; // Self-assignment commented out
2854 : }
2855 : } else {
2856 0 : GLHEOutletTemp = GLHEInletTemp;
2857 : }
2858 :
2859 0 : HWOutletTemp = HWInletTemp;
2860 :
2861 0 : if (this->ancillaryPowerSched != nullptr) {
2862 0 : WrapperElecPowerCool += (this->AncillaryPower * this->ancillaryPowerSched->getCurrentVal());
2863 : }
2864 :
2865 0 : state.dataLoopNodes->Node(this->CHWOutletNodeNum).Temp = CHWOutletTemp;
2866 0 : state.dataLoopNodes->Node(this->HWOutletNodeNum).Temp = HWOutletTemp;
2867 0 : state.dataLoopNodes->Node(this->GLHEOutletNodeNum).Temp = GLHEOutletTemp;
2868 :
2869 0 : } else {
2870 :
2871 : // Initialize local variables
2872 0 : CHWOutletTemp = CHWInletTemp;
2873 0 : HWOutletTemp = HWInletTemp;
2874 0 : GLHEOutletTemp = GLHEInletTemp;
2875 :
2876 0 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
2877 0 : this->ChillerHeater(ChillerHeaterNum).EvapOutletNode.MassFlowRate = 0.0;
2878 0 : this->ChillerHeater(ChillerHeaterNum).CondOutletNode.MassFlowRate = 0.0;
2879 0 : this->ChillerHeater(ChillerHeaterNum).EvapOutletNode.Temp = CHWInletTemp;
2880 0 : this->ChillerHeater(ChillerHeaterNum).EvapInletNode.Temp = CHWInletTemp;
2881 0 : this->ChillerHeater(ChillerHeaterNum).CondOutletNode.Temp = GLHEInletTemp;
2882 0 : this->ChillerHeater(ChillerHeaterNum).CondInletNode.Temp = GLHEInletTemp;
2883 0 : this->ChillerHeater(ChillerHeaterNum).Report.CurrentMode = 0;
2884 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerPartLoadRatio = 0.0;
2885 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerCyclingRatio = 0.0;
2886 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoadRate = 0.0;
2887 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerCapFT = 0.0;
2888 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFT = 0.0;
2889 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFPLR = 0.0;
2890 0 : this->ChillerHeater(ChillerHeaterNum).Report.CoolingPower = 0.0;
2891 0 : this->ChillerHeater(ChillerHeaterNum).Report.HeatingPower = 0.0;
2892 0 : this->ChillerHeater(ChillerHeaterNum).Report.QEvap = 0.0;
2893 0 : this->ChillerHeater(ChillerHeaterNum).Report.QCond = 0.0;
2894 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapOutletTemp = CHWOutletTemp;
2895 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapInletTemp = CHWInletTemp;
2896 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondOutletTemp = GLHEOutletTemp;
2897 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondInletTemp = GLHEInletTemp;
2898 0 : this->ChillerHeater(ChillerHeaterNum).Report.Evapmdot = 0.0;
2899 0 : this->ChillerHeater(ChillerHeaterNum).Report.Condmdot = 0.0;
2900 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoad = 0.0;
2901 0 : this->ChillerHeater(ChillerHeaterNum).Report.CoolingEnergy = 0.0;
2902 0 : this->ChillerHeater(ChillerHeaterNum).Report.HeatingEnergy = 0.0;
2903 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapEnergy = 0.0;
2904 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondEnergy = 0.0;
2905 0 : this->ChillerHeater(ChillerHeaterNum).Report.ActualCOP = 0.0;
2906 : }
2907 : }
2908 :
2909 0 : if (this->SimulHtgDominant || this->SimulClgDominant) {
2910 0 : state.dataLoopNodes->Node(this->CHWOutletNodeNum).Temp = CHWOutletTemp;
2911 0 : this->Report.CHWInletTempSimul = CHWInletTemp;
2912 0 : this->Report.CHWOutletTempSimul = CHWOutletTemp;
2913 0 : this->Report.CHWmdotSimul = CHWInletMassFlowRate;
2914 0 : this->Report.GLHEInletTempSimul = GLHEInletTemp;
2915 0 : this->Report.GLHEOutletTempSimul = GLHEOutletTemp;
2916 0 : this->Report.GLHEmdotSimul = GLHEInletMassFlowRate;
2917 0 : this->Report.TotElecCoolingSimul = WrapperElecEnergyCool;
2918 0 : this->Report.CoolingEnergySimul = WrapperCoolEnergy;
2919 0 : this->Report.TotElecCoolingPwrSimul = WrapperElecPowerCool;
2920 0 : this->Report.CoolingRateSimul = WrapperCoolRate;
2921 :
2922 : } else {
2923 :
2924 0 : state.dataLoopNodes->Node(this->CHWOutletNodeNum).Temp = CHWOutletTemp;
2925 0 : state.dataLoopNodes->Node(this->HWOutletNodeNum).Temp = HWOutletTemp;
2926 0 : state.dataLoopNodes->Node(this->GLHEOutletNodeNum).Temp = GLHEOutletTemp;
2927 0 : this->Report.CHWInletTemp = CHWInletTemp;
2928 0 : this->Report.CHWOutletTemp = CHWOutletTemp;
2929 0 : this->Report.HWInletTemp = HWInletTemp;
2930 0 : this->Report.HWOutletTemp = HWOutletTemp;
2931 0 : this->Report.GLHEInletTemp = GLHEInletTemp;
2932 0 : this->Report.GLHEOutletTemp = GLHEOutletTemp;
2933 0 : this->Report.CHWmdot = CHWInletMassFlowRate;
2934 0 : this->Report.HWmdot = HWInletMassFlowRate;
2935 0 : this->Report.GLHEmdot = GLHEInletMassFlowRate;
2936 0 : this->Report.TotElecCooling = WrapperElecEnergyCool;
2937 0 : this->Report.TotElecHeating = WrapperElecEnergyHeat;
2938 0 : this->Report.CoolingEnergy = WrapperCoolEnergy;
2939 0 : this->Report.HeatingEnergy = WrapperHeatEnergy;
2940 0 : this->Report.GLHEEnergy = WrapperGLHEEnergy;
2941 0 : this->Report.TotElecCoolingPwr = WrapperElecPowerCool;
2942 0 : this->Report.TotElecHeatingPwr = WrapperElecPowerHeat;
2943 0 : this->Report.CoolingRate = WrapperCoolRate;
2944 0 : this->Report.HeatingRate = WrapperHeatRate;
2945 0 : this->Report.GLHERate = WrapperGLHERate;
2946 : }
2947 0 : PlantUtilities::SetComponentFlowRate(state, CHWInletMassFlowRate, this->CHWInletNodeNum, this->CHWOutletNodeNum, this->CWPlantLoc);
2948 :
2949 0 : PlantUtilities::SetComponentFlowRate(state, HWInletMassFlowRate, this->HWInletNodeNum, this->HWOutletNodeNum, this->HWPlantLoc);
2950 :
2951 0 : PlantUtilities::SetComponentFlowRate(state, GLHEInletMassFlowRate, this->GLHEInletNodeNum, this->GLHEOutletNodeNum, this->GLHEPlantLoc);
2952 :
2953 : } // End of cooling
2954 :
2955 0 : } else if (LoopNum == this->HWPlantLoc.loopNum) { // Hot water loop
2956 0 : if (this->ControlMode == CondenserType::SmartMixing) { // Chiller heater component
2957 0 : if (CurHeatingLoad > 0.0 && HWInletMassFlowRate > 0.0) {
2958 :
2959 0 : this->CalcChillerHeaterModel(state);
2960 0 : this->UpdateChillerHeaterRecords(state);
2961 :
2962 : // Calculate individual CH units's temperatures and mass flow rates
2963 0 : CHWOutletTemp = 0.0;
2964 0 : HWOutletTemp = 0.0;
2965 0 : GLHEOutletTemp = 0.0;
2966 0 : CHWOutletMassFlowRate = 0.0;
2967 0 : Real64 HWOutletMassFlowRate = 0.0;
2968 0 : GLHEOutletMassFlowRate = 0.0;
2969 :
2970 0 : if (this->SimulHtgDominant || this->SimulClgDominant) {
2971 0 : if (this->SimulClgDominant) {
2972 0 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
2973 0 : int CurrentMode = this->ChillerHeater(ChillerHeaterNum).Report.CurrentMode;
2974 0 : CHWInletTemp = this->Report.CHWInletTempSimul;
2975 0 : GLHEInletTemp = this->Report.GLHEInletTempSimul;
2976 0 : CHWInletMassFlowRate = this->Report.CHWmdotSimul;
2977 0 : GLHEInletMassFlowRate = this->Report.GLHEmdotSimul;
2978 :
2979 0 : if (CurrentMode != 0) { // This chiller heater unit is on
2980 0 : if (CurrentMode == 3) { // Heat recovery mode. Both chilled water and hot water connections
2981 0 : CHWOutletMassFlowRate += this->ChillerHeater(ChillerHeaterNum)
2982 0 : .Report.EvapmdotSimul; // Wrapper evaporator side to plant chilled water loop
2983 0 : HWOutletMassFlowRate +=
2984 0 : this->ChillerHeater(ChillerHeaterNum).Report.Condmdot; // Wrapper condenser side to plant hot water loop
2985 0 : if (HWInletMassFlowRate > 0.0) {
2986 0 : HWOutletTemp += this->ChillerHeater(ChillerHeaterNum).Report.CondOutletTemp *
2987 0 : (this->ChillerHeater(ChillerHeaterNum).Report.Condmdot /
2988 : HWInletMassFlowRate); // Only calculate in the heat recovery mode
2989 : } else {
2990 0 : HWOutletTemp = HWInletTemp;
2991 : }
2992 : } else { // Mode 4. Cooling-only mode with other heat recovery units. Condenser flows.
2993 0 : CHWOutletMassFlowRate += this->ChillerHeater(ChillerHeaterNum)
2994 0 : .Report.EvapmdotSimul; // Wrapper evaporator side to plant chilled water loop
2995 : // Sum condenser node mass flow rates and mass weighed temperatures
2996 0 : if (GLHEInletMassFlowRate > 0.0) {
2997 0 : GLHEOutletMassFlowRate += this->ChillerHeater(ChillerHeaterNum).Report.CondmdotSimul;
2998 0 : if (GLHEOutletMassFlowRate > GLHEInletMassFlowRate) {
2999 0 : GLHEOutletMassFlowRate = GLHEInletMassFlowRate;
3000 : }
3001 0 : GLHEOutletTemp += this->ChillerHeater(ChillerHeaterNum).Report.CondOutletTempSimul *
3002 0 : (this->ChillerHeater(ChillerHeaterNum).Report.CondmdotSimul / GLHEInletMassFlowRate);
3003 0 : WrapperGLHERate += this->ChillerHeater(ChillerHeaterNum).Report.QCondSimul;
3004 0 : WrapperGLHEEnergy += this->ChillerHeater(ChillerHeaterNum).Report.CondEnergySimul;
3005 : } else {
3006 0 : GLHEInletMassFlowRate = 0.0;
3007 0 : GLHEOutletMassFlowRate = 0.0;
3008 0 : GLHEOutletTemp = GLHEInletTemp;
3009 0 : WrapperGLHERate = 0.0;
3010 0 : WrapperGLHEEnergy = 0.0;
3011 : }
3012 : }
3013 : } else { // This chiller heater is off
3014 : // Check if any unit is cooling only mode
3015 0 : if (ChillerHeaterNum == this->ChillerHeaterNums) { // All units are heat revocery mode. No condenser flow
3016 0 : GLHEOutletMassFlowRate = 0.0;
3017 0 : GLHEInletMassFlowRate = 0.0;
3018 0 : GLHEOutletTemp = GLHEInletTemp;
3019 : } else { // At leaset, one of chiller heater units is cooling-only mode
3020 : // GLHEOutletMassFlowRate = GLHEOutletMassFlowRate; // Self-assignment commented out
3021 : // GLHEOutletTemp = GLHEOutletTemp; // Self-assignment commented out
3022 : }
3023 : }
3024 : // Calculate mass weighed chilled water temperatures
3025 0 : if (CHWInletMassFlowRate > 0.0) {
3026 0 : CHWOutletTemp += this->ChillerHeater(ChillerHeaterNum).Report.EvapOutletTempSimul *
3027 0 : (this->ChillerHeater(ChillerHeaterNum).Report.EvapmdotSimul / CHWInletMassFlowRate);
3028 : } else {
3029 0 : CHWOutletTemp = CHWInletTemp;
3030 : }
3031 :
3032 0 : WrapperElecPowerCool += this->ChillerHeater(ChillerHeaterNum).Report.CoolingPowerSimul; // Cooling electricity
3033 0 : WrapperCoolRate += this->ChillerHeater(ChillerHeaterNum).Report.QEvapSimul;
3034 0 : WrapperElecEnergyCool += this->ChillerHeater(ChillerHeaterNum).Report.CoolingEnergySimul;
3035 0 : WrapperCoolEnergy += this->ChillerHeater(ChillerHeaterNum).Report.EvapEnergySimul;
3036 : // Avoid double counting wrapper energy use
3037 0 : WrapperElecPowerHeat = 0.0;
3038 0 : WrapperHeatRate = 0.0;
3039 0 : WrapperHeatEnergy = 0.0;
3040 : }
3041 :
3042 : // Calculate chilled water temperature
3043 0 : if (CHWInletMassFlowRate > 0.0) {
3044 0 : Real64 CHWBypassMassFlowRate = CHWInletMassFlowRate - CHWOutletMassFlowRate;
3045 0 : if (CHWBypassMassFlowRate > 0.0) {
3046 0 : CHWOutletTemp += CHWInletTemp * CHWBypassMassFlowRate / CHWInletMassFlowRate;
3047 : } else { // No bypass withnin a wrapper
3048 : // CHWOutletTemp = CHWOutletTemp; // Self-assignment commented out
3049 : }
3050 : } else {
3051 0 : CHWOutletTemp = CHWInletTemp;
3052 : }
3053 : // Calculate hot water outlet temperature
3054 0 : if (HWInletMassFlowRate > 0.0) {
3055 0 : Real64 HWBypassMassFlowRate = HWInletMassFlowRate - HWOutletMassFlowRate;
3056 0 : if (HWBypassMassFlowRate > 0.0) {
3057 0 : HWOutletTemp += HWInletTemp * HWBypassMassFlowRate / HWInletMassFlowRate;
3058 : } else {
3059 : // HWOutletTemp = HWOutletTemp; // Self-assignment commented out
3060 : }
3061 : } else {
3062 0 : HWOutletTemp = HWInletTemp;
3063 : }
3064 : // Calculate condenser outlet temperature
3065 0 : if (GLHEInletMassFlowRate > 0.0) {
3066 0 : Real64 GLHEBypassMassFlowRate = GLHEInletMassFlowRate - GLHEOutletMassFlowRate;
3067 0 : if (GLHEBypassMassFlowRate > 0.0) {
3068 0 : GLHEOutletTemp += GLHEInletTemp * GLHEBypassMassFlowRate / GLHEInletMassFlowRate;
3069 : } else {
3070 : // GLHEOutletTemp = GLHEOutletTemp; // Self-assignment commented out
3071 : }
3072 : } else {
3073 0 : GLHEOutletTemp = GLHEInletTemp;
3074 : }
3075 :
3076 : // Add ancilliary power if scheduled
3077 0 : if (this->ancillaryPowerSched != nullptr) {
3078 0 : WrapperElecPowerCool += (this->AncillaryPower * this->ancillaryPowerSched->getCurrentVal());
3079 : }
3080 :
3081 : // Electricity should be counted once for cooling in this mode
3082 0 : WrapperElecEnergyHeat = 0.0;
3083 :
3084 0 : } else if (this->SimulHtgDominant) { // Heating dominant simultaneous clg/htg mode
3085 :
3086 0 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
3087 : // Set temperatures and mass flow rates for the cooling side
3088 0 : int CurrentMode = this->ChillerHeater(ChillerHeaterNum).Report.CurrentMode;
3089 0 : CHWInletTemp = this->Report.CHWInletTempSimul;
3090 0 : CHWInletMassFlowRate = this->Report.CHWmdotSimul;
3091 :
3092 0 : if (CurrentMode != 0) { // This chiller heater unit is on
3093 0 : if (CurrentMode == 3) { // Heat recovery mode. Both chilled water and hot water connections
3094 0 : CHWOutletMassFlowRate += this->ChillerHeater(ChillerHeaterNum)
3095 0 : .Report.EvapmdotSimul; // Wrapper evaporator side to plant chilled water loop
3096 0 : HWOutletMassFlowRate +=
3097 0 : this->ChillerHeater(ChillerHeaterNum).Report.Condmdot; // Wrapper condenser side to plant hot water loop
3098 0 : if (CHWInletMassFlowRate > 0.0) {
3099 0 : CHWOutletTemp += this->ChillerHeater(ChillerHeaterNum).Report.EvapOutletTempSimul *
3100 0 : (this->ChillerHeater(ChillerHeaterNum).Report.EvapmdotSimul /
3101 : CHWInletMassFlowRate); // Only need to calculate in the heat recovery mode
3102 : } else {
3103 0 : CHWOutletTemp = CHWInletTemp;
3104 : }
3105 : } else { // Mode 5. Heating only mode with other heat recovery units
3106 0 : HWOutletMassFlowRate +=
3107 0 : this->ChillerHeater(ChillerHeaterNum).Report.Condmdot; // Wrapper condenser side to plant hot water loop
3108 0 : if (GLHEInletMassFlowRate > 0.0) {
3109 0 : GLHEOutletMassFlowRate +=
3110 0 : this->ChillerHeater(ChillerHeaterNum).Report.Evapmdot; // Wrapper evaporator side to plant condenser loop
3111 0 : if (GLHEOutletMassFlowRate > GLHEInletMassFlowRate) {
3112 0 : GLHEOutletMassFlowRate = GLHEInletMassFlowRate;
3113 : }
3114 0 : GLHEOutletTemp += this->ChillerHeater(ChillerHeaterNum).Report.EvapOutletTemp *
3115 0 : (this->ChillerHeater(ChillerHeaterNum).Report.Evapmdot / GLHEInletMassFlowRate);
3116 0 : WrapperGLHERate += this->ChillerHeater(ChillerHeaterNum).Report.QEvap;
3117 0 : WrapperGLHEEnergy += this->ChillerHeater(ChillerHeaterNum).Report.EvapEnergy;
3118 : } else {
3119 0 : GLHEInletMassFlowRate = 0.0;
3120 0 : GLHEOutletMassFlowRate = 0.0;
3121 0 : GLHEOutletTemp = GLHEInletTemp;
3122 0 : WrapperGLHERate = 0.0;
3123 0 : WrapperGLHEEnergy = 0.0;
3124 : }
3125 : } // End of heat recovery mode
3126 :
3127 : } else { // This chiller heater is off
3128 :
3129 : // Check if any unit is heating only mode
3130 0 : if (ChillerHeaterNum == this->ChillerHeaterNums) { // All are heat revocery mode. No condenser flow
3131 0 : GLHEOutletMassFlowRate = 0.0;
3132 0 : GLHEInletMassFlowRate = 0.0;
3133 0 : GLHEOutletTemp = GLHEInletTemp;
3134 : } else { // At leaset, one of chiller heater units is heating only mode
3135 : // GLHEOutletMassFlowRate = GLHEOutletMassFlowRate; // Self-assignment commented out
3136 : // GLHEOutletTemp = GLHEOutletTemp; // Self-assignment commented out
3137 : }
3138 : }
3139 :
3140 : // Calculate mass weighed hot water temperatures
3141 0 : if (HWInletMassFlowRate > 0.0) {
3142 0 : HWOutletTemp += this->ChillerHeater(ChillerHeaterNum).Report.CondOutletTemp *
3143 0 : (this->ChillerHeater(ChillerHeaterNum).Report.Condmdot /
3144 : HWInletMassFlowRate); // Always heating as long as heating load remains
3145 : } else {
3146 0 : HWOutletTemp = HWInletTemp;
3147 : }
3148 :
3149 0 : WrapperElecPowerHeat += this->ChillerHeater(ChillerHeaterNum).Report.HeatingPower;
3150 0 : WrapperHeatRate += this->ChillerHeater(ChillerHeaterNum).Report.QCond;
3151 0 : WrapperElecEnergyHeat += this->ChillerHeater(ChillerHeaterNum).Report.HeatingEnergy;
3152 0 : WrapperHeatEnergy += this->ChillerHeater(ChillerHeaterNum).Report.CondEnergy;
3153 :
3154 : // Avoid double counting wrapper energy use
3155 0 : WrapperElecPowerCool = 0.0;
3156 0 : WrapperCoolRate = 0.0;
3157 : }
3158 : // Calculate chilled water outlet temperature
3159 0 : if (CHWInletMassFlowRate > 0.0) {
3160 0 : Real64 CHWBypassMassFlowRate = CHWInletMassFlowRate - CHWOutletMassFlowRate;
3161 0 : if (CHWBypassMassFlowRate > 0.0) {
3162 0 : CHWOutletTemp += CHWInletTemp * CHWBypassMassFlowRate / CHWInletMassFlowRate;
3163 : } else { // No bypass withnin a wrapper
3164 : // CHWOutletTemp = CHWOutletTemp; // Self-assignment commented out
3165 : }
3166 : } else {
3167 0 : CHWOutletTemp = CHWInletTemp;
3168 : }
3169 : // Calculate hot water outlet temperature
3170 0 : if (HWInletMassFlowRate > 0.0) {
3171 0 : Real64 HWBypassMassFlowRate = HWInletMassFlowRate - HWOutletMassFlowRate;
3172 0 : if (HWBypassMassFlowRate > 0.0) {
3173 0 : HWOutletTemp += HWInletTemp * HWBypassMassFlowRate / HWInletMassFlowRate;
3174 : } else {
3175 : // HWOutletTemp = HWOutletTemp; // Self-assignment commented out
3176 : }
3177 : } else {
3178 0 : HWOutletTemp = HWInletTemp;
3179 : }
3180 : // Calculate condenser outlet temperature
3181 0 : if (GLHEInletMassFlowRate > 0.0) {
3182 0 : Real64 GLHEBypassMassFlowRate = GLHEInletMassFlowRate - GLHEOutletMassFlowRate;
3183 0 : if (GLHEBypassMassFlowRate > 0.0) {
3184 0 : GLHEOutletTemp += GLHEInletTemp * GLHEBypassMassFlowRate / GLHEInletMassFlowRate;
3185 : } else {
3186 : // GLHEOutletTemp = GLHEOutletTemp; // Self-assignment commented out
3187 : }
3188 : } else {
3189 0 : GLHEOutletTemp = GLHEInletTemp;
3190 : }
3191 :
3192 : // Check if ancilliary power is used
3193 0 : if (this->ancillaryPowerSched != nullptr) {
3194 0 : WrapperElecPowerHeat += (this->AncillaryPower * this->ancillaryPowerSched->getCurrentVal());
3195 : }
3196 :
3197 : // Electricity should be counted once
3198 0 : WrapperElecEnergyCool = 0.0;
3199 :
3200 : } // End of simultaneous clg/htg mode calculations
3201 :
3202 0 : } else { // Heating only mode (mode 2)
3203 :
3204 0 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
3205 0 : HWOutletMassFlowRate += this->ChillerHeater(ChillerHeaterNum).Report.Condmdot;
3206 0 : HWOutletTemp += this->ChillerHeater(ChillerHeaterNum).Report.CondOutletTemp *
3207 0 : this->ChillerHeater(ChillerHeaterNum).Report.Condmdot / HWInletMassFlowRate;
3208 0 : WrapperElecPowerHeat += this->ChillerHeater(ChillerHeaterNum).Report.HeatingPower;
3209 0 : WrapperHeatRate += this->ChillerHeater(ChillerHeaterNum).Report.QCond;
3210 0 : WrapperElecEnergyHeat += this->ChillerHeater(ChillerHeaterNum).Report.HeatingEnergy;
3211 0 : WrapperHeatEnergy += this->ChillerHeater(ChillerHeaterNum).Report.CondEnergy;
3212 :
3213 0 : if (GLHEInletMassFlowRate > 0.0) {
3214 0 : GLHEOutletMassFlowRate += this->ChillerHeater(ChillerHeaterNum).Report.Evapmdot;
3215 0 : if (GLHEOutletMassFlowRate > GLHEInletMassFlowRate) {
3216 0 : GLHEOutletMassFlowRate = GLHEInletMassFlowRate;
3217 : }
3218 0 : GLHEOutletTemp += this->ChillerHeater(ChillerHeaterNum).Report.EvapOutletTemp *
3219 0 : (this->ChillerHeater(ChillerHeaterNum).Report.Evapmdot / GLHEInletMassFlowRate);
3220 0 : WrapperGLHERate += this->ChillerHeater(ChillerHeaterNum).Report.QEvap;
3221 0 : WrapperGLHEEnergy += this->ChillerHeater(ChillerHeaterNum).Report.EvapEnergy;
3222 : } else { // No source water flow
3223 0 : GLHEOutletMassFlowRate = 0.0;
3224 0 : GLHEInletMassFlowRate = 0.0;
3225 0 : GLHEOutletTemp = GLHEInletTemp;
3226 0 : WrapperGLHERate = 0.0;
3227 0 : WrapperGLHEEnergy = 0.0;
3228 : }
3229 : }
3230 :
3231 : // Calculate hot water outlet temperature
3232 0 : if (HWInletMassFlowRate > 0.0) {
3233 0 : Real64 HWBypassMassFlowRate = HWInletMassFlowRate - HWOutletMassFlowRate;
3234 0 : if (HWBypassMassFlowRate > 0.0) {
3235 0 : HWOutletTemp += HWInletTemp * HWBypassMassFlowRate / HWInletMassFlowRate;
3236 : } else {
3237 : // HWOutletTemp = HWOutletTemp; // Self-assignment commented out
3238 0 : if (HWOutletTemp > HWInletTemp) {
3239 0 : HWOutletTemp = HWInletTemp;
3240 : }
3241 : }
3242 : } else {
3243 0 : HWOutletTemp = HWInletTemp;
3244 : }
3245 :
3246 : // Calculate condenser outlet temperature
3247 0 : if (GLHEInletMassFlowRate > 0.0) {
3248 0 : Real64 GLHEBypassMassFlowRate = GLHEInletMassFlowRate - GLHEOutletMassFlowRate;
3249 0 : if (GLHEBypassMassFlowRate > 0.0) {
3250 0 : GLHEOutletTemp += GLHEInletTemp * GLHEBypassMassFlowRate / GLHEInletMassFlowRate;
3251 : } else {
3252 : // GLHEOutletTemp = GLHEOutletTemp; // Self-assignment commented out
3253 : }
3254 : } else {
3255 0 : GLHEOutletTemp = GLHEInletTemp;
3256 : }
3257 :
3258 0 : CHWOutletTemp = CHWInletTemp;
3259 :
3260 : // Add ancilliary power if necessary
3261 0 : if (this->ancillaryPowerSched != nullptr) {
3262 0 : WrapperElecPowerHeat += (this->AncillaryPower * this->ancillaryPowerSched->getCurrentVal());
3263 : }
3264 :
3265 : } // End of calculations
3266 :
3267 0 : PlantUtilities::SetComponentFlowRate(state, CHWInletMassFlowRate, this->CHWInletNodeNum, this->CHWOutletNodeNum, this->CWPlantLoc);
3268 :
3269 0 : PlantUtilities::SetComponentFlowRate(state, HWInletMassFlowRate, this->HWInletNodeNum, this->HWOutletNodeNum, this->HWPlantLoc);
3270 :
3271 0 : PlantUtilities::SetComponentFlowRate(
3272 0 : state, GLHEInletMassFlowRate, this->GLHEInletNodeNum, this->GLHEOutletNodeNum, this->GLHEPlantLoc);
3273 :
3274 : // Local variables
3275 0 : this->Report.CHWInletTemp = CHWInletTemp;
3276 0 : this->Report.CHWOutletTemp = CHWOutletTemp;
3277 0 : this->Report.HWInletTemp = HWInletTemp;
3278 0 : this->Report.HWOutletTemp = HWOutletTemp;
3279 0 : this->Report.GLHEInletTemp = GLHEInletTemp;
3280 0 : this->Report.GLHEOutletTemp = GLHEOutletTemp;
3281 0 : this->Report.CHWmdot = CHWInletMassFlowRate;
3282 0 : this->Report.HWmdot = HWInletMassFlowRate;
3283 0 : this->Report.GLHEmdot = GLHEInletMassFlowRate;
3284 0 : this->Report.TotElecCooling = WrapperElecEnergyCool;
3285 0 : this->Report.TotElecHeating = WrapperElecEnergyHeat;
3286 0 : this->Report.CoolingEnergy = WrapperCoolEnergy;
3287 0 : this->Report.HeatingEnergy = WrapperHeatEnergy;
3288 0 : this->Report.GLHEEnergy = WrapperGLHEEnergy;
3289 0 : this->Report.TotElecCoolingPwr = WrapperElecPowerCool;
3290 0 : this->Report.TotElecHeatingPwr = WrapperElecPowerHeat;
3291 0 : this->Report.CoolingRate = WrapperCoolRate;
3292 0 : this->Report.HeatingRate = WrapperHeatRate;
3293 0 : this->Report.GLHERate = WrapperGLHERate;
3294 :
3295 0 : state.dataLoopNodes->Node(this->CHWOutletNodeNum).Temp = CHWOutletTemp;
3296 0 : state.dataLoopNodes->Node(this->HWOutletNodeNum).Temp = HWOutletTemp;
3297 0 : state.dataLoopNodes->Node(this->GLHEOutletNodeNum).Temp = GLHEOutletTemp;
3298 :
3299 0 : } else { // Central chiller heater system is off
3300 :
3301 0 : CHWOutletTemp = CHWInletTemp;
3302 0 : HWOutletTemp = HWInletTemp;
3303 0 : GLHEOutletTemp = GLHEInletTemp;
3304 0 : state.dataLoopNodes->Node(this->CHWOutletNodeNum).Temp = CHWOutletTemp;
3305 0 : state.dataLoopNodes->Node(this->HWOutletNodeNum).Temp = HWOutletTemp;
3306 0 : state.dataLoopNodes->Node(this->GLHEOutletNodeNum).Temp = GLHEOutletTemp;
3307 :
3308 0 : if (this->WrapperCoolingLoad == 0.0 && !this->SimulHtgDominant) {
3309 :
3310 0 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
3311 0 : this->ChillerHeater(ChillerHeaterNum).EvapOutletNode.MassFlowRate = 0.0;
3312 0 : this->ChillerHeater(ChillerHeaterNum).CondOutletNode.MassFlowRate = 0.0;
3313 0 : this->ChillerHeater(ChillerHeaterNum).EvapOutletNode.Temp = CHWInletTemp;
3314 0 : this->ChillerHeater(ChillerHeaterNum).EvapInletNode.Temp = CHWInletTemp;
3315 0 : this->ChillerHeater(ChillerHeaterNum).CondOutletNode.Temp = GLHEInletTemp;
3316 0 : this->ChillerHeater(ChillerHeaterNum).CondInletNode.Temp = GLHEInletTemp;
3317 0 : this->ChillerHeater(ChillerHeaterNum).Report.CurrentMode = 0;
3318 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerPartLoadRatio = 0.0;
3319 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerCyclingRatio = 0.0;
3320 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoadRate = 0.0;
3321 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerCapFT = 0.0;
3322 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFT = 0.0;
3323 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerEIRFPLR = 0.0;
3324 0 : this->ChillerHeater(ChillerHeaterNum).Report.CoolingPower = 0.0;
3325 0 : this->ChillerHeater(ChillerHeaterNum).Report.HeatingPower = 0.0;
3326 0 : this->ChillerHeater(ChillerHeaterNum).Report.QEvap = 0.0;
3327 0 : this->ChillerHeater(ChillerHeaterNum).Report.QCond = 0.0;
3328 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapOutletTemp = CHWOutletTemp;
3329 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapInletTemp = CHWInletTemp;
3330 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondOutletTemp = GLHEOutletTemp;
3331 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondInletTemp = GLHEInletTemp;
3332 0 : this->ChillerHeater(ChillerHeaterNum).Report.Evapmdot = 0.0;
3333 0 : this->ChillerHeater(ChillerHeaterNum).Report.Condmdot = 0.0;
3334 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoad = 0.0;
3335 0 : this->ChillerHeater(ChillerHeaterNum).Report.CoolingEnergy = 0.0;
3336 0 : this->ChillerHeater(ChillerHeaterNum).Report.HeatingEnergy = 0.0;
3337 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapEnergy = 0.0;
3338 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondEnergy = 0.0;
3339 0 : this->ChillerHeater(ChillerHeaterNum).Report.ActualCOP = 0.0;
3340 : }
3341 :
3342 0 : this->Report.CHWInletTemp = CHWInletTemp;
3343 0 : this->Report.CHWOutletTemp = CHWOutletTemp;
3344 0 : this->Report.HWInletTemp = HWInletTemp;
3345 0 : this->Report.HWOutletTemp = HWOutletTemp;
3346 0 : this->Report.GLHEInletTemp = GLHEInletTemp;
3347 0 : this->Report.GLHEOutletTemp = GLHEOutletTemp;
3348 0 : this->Report.CHWmdot = CHWInletMassFlowRate;
3349 0 : this->Report.HWmdot = HWInletMassFlowRate;
3350 0 : this->Report.GLHEmdot = GLHEInletMassFlowRate;
3351 0 : this->Report.TotElecCooling = WrapperElecEnergyCool;
3352 0 : this->Report.TotElecHeating = WrapperElecEnergyHeat;
3353 0 : this->Report.CoolingEnergy = WrapperCoolEnergy;
3354 0 : this->Report.HeatingEnergy = WrapperHeatEnergy;
3355 0 : this->Report.GLHEEnergy = WrapperGLHEEnergy;
3356 0 : this->Report.TotElecCoolingPwr = WrapperElecPowerCool;
3357 0 : this->Report.TotElecHeatingPwr = WrapperElecPowerHeat;
3358 0 : this->Report.CoolingRate = WrapperCoolRate;
3359 0 : this->Report.HeatingRate = WrapperHeatRate;
3360 0 : this->Report.GLHERate = WrapperGLHERate;
3361 :
3362 0 : PlantUtilities::SetComponentFlowRate(
3363 0 : state, CHWInletMassFlowRate, this->CHWInletNodeNum, this->CHWOutletNodeNum, this->CWPlantLoc);
3364 :
3365 0 : PlantUtilities::SetComponentFlowRate(state, HWInletMassFlowRate, this->HWInletNodeNum, this->HWOutletNodeNum, this->HWPlantLoc);
3366 :
3367 0 : PlantUtilities::SetComponentFlowRate(
3368 0 : state, GLHEInletMassFlowRate, this->GLHEInletNodeNum, this->GLHEOutletNodeNum, this->GLHEPlantLoc);
3369 : }
3370 :
3371 : } // Heating loop calculation
3372 : }
3373 : }
3374 0 : }
3375 :
3376 0 : void WrapperSpecs::UpdateChillerRecords(EnergyPlusData &state) // Wrapper number
3377 : {
3378 :
3379 : // SUBROUTINE INFORMATION:
3380 : // AUTHOR: Daeho Kang, PNNL
3381 : // DATE WRITTEN: Feb 2013
3382 :
3383 : // PURPOSE OF THIS SUBROUTINE:
3384 : // Update chiller heater variables
3385 :
3386 : Real64 SecInTimeStep; // Number of seconds per HVAC system time step, to convert from W (J/s) to J
3387 : int ChillerHeaterNum; // Chiller heater number
3388 :
3389 0 : SecInTimeStep = state.dataHVACGlobal->TimeStepSysSec;
3390 :
3391 0 : for (ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
3392 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoad =
3393 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoadRate * SecInTimeStep;
3394 0 : this->ChillerHeater(ChillerHeaterNum).Report.CoolingEnergy = this->ChillerHeater(ChillerHeaterNum).Report.CoolingPower * SecInTimeStep;
3395 0 : this->ChillerHeater(ChillerHeaterNum).Report.HeatingEnergy = this->ChillerHeater(ChillerHeaterNum).Report.HeatingPower * SecInTimeStep;
3396 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapEnergy = this->ChillerHeater(ChillerHeaterNum).Report.QEvap * SecInTimeStep;
3397 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondEnergy = this->ChillerHeater(ChillerHeaterNum).Report.QCond * SecInTimeStep;
3398 0 : if (this->SimulClgDominant || this->SimulHtgDominant) {
3399 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoadSimul = this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoad;
3400 0 : this->ChillerHeater(ChillerHeaterNum).Report.CoolingEnergySimul = this->ChillerHeater(ChillerHeaterNum).Report.CoolingEnergy;
3401 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapEnergySimul = this->ChillerHeater(ChillerHeaterNum).Report.EvapEnergy;
3402 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondEnergySimul = this->ChillerHeater(ChillerHeaterNum).Report.CondEnergy;
3403 : }
3404 : }
3405 0 : }
3406 :
3407 0 : void WrapperSpecs::UpdateChillerHeaterRecords(EnergyPlusData &state) // Wrapper number
3408 : {
3409 :
3410 : // SUBROUTINE INFORMATION:
3411 : // AUTHOR: Daeho Kang, PNNL
3412 : // DATE WRITTEN: Feb 2013
3413 :
3414 : // Number of seconds per HVAC system time step, to convert from W (J/s) to J
3415 0 : Real64 SecInTimeStep = state.dataHVACGlobal->TimeStepSysSec;
3416 :
3417 0 : for (int ChillerHeaterNum = 1; ChillerHeaterNum <= this->ChillerHeaterNums; ++ChillerHeaterNum) {
3418 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoad =
3419 0 : this->ChillerHeater(ChillerHeaterNum).Report.ChillerFalseLoadRate * SecInTimeStep;
3420 0 : this->ChillerHeater(ChillerHeaterNum).Report.CoolingEnergy = this->ChillerHeater(ChillerHeaterNum).Report.CoolingPower * SecInTimeStep;
3421 0 : this->ChillerHeater(ChillerHeaterNum).Report.HeatingEnergy = this->ChillerHeater(ChillerHeaterNum).Report.HeatingPower * SecInTimeStep;
3422 0 : this->ChillerHeater(ChillerHeaterNum).Report.EvapEnergy = this->ChillerHeater(ChillerHeaterNum).Report.QEvap * SecInTimeStep;
3423 0 : this->ChillerHeater(ChillerHeaterNum).Report.CondEnergy = this->ChillerHeater(ChillerHeaterNum).Report.QCond * SecInTimeStep;
3424 : }
3425 0 : }
3426 0 : void WrapperSpecs::oneTimeInit_new([[maybe_unused]] EnergyPlusData &state)
3427 : {
3428 0 : }
3429 :
3430 0 : void WrapperSpecs::oneTimeInit([[maybe_unused]] EnergyPlusData &state)
3431 : {
3432 0 : }
3433 :
3434 : } // namespace EnergyPlus::PlantCentralGSHP
|