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 : #include <EnergyPlus/Data/EnergyPlusData.hh>
49 : #include <EnergyPlus/DataAirLoop.hh>
50 : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
51 : #include <EnergyPlus/DataEnvironment.hh>
52 : #include <EnergyPlus/DataHVACGlobals.hh>
53 : #include <EnergyPlus/DataHeatBalance.hh>
54 : #include <EnergyPlus/DataLoopNode.hh>
55 : #include <EnergyPlus/DataPrecisionGlobals.hh>
56 : #include <EnergyPlus/DataSizing.hh>
57 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
58 : #include <EnergyPlus/FluidProperties.hh>
59 : #include <EnergyPlus/General.hh>
60 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
61 : #include <EnergyPlus/Plant/DataPlant.hh>
62 : #include <EnergyPlus/Plant/EquipAndOperations.hh>
63 : #include <EnergyPlus/Plant/Loop.hh>
64 : #include <EnergyPlus/PlantUtilities.hh>
65 : #include <EnergyPlus/Psychrometrics.hh>
66 : #include <EnergyPlus/UtilityRoutines.hh>
67 :
68 : namespace EnergyPlus {
69 : namespace DataPlant {
70 :
71 4 : void ChillerHeaterSupervisoryOperationData::OneTimeInitChillerHeaterChangeoverOpScheme(EnergyPlusData &state)
72 : {
73 4 : if (this->oneTimeSetupComplete) {
74 2 : return;
75 : }
76 :
77 2 : SetupOutputVariable(state,
78 : "Supervisory Plant Heat Pump Operation Mode",
79 : Constant::Units::unknown,
80 2 : this->Report.AirSourcePlant_OpMode,
81 : OutputProcessor::TimeStepType::System,
82 : OutputProcessor::StoreType::Average,
83 2 : this->Name);
84 :
85 2 : SetupOutputVariable(state,
86 : "Supervisory Plant Auxiliary Boiler Mode",
87 : Constant::Units::unknown,
88 2 : this->Report.BoilerAux_OpMode,
89 : OutputProcessor::TimeStepType::System,
90 : OutputProcessor::StoreType::Average,
91 2 : this->Name);
92 4 : SetupOutputVariable(state,
93 : "Supervisory Plant Operation Polled Building Heating Load",
94 : Constant::Units::W,
95 2 : this->Report.BuildingPolledHeatingLoad,
96 : OutputProcessor::TimeStepType::System,
97 : OutputProcessor::StoreType::Average,
98 2 : this->Name);
99 4 : SetupOutputVariable(state,
100 : "Supervisory Plant Operation Polled Building Cooling Load",
101 : Constant::Units::W,
102 2 : this->Report.BuildingPolledCoolingLoad,
103 : OutputProcessor::TimeStepType::System,
104 : OutputProcessor::StoreType::Average,
105 2 : this->Name);
106 4 : SetupOutputVariable(state,
107 : "Supervisory Plant Operation Primary Plant Heating Load",
108 : Constant::Units::W,
109 2 : this->Report.PrimaryPlantHeatingLoad,
110 : OutputProcessor::TimeStepType::System,
111 : OutputProcessor::StoreType::Average,
112 2 : this->Name);
113 4 : SetupOutputVariable(state,
114 : "Supervisory Plant Operation Primary Plant Cooling Load",
115 : Constant::Units::W,
116 2 : this->Report.PrimaryPlantCoolingLoad,
117 : OutputProcessor::TimeStepType::System,
118 : OutputProcessor::StoreType::Average,
119 2 : this->Name);
120 :
121 : // routine for setup of chiller heater supervisory plant operation scheme
122 4 : for (int zoneListNum = 1; zoneListNum <= state.dataHeatBal->NumOfZoneLists; ++zoneListNum) {
123 2 : if (this->ZoneListName == state.dataHeatBal->ZoneList(zoneListNum).Name) {
124 :
125 2 : this->PlantOps.NumOfZones = state.dataHeatBal->ZoneList(zoneListNum).NumOfZones;
126 2 : this->ZonePtrs.allocate(this->PlantOps.NumOfZones);
127 10 : for (int zoneNumInList = 1; zoneNumInList <= state.dataHeatBal->ZoneList(zoneListNum).NumOfZones; ++zoneNumInList) {
128 8 : this->ZonePtrs(zoneNumInList) = state.dataHeatBal->ZoneList(zoneListNum).Zone(zoneNumInList);
129 : }
130 : }
131 : }
132 :
133 2 : if (state.dataHVACGlobal->NumPrimaryAirSys > 0) {
134 2 : this->AirLoopPtrs.allocate(state.dataHVACGlobal->NumPrimaryAirSys); // size to all, if zero then that airloop is not served
135 2 : this->PlantOps.NumOfAirLoops = state.dataHVACGlobal->NumPrimaryAirSys;
136 2 : this->AirLoopPtrs = 0;
137 4 : for (int AirLoopIndex = 1; AirLoopIndex <= state.dataHVACGlobal->NumPrimaryAirSys; ++AirLoopIndex) { // loop over the air systems
138 2 : auto &AirToZoneNodeInfo(state.dataAirLoop->AirToZoneNodeInfo(AirLoopIndex));
139 10 : for (int ZonesPolledIndex = 1; ZonesPolledIndex <= this->PlantOps.NumOfZones; ++ZonesPolledIndex) {
140 40 : for (int ZonesCooledIndex = 1; ZonesCooledIndex <= AirToZoneNodeInfo.NumZonesCooled; ++ZonesCooledIndex) {
141 32 : if (AirToZoneNodeInfo.CoolCtrlZoneNums(ZonesCooledIndex) == this->ZonePtrs(ZonesPolledIndex)) {
142 8 : this->AirLoopPtrs(AirLoopIndex) = AirLoopIndex;
143 : }
144 : }
145 8 : for (int ZonesHeatedIndex = 1; ZonesHeatedIndex <= AirToZoneNodeInfo.NumZonesHeated; ++ZonesHeatedIndex) {
146 0 : if (AirToZoneNodeInfo.HeatCtrlZoneNums(ZonesHeatedIndex) == this->ZonePtrs(ZonesPolledIndex)) {
147 0 : this->AirLoopPtrs(AirLoopIndex) = AirLoopIndex;
148 : }
149 : }
150 : }
151 : }
152 : }
153 :
154 2 : if (this->PlantOps.NumSimultHeatCoolHeatingEquipLists > 0 && this->PlantOps.NumSimultHeatCoolCoolingEquipLists > 0) {
155 1 : this->PlantOps.SimultHeatCoolOpAvailable = true;
156 : }
157 :
158 2 : this->PlantLoopIndicesBeingSupervised.allocate(state.dataPlnt->TotNumLoops);
159 2 : this->PlantLoopIndicesBeingSupervised = 0;
160 6 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
161 4 : auto &this_plant_loop(state.dataPlnt->PlantLoop(LoopNum));
162 8 : for (int OpNum = 1, OpNum_end = this_plant_loop.NumOpSchemes; OpNum <= OpNum_end; ++OpNum) {
163 4 : auto const &this_op_scheme(this_plant_loop.OpScheme(OpNum));
164 4 : if (this_op_scheme.Type == OpScheme::ChillerHeaterSupervisory) {
165 4 : this->PlantLoopIndicesBeingSupervised(LoopNum) = LoopNum;
166 : }
167 : }
168 : }
169 :
170 : // find an setup any Plant Load Profile objects on the supervised loops
171 2 : int numLoadProfileOnSupervisedLoops = 0;
172 6 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
173 4 : if (this->PlantLoopIndicesBeingSupervised(LoopNum) > 0) {
174 : // search for any plant load profile on loop demand side
175 4 : auto &this_plant_loopside(state.dataPlnt->PlantLoop(LoopNum).LoopSide(DataPlant::LoopSideLocation::Demand));
176 12 : for (int BranchNum = 1; BranchNum <= this_plant_loopside.TotalBranches; ++BranchNum) {
177 16 : for (int CompNum = 1; CompNum <= this_plant_loopside.Branch(BranchNum).TotalComponents; ++CompNum) {
178 8 : if (this_plant_loopside.Branch(BranchNum).Comp(CompNum).Type == DataPlant::PlantEquipmentType::PlantLoadProfile) {
179 0 : ++numLoadProfileOnSupervisedLoops;
180 : }
181 : }
182 : }
183 : }
184 : }
185 2 : this->PlantOps.numPlantLoadProfiles = numLoadProfileOnSupervisedLoops;
186 :
187 2 : this->PlantLoadProfileComps.allocate(this->PlantOps.numPlantLoadProfiles);
188 2 : int loadProfileCompNum = 1;
189 6 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
190 4 : if (this->PlantLoopIndicesBeingSupervised(LoopNum) > 0) {
191 : // search for any plant load profile on loop demand side
192 4 : auto &this_plant_loopside(state.dataPlnt->PlantLoop(LoopNum).LoopSide(DataPlant::LoopSideLocation::Demand));
193 12 : for (int BranchNum = 1; BranchNum <= this_plant_loopside.TotalBranches; ++BranchNum) {
194 16 : for (int CompNum = 1; CompNum <= this_plant_loopside.Branch(BranchNum).TotalComponents; ++CompNum) {
195 8 : if (this_plant_loopside.Branch(BranchNum).Comp(CompNum).Type == DataPlant::PlantEquipmentType::PlantLoadProfile) {
196 0 : PlantLocation foundLoc;
197 0 : foundLoc.loopNum = LoopNum;
198 0 : foundLoc.loopSideNum = DataPlant::LoopSideLocation::Demand;
199 0 : foundLoc.branchNum = BranchNum;
200 0 : foundLoc.compNum = CompNum;
201 0 : PlantLoadProfileComps(loadProfileCompNum) = foundLoc;
202 0 : ++loadProfileCompNum;
203 : }
204 : }
205 : }
206 : }
207 : } // end load profile setup
208 :
209 : // find and setup any boilers on the supervised loops
210 2 : int numBoilersOnSupervisedLoops = 0;
211 6 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
212 4 : if (this->PlantLoopIndicesBeingSupervised(LoopNum) > 0) {
213 : // search for any Boiler on loop supply side
214 4 : auto &this_plant_loopside(state.dataPlnt->PlantLoop(LoopNum).LoopSide(DataPlant::LoopSideLocation::Supply));
215 12 : for (int BranchNum = 1; BranchNum <= this_plant_loopside.TotalBranches; ++BranchNum) {
216 16 : for (int CompNum = 1; CompNum <= this_plant_loopside.Branch(BranchNum).TotalComponents; ++CompNum) {
217 8 : if (this_plant_loopside.Branch(BranchNum).Comp(CompNum).Type == DataPlant::PlantEquipmentType::Boiler_Simple) {
218 0 : ++numBoilersOnSupervisedLoops;
219 : }
220 : }
221 : }
222 : }
223 : }
224 2 : this->PlantOps.numBoilers = numBoilersOnSupervisedLoops;
225 2 : this->PlantBoilerComps.allocate(this->PlantOps.numBoilers);
226 2 : int BoilerCompNum = 1;
227 6 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
228 4 : if (this->PlantLoopIndicesBeingSupervised(LoopNum) > 0) {
229 : // search for boiler on loop supply side
230 4 : auto &this_plant_loopside(state.dataPlnt->PlantLoop(LoopNum).LoopSide(DataPlant::LoopSideLocation::Supply));
231 12 : for (int BranchNum = 1; BranchNum <= this_plant_loopside.TotalBranches; ++BranchNum) {
232 16 : for (int CompNum = 1; CompNum <= this_plant_loopside.Branch(BranchNum).TotalComponents; ++CompNum) {
233 8 : if (this_plant_loopside.Branch(BranchNum).Comp(CompNum).Type == DataPlant::PlantEquipmentType::Boiler_Simple) {
234 0 : PlantLocation foundLoc;
235 0 : foundLoc.loopNum = LoopNum;
236 0 : foundLoc.loopSideNum = DataPlant::LoopSideLocation::Supply;
237 0 : foundLoc.branchNum = BranchNum;
238 0 : foundLoc.compNum = CompNum;
239 0 : PlantBoilerComps(BoilerCompNum) = foundLoc;
240 0 : ++BoilerCompNum;
241 : }
242 : }
243 : }
244 : }
245 : } // end boiler setup
246 :
247 : // find and setup any fluid to fluid heat exchangers on the supervised loops
248 2 : this->SecondaryPlantLoopIndicesBeingSupervised.allocate(state.dataPlnt->TotNumLoops);
249 2 : this->SecondaryPlantLoopIndicesBeingSupervised = 0;
250 2 : int numHXsOnSupervisedLoops = 0;
251 6 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
252 4 : if (this->PlantLoopIndicesBeingSupervised(LoopNum) > 0) {
253 : // search for any Heat exchangers on loop supply side
254 4 : auto &this_plant_loopside(state.dataPlnt->PlantLoop(LoopNum).LoopSide(DataPlant::LoopSideLocation::Supply));
255 12 : for (int BranchNum = 1; BranchNum <= this_plant_loopside.TotalBranches; ++BranchNum) {
256 16 : for (int CompNum = 1; CompNum <= this_plant_loopside.Branch(BranchNum).TotalComponents; ++CompNum) {
257 8 : if (this_plant_loopside.Branch(BranchNum).Comp(CompNum).Type == DataPlant::PlantEquipmentType::FluidToFluidPlantHtExchg) {
258 0 : ++numHXsOnSupervisedLoops;
259 : }
260 : }
261 : }
262 : }
263 : }
264 2 : this->PlantOps.numPlantHXs = numHXsOnSupervisedLoops;
265 2 : this->PlantHXComps.allocate(this->PlantOps.numPlantHXs);
266 2 : int HXCompNum = 1;
267 6 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
268 4 : if (this->PlantLoopIndicesBeingSupervised(LoopNum) > 0) {
269 : // search for boiler on loop supply side
270 4 : auto &this_plant_loopside(state.dataPlnt->PlantLoop(LoopNum).LoopSide(DataPlant::LoopSideLocation::Supply));
271 12 : for (int BranchNum = 1; BranchNum <= this_plant_loopside.TotalBranches; ++BranchNum) {
272 16 : for (int CompNum = 1; CompNum <= this_plant_loopside.Branch(BranchNum).TotalComponents; ++CompNum) {
273 8 : if (this_plant_loopside.Branch(BranchNum).Comp(CompNum).Type == DataPlant::PlantEquipmentType::FluidToFluidPlantHtExchg) {
274 0 : PlantLocation foundLoc;
275 0 : foundLoc.loopNum = LoopNum;
276 0 : foundLoc.loopSideNum = DataPlant::LoopSideLocation::Supply;
277 0 : foundLoc.branchNum = BranchNum;
278 0 : foundLoc.compNum = CompNum;
279 0 : PlantHXComps(HXCompNum) = foundLoc;
280 0 : ++HXCompNum;
281 :
282 : // store this loop as being a secondary loop
283 : // assuming that since there is a heat exchanger on the supply side of this loop it is a secondary loop.
284 0 : this->SecondaryPlantLoopIndicesBeingSupervised(LoopNum) = LoopNum;
285 : }
286 : }
287 : }
288 : }
289 : } // end HX setup
290 :
291 : // setup Comp.SetPointNodeNum for machines
292 2 : if (this->PlantOps.NumCoolingOnlyEquipLists > 0) {
293 5 : for (int equipListNum = 1; equipListNum <= this->PlantOps.NumCoolingOnlyEquipLists; ++equipListNum) {
294 :
295 3 : int NumComps = this->CoolingOnlyEquipList(equipListNum).NumComps;
296 7 : for (int compNum = 1; compNum <= NumComps; ++compNum) {
297 4 : auto &this_equip(this->CoolingOnlyEquipList(equipListNum).Comp(compNum));
298 4 : PlantLocation compLoc;
299 : DataPlant::PlantEquipmentType Type =
300 4 : static_cast<DataPlant::PlantEquipmentType>(getEnumValue(PlantEquipTypeNamesUC, Util::makeUPPER(this_equip.TypeOf)));
301 4 : bool errFlag1(false);
302 4 : int NumSearchResults(0);
303 4 : PlantUtilities::ScanPlantLoopsForObject(state, this_equip.Name, Type, compLoc, errFlag1, _, _, NumSearchResults);
304 4 : if (NumSearchResults == 1) {
305 :
306 4 : this_equip.LoopNumPtr = compLoc.loopNum;
307 4 : this_equip.LoopSideNumPtr = compLoc.loopSideNum;
308 4 : this_equip.BranchNumPtr = compLoc.branchNum;
309 4 : this_equip.CompNumPtr = compLoc.compNum;
310 4 : this->PlantOps.PrimaryChWLoopIndex = compLoc.loopNum;
311 0 : } else if (NumSearchResults > 1) {
312 0 : bool foundit = false;
313 0 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
314 0 : if (this->PlantLoopIndicesBeingSupervised(LoopNum) > 0) {
315 0 : int PltSizNum = state.dataPlnt->PlantLoop(LoopNum).PlantSizNum;
316 0 : if (PltSizNum > 0) {
317 0 : if (state.dataSize->PlantSizData(PltSizNum).LoopType == DataSizing::TypeOfPlantLoop::Cooling) {
318 0 : int innerNumSearchResults = 0;
319 0 : PlantUtilities::ScanPlantLoopsForObject(
320 : state, this_equip.Name, Type, compLoc, errFlag1, _, _, innerNumSearchResults, _, LoopNum);
321 0 : if (innerNumSearchResults == 1) {
322 0 : this_equip.LoopNumPtr = compLoc.loopNum;
323 0 : this_equip.LoopSideNumPtr = compLoc.loopSideNum;
324 0 : this_equip.BranchNumPtr = compLoc.branchNum;
325 0 : this_equip.CompNumPtr = compLoc.compNum;
326 0 : foundit = true;
327 0 : continue;
328 : }
329 : }
330 : }
331 : }
332 : }
333 0 : if (!foundit) {
334 0 : ShowSevereError(state,
335 0 : format("ChillerHeaterSupervisoryOperationData::OneTimeInitChillerHeaterChangeoverOpScheme problem=\"{}\" "
336 : "component \"{}\" was not found on a cooling plant loop.",
337 0 : this->Name,
338 0 : this_equip.Name));
339 : }
340 0 : } else if (NumSearchResults == 0) {
341 0 : ShowSevereError(state,
342 0 : format("ChillerHeaterSupervisoryOperationData::OneTimeInitChillerHeaterChangeoverOpScheme problem=\"{}\" "
343 : "component \"{}\" was not found on a plant loop.",
344 0 : this->Name,
345 0 : this_equip.Name));
346 : }
347 4 : int inletNode = state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
348 4 : .LoopSide(this_equip.LoopSideNumPtr)
349 4 : .Branch(this_equip.BranchNumPtr)
350 4 : .Comp(this_equip.CompNumPtr)
351 4 : .NodeNumIn;
352 4 : int outletNode = state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
353 4 : .LoopSide(this_equip.LoopSideNumPtr)
354 4 : .Branch(this_equip.BranchNumPtr)
355 4 : .Comp(this_equip.CompNumPtr)
356 4 : .NodeNumOut;
357 4 : this_equip.DemandNodeNum = inletNode;
358 4 : this_equip.SetPointNodeNum = outletNode;
359 4 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
360 4 : .LoopSide(this_equip.LoopSideNumPtr)
361 4 : .Branch(this_equip.BranchNumPtr)
362 4 : .Comp(this_equip.CompNumPtr)
363 4 : .OpScheme.allocate(1);
364 4 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
365 4 : .LoopSide(this_equip.LoopSideNumPtr)
366 4 : .Branch(this_equip.BranchNumPtr)
367 4 : .Comp(this_equip.CompNumPtr)
368 4 : .OpScheme(1)
369 4 : .OpSchemePtr = 1; // TODO check
370 4 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
371 4 : .LoopSide(this_equip.LoopSideNumPtr)
372 4 : .Branch(this_equip.BranchNumPtr)
373 4 : .Comp(this_equip.CompNumPtr)
374 8 : .CurOpSchemeType = this->Type;
375 : }
376 : }
377 : }
378 2 : if (this->PlantOps.NumHeatingOnlyEquipLists > 0) {
379 5 : for (int equipListNum = 1; equipListNum <= this->PlantOps.NumHeatingOnlyEquipLists; ++equipListNum) {
380 :
381 3 : int NumComps = this->HeatingOnlyEquipList(equipListNum).NumComps;
382 7 : for (int compNum = 1; compNum <= NumComps; ++compNum) {
383 4 : auto &this_equip(this->HeatingOnlyEquipList(equipListNum).Comp(compNum));
384 4 : PlantLocation compLoc;
385 : DataPlant::PlantEquipmentType Type;
386 4 : Type = static_cast<DataPlant::PlantEquipmentType>(getEnumValue(PlantEquipTypeNamesUC, Util::makeUPPER(this_equip.TypeOf)));
387 4 : bool errFlag1(false);
388 4 : int NumSearchResults(0);
389 4 : PlantUtilities::ScanPlantLoopsForObject(state, this_equip.Name, Type, compLoc, errFlag1, _, _, NumSearchResults);
390 4 : if (NumSearchResults == 1) {
391 :
392 4 : this_equip.LoopNumPtr = compLoc.loopNum;
393 4 : this_equip.LoopSideNumPtr = compLoc.loopSideNum;
394 4 : this_equip.BranchNumPtr = compLoc.branchNum;
395 4 : this_equip.CompNumPtr = compLoc.compNum;
396 4 : this->PlantOps.PrimaryHWLoopIndex = compLoc.loopNum;
397 :
398 0 : } else if (NumSearchResults > 1) {
399 :
400 0 : bool foundit = false;
401 0 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
402 0 : if (this->PlantLoopIndicesBeingSupervised(LoopNum) > 0) {
403 0 : int PltSizNum = state.dataPlnt->PlantLoop(LoopNum).PlantSizNum;
404 0 : if (PltSizNum > 0) {
405 0 : if (state.dataSize->PlantSizData(PltSizNum).LoopType == DataSizing::TypeOfPlantLoop::Heating) {
406 0 : int innerNumSearchResults = 0;
407 0 : PlantUtilities::ScanPlantLoopsForObject(
408 : state, this_equip.Name, Type, compLoc, errFlag1, _, _, innerNumSearchResults, _, LoopNum);
409 0 : if (innerNumSearchResults == 1) {
410 0 : this_equip.LoopNumPtr = compLoc.loopNum;
411 0 : this_equip.LoopSideNumPtr = compLoc.loopSideNum;
412 0 : this_equip.BranchNumPtr = compLoc.branchNum;
413 0 : this_equip.CompNumPtr = compLoc.compNum;
414 0 : foundit = true;
415 0 : continue;
416 : }
417 : }
418 : }
419 : }
420 : }
421 0 : if (!foundit) {
422 0 : ShowSevereError(state,
423 0 : format("ChillerHeaterSupervisoryOperationData::OneTimeInitChillerHeaterChangeoverOpScheme problem=\"{}\" "
424 : "component \"{}\" was not found on a heating plant loop.",
425 0 : this->Name,
426 0 : this_equip.Name));
427 : }
428 0 : } else if (NumSearchResults == 0) {
429 0 : ShowSevereError(state,
430 0 : format("ChillerHeaterSupervisoryOperationData::OneTimeInitChillerHeaterChangeoverOpScheme problem=\"{}\" "
431 : "component \"{}\" was not found on a plant loop.",
432 0 : this->Name,
433 0 : this_equip.Name));
434 : }
435 4 : int inletNode = state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
436 4 : .LoopSide(this_equip.LoopSideNumPtr)
437 4 : .Branch(this_equip.BranchNumPtr)
438 4 : .Comp(this_equip.CompNumPtr)
439 4 : .NodeNumIn;
440 4 : int outletNode = state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
441 4 : .LoopSide(this_equip.LoopSideNumPtr)
442 4 : .Branch(this_equip.BranchNumPtr)
443 4 : .Comp(this_equip.CompNumPtr)
444 4 : .NodeNumOut;
445 4 : this_equip.DemandNodeNum = inletNode;
446 4 : this_equip.SetPointNodeNum = outletNode;
447 4 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
448 4 : .LoopSide(this_equip.LoopSideNumPtr)
449 4 : .Branch(this_equip.BranchNumPtr)
450 4 : .Comp(this_equip.CompNumPtr)
451 4 : .OpScheme.allocate(1);
452 4 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
453 4 : .LoopSide(this_equip.LoopSideNumPtr)
454 4 : .Branch(this_equip.BranchNumPtr)
455 4 : .Comp(this_equip.CompNumPtr)
456 4 : .OpScheme(1)
457 4 : .OpSchemePtr = 1; // TODO check
458 4 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
459 4 : .LoopSide(this_equip.LoopSideNumPtr)
460 4 : .Branch(this_equip.BranchNumPtr)
461 4 : .Comp(this_equip.CompNumPtr)
462 8 : .CurOpSchemeType = this->Type;
463 : }
464 : }
465 : }
466 :
467 2 : if (this->PlantOps.NumSimultHeatCoolCoolingEquipLists > 0) {
468 2 : for (int equipListNum = 1; equipListNum <= this->PlantOps.NumSimultHeatCoolCoolingEquipLists; ++equipListNum) {
469 :
470 1 : int NumComps = this->SimultHeatCoolCoolingEquipList(equipListNum).NumComps;
471 2 : for (int compNum = 1; compNum <= NumComps; ++compNum) {
472 1 : auto &this_equip(this->SimultHeatCoolCoolingEquipList(equipListNum).Comp(compNum));
473 1 : PlantLocation compLoc;
474 : DataPlant::PlantEquipmentType Type;
475 1 : Type = static_cast<DataPlant::PlantEquipmentType>(getEnumValue(PlantEquipTypeNamesUC, Util::makeUPPER(this_equip.TypeOf)));
476 1 : bool errFlag1(false);
477 1 : int NumSearchResults(0);
478 1 : PlantUtilities::ScanPlantLoopsForObject(state, this_equip.Name, Type, compLoc, errFlag1, _, _, NumSearchResults);
479 1 : if (NumSearchResults == 1) {
480 :
481 1 : this_equip.LoopNumPtr = compLoc.loopNum;
482 1 : this_equip.LoopSideNumPtr = compLoc.loopSideNum;
483 1 : this_equip.BranchNumPtr = compLoc.branchNum;
484 1 : this_equip.CompNumPtr = compLoc.compNum;
485 :
486 0 : } else if (NumSearchResults > 1) {
487 :
488 0 : bool foundit = false;
489 0 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
490 0 : if (this->PlantLoopIndicesBeingSupervised(LoopNum) > 0) {
491 0 : int PltSizNum = state.dataPlnt->PlantLoop(LoopNum).PlantSizNum;
492 0 : if (PltSizNum > 0) {
493 0 : if (state.dataSize->PlantSizData(PltSizNum).LoopType == DataSizing::TypeOfPlantLoop::Cooling) {
494 0 : int innerNumSearchResults = 0;
495 0 : PlantUtilities::ScanPlantLoopsForObject(
496 : state, this_equip.Name, Type, compLoc, errFlag1, _, _, innerNumSearchResults, _, LoopNum);
497 0 : if (innerNumSearchResults == 1) {
498 0 : this_equip.LoopNumPtr = compLoc.loopNum;
499 0 : this_equip.LoopSideNumPtr = compLoc.loopSideNum;
500 0 : this_equip.BranchNumPtr = compLoc.branchNum;
501 0 : this_equip.CompNumPtr = compLoc.compNum;
502 0 : foundit = true;
503 0 : continue;
504 : }
505 : }
506 : }
507 : }
508 : }
509 0 : if (!foundit) {
510 0 : ShowSevereError(state,
511 0 : format("ChillerHeaterSupervisoryOperationData::OneTimeInitChillerHeaterChangeoverOpScheme problem=\"{}\" "
512 : "component \"{}\" was not found on a cooling plant loop.",
513 0 : this->Name,
514 0 : this_equip.Name));
515 : }
516 0 : } else if (NumSearchResults == 0) {
517 0 : ShowSevereError(state,
518 0 : format("ChillerHeaterSupervisoryOperationData::OneTimeInitChillerHeaterChangeoverOpScheme problem=\"{}\" "
519 : "component \"{}\" was not found on a plant loop.",
520 0 : this->Name,
521 0 : this_equip.Name));
522 : }
523 1 : int inletNode = state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
524 1 : .LoopSide(this_equip.LoopSideNumPtr)
525 1 : .Branch(this_equip.BranchNumPtr)
526 1 : .Comp(this_equip.CompNumPtr)
527 1 : .NodeNumIn;
528 1 : int outletNode = state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
529 1 : .LoopSide(this_equip.LoopSideNumPtr)
530 1 : .Branch(this_equip.BranchNumPtr)
531 1 : .Comp(this_equip.CompNumPtr)
532 1 : .NodeNumOut;
533 1 : this_equip.DemandNodeNum = inletNode;
534 1 : this_equip.SetPointNodeNum = outletNode;
535 1 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
536 1 : .LoopSide(this_equip.LoopSideNumPtr)
537 1 : .Branch(this_equip.BranchNumPtr)
538 1 : .Comp(this_equip.CompNumPtr)
539 1 : .OpScheme.allocate(1);
540 1 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
541 1 : .LoopSide(this_equip.LoopSideNumPtr)
542 1 : .Branch(this_equip.BranchNumPtr)
543 1 : .Comp(this_equip.CompNumPtr)
544 1 : .OpScheme(1)
545 1 : .OpSchemePtr = 1; // TODO check
546 1 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
547 1 : .LoopSide(this_equip.LoopSideNumPtr)
548 1 : .Branch(this_equip.BranchNumPtr)
549 1 : .Comp(this_equip.CompNumPtr)
550 2 : .CurOpSchemeType = this->Type;
551 : }
552 : }
553 : }
554 :
555 2 : if (this->PlantOps.NumSimultHeatCoolHeatingEquipLists > 0) {
556 2 : for (int equipListNum = 1; equipListNum <= this->PlantOps.NumSimultHeatCoolHeatingEquipLists; ++equipListNum) {
557 :
558 1 : int NumComps = this->SimultHeatCoolHeatingEquipList(equipListNum).NumComps;
559 2 : for (int compNum = 1; compNum <= NumComps; ++compNum) {
560 1 : auto &this_equip(this->SimultHeatCoolHeatingEquipList(equipListNum).Comp(compNum));
561 1 : PlantLocation compLoc;
562 : DataPlant::PlantEquipmentType Type;
563 1 : Type = static_cast<DataPlant::PlantEquipmentType>(getEnumValue(PlantEquipTypeNamesUC, Util::makeUPPER(this_equip.TypeOf)));
564 1 : bool errFlag1(false);
565 1 : int NumSearchResults(0);
566 1 : PlantUtilities::ScanPlantLoopsForObject(state, this_equip.Name, Type, compLoc, errFlag1, _, _, NumSearchResults);
567 1 : if (NumSearchResults == 1) {
568 :
569 1 : this_equip.LoopNumPtr = compLoc.loopNum;
570 1 : this_equip.LoopSideNumPtr = compLoc.loopSideNum;
571 1 : this_equip.BranchNumPtr = compLoc.branchNum;
572 1 : this_equip.CompNumPtr = compLoc.compNum;
573 :
574 0 : } else if (NumSearchResults > 1) {
575 :
576 0 : bool foundit = false;
577 0 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
578 0 : if (this->PlantLoopIndicesBeingSupervised(LoopNum) > 0) {
579 0 : int PltSizNum = state.dataPlnt->PlantLoop(LoopNum).PlantSizNum;
580 0 : if (PltSizNum > 0) {
581 0 : if (state.dataSize->PlantSizData(PltSizNum).LoopType == DataSizing::TypeOfPlantLoop::Heating) {
582 0 : int innerNumSearchResults = 0;
583 0 : PlantUtilities::ScanPlantLoopsForObject(
584 : state, this_equip.Name, Type, compLoc, errFlag1, _, _, innerNumSearchResults, _, LoopNum);
585 0 : if (innerNumSearchResults == 1) {
586 0 : this_equip.LoopNumPtr = compLoc.loopNum;
587 0 : this_equip.LoopSideNumPtr = compLoc.loopSideNum;
588 0 : this_equip.BranchNumPtr = compLoc.branchNum;
589 0 : this_equip.CompNumPtr = compLoc.compNum;
590 0 : foundit = true;
591 0 : continue;
592 : }
593 : }
594 : }
595 : }
596 : }
597 0 : if (!foundit) {
598 0 : ShowSevereError(state,
599 0 : format("ChillerHeaterSupervisoryOperationData::OneTimeInitChillerHeaterChangeoverOpScheme problem=\"{}\" "
600 : "component \"{}\" was not found on a heating plant loop.",
601 0 : this->Name,
602 0 : this_equip.Name));
603 : }
604 0 : } else if (NumSearchResults == 0) {
605 0 : ShowSevereError(state,
606 0 : format("ChillerHeaterSupervisoryOperationData::OneTimeInitChillerHeaterChangeoverOpScheme problem=\"{}\" "
607 : "component \"{}\" was not found on a plant loop.",
608 0 : this->Name,
609 0 : this_equip.Name));
610 : }
611 1 : int inletNode = state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
612 1 : .LoopSide(this_equip.LoopSideNumPtr)
613 1 : .Branch(this_equip.BranchNumPtr)
614 1 : .Comp(this_equip.CompNumPtr)
615 1 : .NodeNumIn;
616 1 : int outletNode = state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
617 1 : .LoopSide(this_equip.LoopSideNumPtr)
618 1 : .Branch(this_equip.BranchNumPtr)
619 1 : .Comp(this_equip.CompNumPtr)
620 1 : .NodeNumOut;
621 1 : this_equip.DemandNodeNum = inletNode;
622 1 : this_equip.SetPointNodeNum = outletNode;
623 1 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
624 1 : .LoopSide(this_equip.LoopSideNumPtr)
625 1 : .Branch(this_equip.BranchNumPtr)
626 1 : .Comp(this_equip.CompNumPtr)
627 1 : .OpScheme.allocate(1);
628 1 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
629 1 : .LoopSide(this_equip.LoopSideNumPtr)
630 1 : .Branch(this_equip.BranchNumPtr)
631 1 : .Comp(this_equip.CompNumPtr)
632 1 : .OpScheme(1)
633 1 : .OpSchemePtr = 1; // TODO check
634 1 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
635 1 : .LoopSide(this_equip.LoopSideNumPtr)
636 1 : .Branch(this_equip.BranchNumPtr)
637 1 : .Comp(this_equip.CompNumPtr)
638 2 : .CurOpSchemeType = this->Type;
639 : }
640 : }
641 : }
642 :
643 : // process primary loops for supply inlet node numbers
644 :
645 : // examine supply inlet branch on primary chilled water loop to see if there is a tank, use outlet of tank if so
646 :
647 2 : if (this->PlantOps.PrimaryChWLoopIndex > 0) {
648 :
649 2 : this->PlantOps.PrimaryChWLoopSupInletNode =
650 2 : state.dataPlnt->PlantLoop(this->PlantOps.PrimaryChWLoopIndex).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).NodeNumIn;
651 4 : for (int numComps = 1; numComps <= state.dataPlnt->PlantLoop(this->PlantOps.PrimaryChWLoopIndex)
652 4 : .LoopSide(DataPlant::LoopSideLocation::Supply)
653 4 : .Branch(1)
654 4 : .TotalComponents;
655 : ++numComps) {
656 2 : auto const &this_Comp(state.dataPlnt->PlantLoop(this->PlantOps.PrimaryChWLoopIndex)
657 2 : .LoopSide(DataPlant::LoopSideLocation::Supply)
658 2 : .Branch(1)
659 2 : .Comp(numComps));
660 2 : if (this_Comp.Type == DataPlant::PlantEquipmentType::ChilledWaterTankMixed ||
661 2 : this_Comp.Type == DataPlant::PlantEquipmentType::ChilledWaterTankStratified) {
662 : // assume tank is on chilled water return for use as a buffer tank, use the outlet of the tank instead of the inlet when
663 : // calculating the current load on the primary chilled water plant
664 0 : this->PlantOps.PrimaryChWLoopSupInletNode = this_Comp.NodeNumOut;
665 : }
666 : }
667 : }
668 :
669 2 : if (this->PlantOps.PrimaryHWLoopIndex > 0) {
670 2 : this->PlantOps.PrimaryHWLoopSupInletNode =
671 2 : state.dataPlnt->PlantLoop(this->PlantOps.PrimaryHWLoopIndex).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).NodeNumIn;
672 : }
673 : // process dedicated heat recovery water to water heatpumps to control
674 2 : if (this->PlantOps.DedicatedHR_ChWRetControl_Input && this->PlantOps.DedicatedHR_HWRetControl_Input) {
675 0 : bool founditCooling = false;
676 0 : bool founditHeating = false;
677 0 : for (auto &thisHP : state.dataEIRPlantLoopHeatPump->heatPumps) {
678 0 : std::string const thisPLHPName = Util::makeUPPER(thisHP.name);
679 : // find cooling side heat pump
680 0 : std::string const targetDedHRCoolName = Util::makeUPPER(this->DedicatedHR_ChWRetControl_Name);
681 0 : if (thisPLHPName == targetDedHRCoolName) { // found it
682 0 : this->DedicatedHR_CoolingPLHP = thisHP; // store pointer to cooling side of heat pump
683 0 : founditCooling = true;
684 :
685 0 : int pltSizNum = state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum).PlantSizNum;
686 0 : this->PlantOps.DedicatedHR_SecChW_DesignCapacity = state.dataSize->PlantSizData(pltSizNum).DesCapacity;
687 0 : this->PlantOps.SecondaryChWLoopIndex = this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum;
688 :
689 : // set up load side plant loop information for cooling side of heat pump
690 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum)
691 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopSideNum)
692 0 : .Branch(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.branchNum)
693 0 : .Comp(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.compNum)
694 0 : .OpScheme.allocate(1);
695 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum)
696 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopSideNum)
697 0 : .Branch(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.branchNum)
698 0 : .Comp(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.compNum)
699 0 : .OpScheme(1)
700 0 : .OpSchemePtr = 1;
701 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum)
702 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopSideNum)
703 0 : .Branch(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.branchNum)
704 0 : .Comp(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.compNum)
705 0 : .CurOpSchemeType = this->Type;
706 :
707 : // setup source side plant loop data structure information for cooling side of heat pump
708 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopNum)
709 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopSideNum)
710 0 : .Branch(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.branchNum)
711 0 : .Comp(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.compNum)
712 0 : .OpScheme.allocate(1);
713 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopNum)
714 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopSideNum)
715 0 : .Branch(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.branchNum)
716 0 : .Comp(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.compNum)
717 0 : .OpScheme(1)
718 0 : .OpSchemePtr = 1;
719 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopNum)
720 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopSideNum)
721 0 : .Branch(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.branchNum)
722 0 : .Comp(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.compNum)
723 0 : .CurOpSchemeType = this->Type;
724 : }
725 :
726 : // find heating side heat pump
727 0 : std::string const targetDedHRHeatName = Util::makeUPPER(this->DedicatedHR_HWRetControl_Name);
728 0 : if (thisPLHPName == targetDedHRHeatName) { // found it
729 0 : this->DedicatedHR_HeatingPLHP = thisHP; // store pointer to heating side of heat pump
730 0 : founditHeating = true;
731 :
732 0 : int pltSizNum = state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum).PlantSizNum;
733 0 : this->PlantOps.DedicatedHR_SecHW_DesignCapacity = state.dataSize->PlantSizData(pltSizNum).DesCapacity;
734 0 : this->PlantOps.SecondaryHWLoopIndex = this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum;
735 :
736 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum)
737 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopSideNum)
738 0 : .Branch(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.branchNum)
739 0 : .Comp(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.compNum)
740 0 : .OpScheme.allocate(1);
741 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum)
742 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopSideNum)
743 0 : .Branch(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.branchNum)
744 0 : .Comp(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.compNum)
745 0 : .OpScheme(1)
746 0 : .OpSchemePtr = 1;
747 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum)
748 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopSideNum)
749 0 : .Branch(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.branchNum)
750 0 : .Comp(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.compNum)
751 0 : .CurOpSchemeType = this->Type;
752 :
753 : // setup source side plant loop data structure information for heating side of heat pump
754 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopNum)
755 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopSideNum)
756 0 : .Branch(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.branchNum)
757 0 : .Comp(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.compNum)
758 0 : .OpScheme.allocate(1);
759 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopNum)
760 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopSideNum)
761 0 : .Branch(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.branchNum)
762 0 : .Comp(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.compNum)
763 0 : .OpScheme(1)
764 0 : .OpSchemePtr = 1;
765 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopNum)
766 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopSideNum)
767 0 : .Branch(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.branchNum)
768 0 : .Comp(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.compNum)
769 0 : .CurOpSchemeType = this->Type;
770 : }
771 0 : }
772 :
773 0 : if (!founditCooling) {
774 0 : ShowSevereError(state,
775 0 : format("ChillerHeaterSupervisoryOperationData::OneTimeInitChillerHeaterChangeoverOpScheme problem=\"{}\" component "
776 : "\"{}\" was not found on a cooling plant loop.",
777 0 : this->Name,
778 0 : this->DedicatedHR_ChWRetControl_Name));
779 : }
780 0 : if (!founditHeating) {
781 0 : ShowSevereError(state,
782 0 : format("ChillerHeaterSupervisoryOperationData::OneTimeInitChillerHeaterChangeoverOpScheme problem=\"{}\" component "
783 : "\"{}\" was not found on a heating plant loop.",
784 0 : this->Name,
785 0 : this->DedicatedHR_ChWRetControl_Name));
786 : }
787 0 : if (founditCooling && founditHeating) {
788 0 : this->PlantOps.DedicatedHR_Present = true;
789 0 : SetupOutputVariable(state,
790 : "Supervisory Plant Heat Recovery Operation Mode",
791 : Constant::Units::unknown,
792 0 : this->Report.DedicHR_OpMode,
793 : OutputProcessor::TimeStepType::System,
794 : OutputProcessor::StoreType::Average,
795 0 : this->Name);
796 0 : SetupOutputVariable(state,
797 : "Supervisory Plant Operation Secondary Plant Heating Load",
798 : Constant::Units::W,
799 0 : this->Report.SecondaryPlantHeatingLoad,
800 : OutputProcessor::TimeStepType::System,
801 : OutputProcessor::StoreType::Average,
802 0 : this->Name);
803 0 : SetupOutputVariable(state,
804 : "Supervisory Plant Operation Secondary Plant Cooling Load",
805 : Constant::Units::W,
806 0 : this->Report.SecondaryPlantCoolingLoad,
807 : OutputProcessor::TimeStepType::System,
808 : OutputProcessor::StoreType::Average,
809 0 : this->Name);
810 : }
811 : }
812 :
813 2 : this->oneTimeSetupComplete = true;
814 : }
815 :
816 11 : void ChillerHeaterSupervisoryOperationData::EvaluateChillerHeaterChangeoverOpScheme(EnergyPlusData &state)
817 : {
818 :
819 11 : DetermineCurrentBuildingLoads(state);
820 11 : DetermineCurrentPlantLoads(state);
821 11 : ProcessSupervisoryControlLogicForAirSourcePlants(state);
822 11 : InitAirSourcePlantEquipmentOff(state);
823 11 : ProcessAndSetAirSourcePlantEquipLists(state);
824 11 : ProcessAndSetDedicatedHeatRecovWWHP(state);
825 11 : ProcessAndSetAuxilBoiler(state);
826 11 : }
827 :
828 11 : void ChillerHeaterSupervisoryOperationData::DetermineCurrentBuildingLoads(EnergyPlusData &state)
829 : {
830 : // Poll the loads on the zones to help decide how to run
831 :
832 11 : Real64 sumZonePredictedHeatingLoad(0.0);
833 11 : Real64 sumZonePredictedCoolingLoad(0.0);
834 55 : for (int zoneIndexinList = 1; zoneIndexinList <= this->PlantOps.NumOfZones; ++zoneIndexinList) {
835 44 : int thisZoneIndex = this->ZonePtrs(zoneIndexinList);
836 44 : Real64 ZoneMult = state.dataHeatBal->Zone(thisZoneIndex).Multiplier * state.dataHeatBal->Zone(thisZoneIndex).ListMultiplier;
837 : // aggregate required outputs to setpoint, with zone multipliers included
838 44 : sumZonePredictedCoolingLoad +=
839 44 : min(0.0,
840 44 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisZoneIndex).OutputRequiredToCoolingSP * ZoneMult); // sum only negative values
841 44 : sumZonePredictedHeatingLoad +=
842 44 : max(0.0,
843 44 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(thisZoneIndex).OutputRequiredToHeatingSP * ZoneMult); // sum only positive values
844 : }
845 :
846 : // now add in ventilation loading at the central air system level
847 11 : Real64 sumAirSysVentHeatingLoad(0.0);
848 11 : Real64 sumAirSysVentCoolingLoad(0.0);
849 :
850 22 : for (int airLoopsServedIndex = 1; airLoopsServedIndex <= this->PlantOps.NumOfAirLoops; ++airLoopsServedIndex) {
851 11 : int AirLoopNum = this->AirLoopPtrs(airLoopsServedIndex);
852 11 : Real64 outAir_H = state.dataEnvrn->OutEnthalpy;
853 11 : Real64 outAirMdot = state.dataAirLoop->AirLoopFlow(AirLoopNum).OAFlow;
854 11 : Real64 retAir_Tdb = state.dataLoopNodes->Node(state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).AirLoopReturnNodeNum(1)).Temp;
855 11 : Real64 retAir_w = state.dataLoopNodes->Node(state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).AirLoopReturnNodeNum(1)).HumRat;
856 11 : Real64 ventLoad = outAirMdot * (Psychrometrics::PsyHFnTdbW(retAir_Tdb, retAir_w) - outAir_H); // negative is cooling
857 11 : if (ventLoad > HVAC::SmallLoad) { // add to heating
858 0 : sumAirSysVentHeatingLoad += ventLoad;
859 11 : } else if (ventLoad < DataPrecisionGlobals::constant_minusone * HVAC::SmallLoad) { // add to cooling
860 0 : sumAirSysVentCoolingLoad += ventLoad;
861 : }
862 : }
863 :
864 : // now add in any process loads from plant load profiles on the controlled loops.
865 11 : Real64 sumLoadProfileHeatingLoad(0.0);
866 11 : Real64 sumLoadProfileCoolingLoad(0.0);
867 11 : for (int NumProcLoad = 1; NumProcLoad <= this->PlantOps.numPlantLoadProfiles; ++NumProcLoad) {
868 0 : Real64 load = 0.0;
869 0 : DataPlant::CompData::getPlantComponent(state, PlantLoadProfileComps(NumProcLoad)).compPtr->getCurrentPower(state, load);
870 0 : if (load > 0.0) {
871 0 : sumLoadProfileHeatingLoad += load;
872 : } else {
873 0 : sumLoadProfileCoolingLoad += load;
874 : }
875 : }
876 :
877 11 : this->Report.BuildingPolledCoolingLoad = sumZonePredictedCoolingLoad + sumAirSysVentCoolingLoad + sumLoadProfileCoolingLoad;
878 11 : this->Report.BuildingPolledHeatingLoad = sumZonePredictedHeatingLoad + sumAirSysVentHeatingLoad + sumLoadProfileHeatingLoad;
879 : // end collect loads.
880 11 : }
881 :
882 11 : void ChillerHeaterSupervisoryOperationData::DetermineCurrentPlantLoads(EnergyPlusData &state)
883 : {
884 :
885 : // Calculate load on primary chilled water loop and store in PrimaryPlantCoolingLoad
886 :
887 11 : Real64 CW_RetMdot = state.dataLoopNodes->Node(this->PlantOps.PrimaryChWLoopSupInletNode).MassFlowRate;
888 11 : Real64 const CpCW = state.dataPlnt->PlantLoop(this->PlantOps.PrimaryChWLoopIndex)
889 11 : .glycol->getSpecificHeat(
890 11 : state, state.dataLoopNodes->Node(this->PlantOps.PrimaryChWLoopSupInletNode).Temp, "DetermineCurrentPlantLoads");
891 : Real64 CW_Qdot =
892 11 : min(0.0,
893 11 : CW_RetMdot * CpCW *
894 22 : (this->Setpoint.PrimCW -
895 11 : state.dataLoopNodes->Node(this->PlantOps.PrimaryChWLoopSupInletNode).Temp)); // power = Mdot Cp Delta T, cooling load is negative
896 11 : this->Report.PrimaryPlantCoolingLoad = CW_Qdot;
897 :
898 : // Calculate load on primary hot water loop and store in PrimaryPlantHeatingLoad
899 : // int HWSupInletNode = this->PlantOps.PrimaryHWLoopSupInletNode;
900 : // state.dataPlnt->PlantLoop(this->PlantOps.PrimaryHWLoopIndex).LoopSide(DataPlant::LoopSideLocation::Supply).Branch(1).NodeNumIn;
901 11 : Real64 HW_RetMdot = state.dataLoopNodes->Node(this->PlantOps.PrimaryHWLoopSupInletNode).MassFlowRate;
902 11 : Real64 const CpHW = state.dataPlnt->PlantLoop(this->PlantOps.PrimaryHWLoopIndex)
903 11 : .glycol->getSpecificHeat(
904 11 : state, state.dataLoopNodes->Node(this->PlantOps.PrimaryHWLoopSupInletNode).Temp, "DetermineCurrentPlantLoads");
905 :
906 : Real64 HW_Qdot =
907 11 : max(0.0,
908 11 : HW_RetMdot * CpHW *
909 11 : (this->DetermineHWSetpointOARest(state) -
910 11 : state.dataLoopNodes->Node(this->PlantOps.PrimaryHWLoopSupInletNode).Temp)); // power = Mdot Cp Delta T, heating load is positive
911 11 : this->Report.PrimaryPlantHeatingLoad = HW_Qdot;
912 11 : }
913 :
914 11 : void ChillerHeaterSupervisoryOperationData::ProcessSupervisoryControlLogicForAirSourcePlants(EnergyPlusData &state)
915 : {
916 : // this routine decides which of three modes the plants should operate in, Heating Only, Cooling Only, Simultaneous Heating and Cooling.
917 :
918 : // step 1, initialize control bools
919 11 : this->PlantOps.AirSourcePlantCoolingOnly = false;
920 11 : this->PlantOps.AirSourcePlantHeatingOnly = false;
921 11 : this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling = false;
922 11 : this->PlantOps.SimultaneousHeatingCoolingWithCoolingDominant = false;
923 11 : this->PlantOps.SimultaneousHeatingCoolingWithHeatingDominant = false;
924 :
925 : // step 2, process logic based on poll results for building loads.
926 11 : if (this->Report.BuildingPolledHeatingLoad < HVAC::SmallLoad &&
927 7 : this->Report.BuildingPolledCoolingLoad < DataPrecisionGlobals::constant_minusone * HVAC::SmallLoad) {
928 2 : this->PlantOps.AirSourcePlantCoolingOnly = true;
929 9 : } else if (this->Report.BuildingPolledCoolingLoad > DataPrecisionGlobals::constant_minusone * HVAC::SmallLoad &&
930 7 : this->Report.BuildingPolledHeatingLoad > HVAC::SmallLoad) {
931 2 : this->PlantOps.AirSourcePlantHeatingOnly = true;
932 :
933 2 : if (state.dataEnvrn->OutDryBulbTemp < this->TempReset.LowOutdoorTemp) { // too cold for airsource HPs so
934 0 : this->PlantOps.AirSourcePlantHeatingOnly = false;
935 : }
936 :
937 7 : } else if ((this->Report.BuildingPolledCoolingLoad < DataPrecisionGlobals::constant_minusone * HVAC::SmallLoad) &&
938 2 : (this->Report.BuildingPolledHeatingLoad > HVAC::SmallLoad)) {
939 2 : this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling = true;
940 2 : if (this->Report.BuildingPolledHeatingLoad > abs(this->Report.BuildingPolledCoolingLoad)) {
941 0 : this->PlantOps.SimultaneousHeatingCoolingWithHeatingDominant = true;
942 0 : if (this->PlantOps.SimultHeatCoolOpAvailable) {
943 0 : this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling = true;
944 : } else {
945 0 : this->PlantOps.AirSourcePlantHeatingOnly = true;
946 0 : this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling = false;
947 : }
948 2 : } else if (abs(this->Report.BuildingPolledCoolingLoad) > this->Report.BuildingPolledHeatingLoad) {
949 1 : this->PlantOps.SimultaneousHeatingCoolingWithCoolingDominant = true;
950 1 : if (this->PlantOps.SimultHeatCoolOpAvailable) {
951 0 : this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling = true;
952 : } else {
953 1 : this->PlantOps.AirSourcePlantCoolingOnly = true;
954 1 : this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling = false;
955 : }
956 : }
957 2 : if (state.dataEnvrn->OutDryBulbTemp < this->TempReset.LowOutdoorTemp) { // too cold for airsource HPs
958 0 : this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling = false;
959 0 : this->PlantOps.AirSourcePlantCoolingOnly = true;
960 : }
961 : }
962 :
963 : // step 3, revise control decision based on current loads on primary plant loops
964 11 : if (this->PlantOps.AirSourcePlantHeatingOnly &&
965 2 : this->Report.PrimaryPlantCoolingLoad < DataPrecisionGlobals::constant_minusone * HVAC::SmallLoad) {
966 : // polled building loads indicate all heating, but cooling plant has cooling load, try to switch to simultaneous cooling and heating with
967 : // heating dominant
968 0 : if (this->PlantOps.SimultHeatCoolOpAvailable) {
969 0 : this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling = true;
970 0 : this->PlantOps.SimultaneousHeatingCoolingWithHeatingDominant = true;
971 0 : this->PlantOps.AirSourcePlantHeatingOnly = false;
972 : }
973 : }
974 :
975 12 : if (this->PlantOps.AirSourcePlantCoolingOnly && this->Report.PrimaryPlantHeatingLoad > HVAC::SmallLoad &&
976 1 : state.dataEnvrn->OutDryBulbTemp >= this->TempReset.LowOutdoorTemp) {
977 : // polled building loads indicate all cooling, but heating plant has heating load, and outdoor air is warm enough for heat pump, try to
978 : // switch to simultaneous cooling and heating with cooling dominant
979 1 : if (this->PlantOps.SimultHeatCoolOpAvailable) {
980 0 : this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling = true;
981 0 : this->PlantOps.SimultaneousHeatingCoolingWithCoolingDominant = true;
982 0 : this->PlantOps.AirSourcePlantCoolingOnly = false;
983 : }
984 : }
985 :
986 : // do we need to turn on cooling-only if in off mode but PrimaryPlantCoolingLoad is loaded?
987 11 : if (!this->PlantOps.AirSourcePlantCoolingOnly && !this->PlantOps.AirSourcePlantHeatingOnly &&
988 6 : !this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling) { // all off
989 5 : if (this->Report.PrimaryPlantCoolingLoad < DataPrecisionGlobals::constant_minusone * HVAC::SmallLoad) {
990 0 : this->PlantOps.AirSourcePlantCoolingOnly = true;
991 : }
992 : }
993 :
994 : // override reset AirSourcePlantHeatingOnly to false and AirSourcePlantCoolingOnly to true if the plant cooling load is higher
995 : // the plant heating load and the plant heating load is small.
996 11 : if (!this->PlantOps.AirSourcePlantCoolingOnly && this->PlantOps.AirSourcePlantHeatingOnly &&
997 2 : !this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling) { // all off
998 2 : if (std::abs(this->Report.PrimaryPlantCoolingLoad) > this->Report.PrimaryPlantHeatingLoad &&
999 0 : this->Report.PrimaryPlantHeatingLoad < HVAC::SmallLoad) {
1000 0 : this->PlantOps.AirSourcePlantCoolingOnly = true;
1001 0 : this->PlantOps.AirSourcePlantHeatingOnly = false;
1002 : }
1003 : }
1004 :
1005 : // override reset AirSourcePlantHeatingOnly to true and AirSourcePlantCoolingOnly to false if the plant heating load is higher
1006 : // the plant cooling load and the plant cooling load is small.
1007 11 : if (this->PlantOps.AirSourcePlantCoolingOnly && !this->PlantOps.AirSourcePlantHeatingOnly &&
1008 3 : !this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling) { // all off
1009 4 : if (this->Report.PrimaryPlantHeatingLoad > std::abs(this->Report.PrimaryPlantCoolingLoad) &&
1010 1 : this->Report.PrimaryPlantCoolingLoad > DataPrecisionGlobals::constant_minusone * HVAC::SmallLoad) {
1011 1 : this->PlantOps.AirSourcePlantHeatingOnly = true;
1012 1 : this->PlantOps.AirSourcePlantCoolingOnly = false;
1013 : }
1014 : }
1015 :
1016 : // do we need to turn on heating-only if in off mode but PrimaryPlantHeatingLoad is loaded?
1017 11 : if (!this->PlantOps.AirSourcePlantCoolingOnly && !this->PlantOps.AirSourcePlantHeatingOnly &&
1018 6 : !this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling) { // all off
1019 5 : if (this->Report.PrimaryPlantHeatingLoad > HVAC::SmallLoad && state.dataEnvrn->OutDryBulbTemp >= this->TempReset.LowOutdoorTemp) {
1020 0 : this->PlantOps.AirSourcePlantHeatingOnly = true;
1021 : }
1022 : }
1023 :
1024 : // step 4, convert logical flags into integers for output variable reporting
1025 11 : if (this->PlantOps.AirSourcePlantHeatingOnly) {
1026 3 : this->Report.AirSourcePlant_OpMode = 1;
1027 8 : } else if (this->PlantOps.AirSourcePlantCoolingOnly) {
1028 2 : this->Report.AirSourcePlant_OpMode = 2;
1029 6 : } else if (this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling) {
1030 1 : this->Report.AirSourcePlant_OpMode = 3;
1031 : } else {
1032 5 : this->Report.AirSourcePlant_OpMode = 0;
1033 : }
1034 11 : }
1035 :
1036 11 : void ChillerHeaterSupervisoryOperationData::InitAirSourcePlantEquipmentOff(EnergyPlusData &state)
1037 : {
1038 : //_____________________________________________________________________________
1039 : // initialize all possible equipment to turn off machines before applying controls to turn them on.
1040 : // set .Available and .ON to false in plant structure
1041 :
1042 11 : if (this->PlantOps.NumCoolingOnlyEquipLists > 0) {
1043 28 : for (int equipListNum = 1; equipListNum <= this->PlantOps.NumCoolingOnlyEquipLists; ++equipListNum) {
1044 17 : int NumComps = this->CoolingOnlyEquipList(equipListNum).NumComps;
1045 40 : for (int compNum = 1; compNum <= NumComps; ++compNum) {
1046 23 : auto &this_equip(this->CoolingOnlyEquipList(equipListNum).Comp(compNum));
1047 23 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1048 23 : .LoopSide(this_equip.LoopSideNumPtr)
1049 23 : .Branch(this_equip.BranchNumPtr)
1050 23 : .Comp(this_equip.CompNumPtr)
1051 23 : .Available = false;
1052 23 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1053 23 : .LoopSide(this_equip.LoopSideNumPtr)
1054 23 : .Branch(this_equip.BranchNumPtr)
1055 23 : .Comp(this_equip.CompNumPtr)
1056 23 : .ON = false;
1057 : }
1058 : }
1059 : }
1060 :
1061 11 : if (this->PlantOps.NumHeatingOnlyEquipLists > 0) {
1062 28 : for (int equipListNum = 1; equipListNum <= this->PlantOps.NumHeatingOnlyEquipLists; ++equipListNum) {
1063 17 : int NumComps = this->HeatingOnlyEquipList(equipListNum).NumComps;
1064 40 : for (int compNum = 1; compNum <= NumComps; ++compNum) {
1065 23 : auto &this_equip(this->HeatingOnlyEquipList(equipListNum).Comp(compNum));
1066 23 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1067 23 : .LoopSide(this_equip.LoopSideNumPtr)
1068 23 : .Branch(this_equip.BranchNumPtr)
1069 23 : .Comp(this_equip.CompNumPtr)
1070 23 : .Available = false;
1071 23 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1072 23 : .LoopSide(this_equip.LoopSideNumPtr)
1073 23 : .Branch(this_equip.BranchNumPtr)
1074 23 : .Comp(this_equip.CompNumPtr)
1075 23 : .ON = false;
1076 : }
1077 : }
1078 : }
1079 :
1080 11 : if (this->PlantOps.NumSimultHeatCoolCoolingEquipLists > 0) {
1081 12 : for (int equipListNum = 1; equipListNum <= this->PlantOps.NumSimultHeatCoolCoolingEquipLists; ++equipListNum) {
1082 :
1083 6 : int NumComps = this->SimultHeatCoolCoolingEquipList(equipListNum).NumComps;
1084 12 : for (int compNum = 1; compNum <= NumComps; ++compNum) {
1085 6 : auto &this_equip(this->SimultHeatCoolCoolingEquipList(equipListNum).Comp(compNum));
1086 6 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1087 6 : .LoopSide(this_equip.LoopSideNumPtr)
1088 6 : .Branch(this_equip.BranchNumPtr)
1089 6 : .Comp(this_equip.CompNumPtr)
1090 6 : .Available = false;
1091 6 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1092 6 : .LoopSide(this_equip.LoopSideNumPtr)
1093 6 : .Branch(this_equip.BranchNumPtr)
1094 6 : .Comp(this_equip.CompNumPtr)
1095 6 : .ON = false;
1096 : }
1097 : }
1098 : }
1099 :
1100 11 : if (this->PlantOps.NumSimultHeatCoolHeatingEquipLists > 0) {
1101 12 : for (int equipListNum = 1; equipListNum <= this->PlantOps.NumSimultHeatCoolHeatingEquipLists; ++equipListNum) {
1102 :
1103 6 : int NumComps = this->SimultHeatCoolHeatingEquipList(equipListNum).NumComps;
1104 12 : for (int compNum = 1; compNum <= NumComps; ++compNum) {
1105 6 : auto &this_equip(this->SimultHeatCoolHeatingEquipList(equipListNum).Comp(compNum));
1106 6 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1107 6 : .LoopSide(this_equip.LoopSideNumPtr)
1108 6 : .Branch(this_equip.BranchNumPtr)
1109 6 : .Comp(this_equip.CompNumPtr)
1110 6 : .Available = false;
1111 6 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1112 6 : .LoopSide(this_equip.LoopSideNumPtr)
1113 6 : .Branch(this_equip.BranchNumPtr)
1114 6 : .Comp(this_equip.CompNumPtr)
1115 6 : .ON = false;
1116 : }
1117 : }
1118 : }
1119 : // end init machines off
1120 11 : }
1121 :
1122 11 : void ChillerHeaterSupervisoryOperationData::ProcessAndSetAirSourcePlantEquipLists(EnergyPlusData &state)
1123 : {
1124 : // TODO this routine is currently code to compare real current plant loads, polled building loads have also been studied.
1125 11 : Real64 CoolingLoadSignal = this->Report.PrimaryPlantCoolingLoad;
1126 11 : Real64 HeatingLoadSignal = this->Report.PrimaryPlantHeatingLoad;
1127 :
1128 : //___________________________________________________________________________
1129 11 : if (this->PlantOps.AirSourcePlantCoolingOnly) {
1130 : // use zone loads to find range based cooling loads
1131 5 : for (int equipListNum = 1; equipListNum <= this->PlantOps.NumCoolingOnlyEquipLists; ++equipListNum) {
1132 : // zone cooling loads are negative, switch to positive for range based limiting
1133 5 : if (CoolingLoadSignal * DataPrecisionGlobals::constant_minusone > this->CoolingOnlyEquipList(equipListNum).RangeLowerLimit &&
1134 2 : this->CoolingOnlyEquipList(equipListNum).RangeUpperLimit > CoolingLoadSignal * DataPrecisionGlobals::constant_minusone) {
1135 : // found that this equipment list load ranges match the zone predicted cooling loads
1136 :
1137 2 : int NumComps = this->CoolingOnlyEquipList(equipListNum).NumComps;
1138 4 : for (int compNum = 1; compNum <= NumComps; ++compNum) {
1139 2 : auto &this_equip(this->CoolingOnlyEquipList(equipListNum).Comp(compNum));
1140 : // set cooling setpoint at outlet
1141 :
1142 : // todo, oa reset ?
1143 :
1144 2 : state.dataLoopNodes->Node(this_equip.SetPointNodeNum).TempSetPoint = this->Setpoint.PrimCW;
1145 2 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this_equip.LoopNumPtr).TempSetPointNodeNum).TempSetPoint =
1146 2 : this->Setpoint.PrimCW;
1147 2 : if (state.dataLoopNodes->Node(this_equip.DemandNodeNum).Temp > this->Setpoint.PrimCW) {
1148 :
1149 2 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1150 2 : .LoopSide(this_equip.LoopSideNumPtr)
1151 2 : .Branch(this_equip.BranchNumPtr)
1152 2 : .Comp(this_equip.CompNumPtr)
1153 2 : .Available = true;
1154 2 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1155 2 : .LoopSide(this_equip.LoopSideNumPtr)
1156 2 : .Branch(this_equip.BranchNumPtr)
1157 2 : .Comp(this_equip.CompNumPtr)
1158 2 : .ON = true;
1159 2 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1160 2 : .LoopSide(this_equip.LoopSideNumPtr)
1161 2 : .Branch(this_equip.BranchNumPtr)
1162 2 : .Comp(this_equip.CompNumPtr)
1163 4 : .CurOpSchemeType = this->Type;
1164 : }
1165 : //
1166 : }
1167 : }
1168 : }
1169 : }
1170 :
1171 : //____________________________________________________________________________
1172 11 : if (this->PlantOps.AirSourcePlantHeatingOnly) { // Use Heating Only equipment operation
1173 :
1174 3 : Real64 HWsetpt = DetermineHWSetpointOARest(state);
1175 : // use zone loads to find range based heating loads
1176 7 : for (int equipListNum = 1; equipListNum <= this->PlantOps.NumHeatingOnlyEquipLists; ++equipListNum) {
1177 7 : if (HeatingLoadSignal > this->HeatingOnlyEquipList(equipListNum).RangeLowerLimit &&
1178 3 : this->HeatingOnlyEquipList(equipListNum).RangeUpperLimit > HeatingLoadSignal) {
1179 : // found that this equipment list load ranges match the zone predicted heating loads
1180 :
1181 3 : int NumComps = this->HeatingOnlyEquipList(equipListNum).NumComps;
1182 6 : for (int compNum = 1; compNum <= NumComps; ++compNum) {
1183 3 : auto &this_equip(this->HeatingOnlyEquipList(equipListNum).Comp(compNum));
1184 : // set heating setpoint at outlet
1185 :
1186 3 : state.dataLoopNodes->Node(this_equip.SetPointNodeNum).TempSetPoint = HWsetpt;
1187 3 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this_equip.LoopNumPtr).TempSetPointNodeNum).TempSetPoint = HWsetpt;
1188 :
1189 3 : if (state.dataLoopNodes->Node(this_equip.DemandNodeNum).Temp < HWsetpt) {
1190 3 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1191 3 : .LoopSide(this_equip.LoopSideNumPtr)
1192 3 : .Branch(this_equip.BranchNumPtr)
1193 3 : .Comp(this_equip.CompNumPtr)
1194 3 : .Available = true;
1195 3 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1196 3 : .LoopSide(this_equip.LoopSideNumPtr)
1197 3 : .Branch(this_equip.BranchNumPtr)
1198 3 : .Comp(this_equip.CompNumPtr)
1199 3 : .ON = true;
1200 3 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1201 3 : .LoopSide(this_equip.LoopSideNumPtr)
1202 3 : .Branch(this_equip.BranchNumPtr)
1203 3 : .Comp(this_equip.CompNumPtr)
1204 6 : .CurOpSchemeType = this->Type;
1205 : }
1206 : //
1207 : }
1208 : }
1209 : }
1210 : }
1211 :
1212 11 : if (this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling) {
1213 :
1214 : // use zone cooling loads to find range based equipment
1215 2 : for (int equipListNum = 1; equipListNum <= this->PlantOps.NumSimultHeatCoolCoolingEquipLists; ++equipListNum) {
1216 : // zone cooling loads are negative, switch to positive for range based limiting
1217 2 : if (CoolingLoadSignal * DataPrecisionGlobals::constant_minusone >
1218 2 : this->SimultHeatCoolCoolingEquipList(equipListNum).RangeLowerLimit &&
1219 1 : this->SimultHeatCoolCoolingEquipList(equipListNum).RangeUpperLimit >
1220 1 : CoolingLoadSignal * DataPrecisionGlobals::constant_minusone) {
1221 : // found that this equipment list load ranges match the zone predicted cooling loads
1222 :
1223 1 : int NumComps = this->SimultHeatCoolCoolingEquipList(equipListNum).NumComps;
1224 2 : for (int compNum = 1; compNum <= NumComps; ++compNum) {
1225 1 : auto &this_equip(this->SimultHeatCoolCoolingEquipList(equipListNum).Comp(compNum));
1226 : // set cooling setpoint at outlet
1227 :
1228 1 : state.dataLoopNodes->Node(this_equip.SetPointNodeNum).TempSetPoint = this->Setpoint.PrimCW;
1229 1 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this_equip.LoopNumPtr).TempSetPointNodeNum).TempSetPoint =
1230 1 : this->Setpoint.PrimCW;
1231 1 : if (state.dataLoopNodes->Node(this_equip.DemandNodeNum).Temp > this->Setpoint.PrimCW) {
1232 1 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1233 1 : .LoopSide(this_equip.LoopSideNumPtr)
1234 1 : .Branch(this_equip.BranchNumPtr)
1235 1 : .Comp(this_equip.CompNumPtr)
1236 1 : .Available = true;
1237 1 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1238 1 : .LoopSide(this_equip.LoopSideNumPtr)
1239 1 : .Branch(this_equip.BranchNumPtr)
1240 1 : .Comp(this_equip.CompNumPtr)
1241 1 : .ON = true;
1242 1 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1243 1 : .LoopSide(this_equip.LoopSideNumPtr)
1244 1 : .Branch(this_equip.BranchNumPtr)
1245 1 : .Comp(this_equip.CompNumPtr)
1246 2 : .CurOpSchemeType = this->Type;
1247 : }
1248 : //
1249 : }
1250 : }
1251 : }
1252 :
1253 : // use zone loads to find range based heating loads
1254 1 : Real64 HWsetpt = DetermineHWSetpointOARest(state);
1255 2 : for (int equipListNum = 1; equipListNum <= this->PlantOps.NumSimultHeatCoolHeatingEquipLists; ++equipListNum) {
1256 2 : if (HeatingLoadSignal > this->SimultHeatCoolHeatingEquipList(equipListNum).RangeLowerLimit &&
1257 1 : this->SimultHeatCoolHeatingEquipList(equipListNum).RangeUpperLimit > HeatingLoadSignal) {
1258 : // found that this equipment list load ranges match the zone predicted heating loads
1259 :
1260 1 : int NumComps = this->SimultHeatCoolHeatingEquipList(equipListNum).NumComps;
1261 2 : for (int compNum = 1; compNum <= NumComps; ++compNum) {
1262 1 : auto &this_equip(this->SimultHeatCoolHeatingEquipList(equipListNum).Comp(compNum));
1263 : // set heating setpoint at outlet
1264 :
1265 1 : state.dataLoopNodes->Node(this_equip.SetPointNodeNum).TempSetPoint = HWsetpt;
1266 1 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this_equip.LoopNumPtr).TempSetPointNodeNum).TempSetPoint = HWsetpt;
1267 :
1268 1 : if (state.dataLoopNodes->Node(this_equip.DemandNodeNum).Temp < HWsetpt) {
1269 1 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1270 1 : .LoopSide(this_equip.LoopSideNumPtr)
1271 1 : .Branch(this_equip.BranchNumPtr)
1272 1 : .Comp(this_equip.CompNumPtr)
1273 1 : .Available = true;
1274 1 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1275 1 : .LoopSide(this_equip.LoopSideNumPtr)
1276 1 : .Branch(this_equip.BranchNumPtr)
1277 1 : .Comp(this_equip.CompNumPtr)
1278 1 : .ON = true;
1279 1 : state.dataPlnt->PlantLoop(this_equip.LoopNumPtr)
1280 1 : .LoopSide(this_equip.LoopSideNumPtr)
1281 1 : .Branch(this_equip.BranchNumPtr)
1282 1 : .Comp(this_equip.CompNumPtr)
1283 2 : .CurOpSchemeType = this->Type;
1284 : }
1285 : //
1286 : }
1287 : }
1288 : }
1289 : }
1290 11 : }
1291 :
1292 11 : void ChillerHeaterSupervisoryOperationData::ProcessAndSetDedicatedHeatRecovWWHP(EnergyPlusData &state)
1293 : {
1294 : // evaluate if and how dedicated heat recovery WWHP should run
1295 :
1296 11 : if (!this->PlantOps.DedicatedHR_Present) {
1297 11 : return;
1298 : }
1299 :
1300 : // initialize off
1301 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum)
1302 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopSideNum)
1303 0 : .Branch(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.branchNum)
1304 0 : .Comp(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.compNum)
1305 0 : .Available = false;
1306 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum)
1307 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopSideNum)
1308 0 : .Branch(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.branchNum)
1309 0 : .Comp(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.compNum)
1310 0 : .ON = false;
1311 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopNum)
1312 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopSideNum)
1313 0 : .Branch(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.branchNum)
1314 0 : .Comp(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.compNum)
1315 0 : .Available = false;
1316 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopNum)
1317 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopSideNum)
1318 0 : .Branch(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.branchNum)
1319 0 : .Comp(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.compNum)
1320 0 : .ON = false;
1321 :
1322 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum)
1323 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopSideNum)
1324 0 : .Branch(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.branchNum)
1325 0 : .Comp(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.compNum)
1326 0 : .Available = false;
1327 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum)
1328 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopSideNum)
1329 0 : .Branch(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.branchNum)
1330 0 : .Comp(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.compNum)
1331 0 : .ON = false;
1332 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopNum)
1333 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopSideNum)
1334 0 : .Branch(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.branchNum)
1335 0 : .Comp(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.compNum)
1336 0 : .Available = false;
1337 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopNum)
1338 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopSideNum)
1339 0 : .Branch(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.branchNum)
1340 0 : .Comp(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.compNum)
1341 0 : .ON = false;
1342 :
1343 : // Dedicated Heat Recovery Water To Water Heat Pump Control.
1344 : // Assume there are two companion machines, one leads for cooling the return chilled water, the other leads for heating the return hot
1345 : // water When one side leads, the other gets favorable heat addition/extraction it is just not controlled to meet a setpoint Assume these
1346 : // are on the secondary loops. Need to decide if it runs and which of cooling or heating companion coils gets to lead.
1347 : //
1348 : // Step 1. get the mass flow rates of the returns. both must be non-zero for the WWHP to run
1349 0 : int inletChWReturnNodeNum = state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopNum)
1350 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopSideNum)
1351 0 : .Branch(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.branchNum)
1352 0 : .Comp(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.compNum)
1353 0 : .NodeNumIn;
1354 0 : int inletHWReturnNodeNum = state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopNum)
1355 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopSideNum)
1356 0 : .Branch(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.branchNum)
1357 0 : .Comp(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.compNum)
1358 0 : .NodeNumIn;
1359 0 : Real64 CW_RetMdot = state.dataLoopNodes->Node(inletChWReturnNodeNum).MassFlowRate;
1360 0 : Real64 HW_RetMdot = state.dataLoopNodes->Node(inletHWReturnNodeNum).MassFlowRate;
1361 :
1362 0 : bool flowInEach = false;
1363 : // need flow in both returns.
1364 0 : if (CW_RetMdot <= HVAC::SmallWaterVolFlow || HW_RetMdot <= HVAC::SmallWaterVolFlow) {
1365 0 : flowInEach = false;
1366 : } else {
1367 0 : flowInEach = true;
1368 : }
1369 :
1370 : // step 2. calculate the loads to adjust the
1371 : // returns to hit the associated setpoints at their current mass flow
1372 : Real64 const CpCW =
1373 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.sourceSidePlantLoc.loopNum)
1374 0 : .glycol->getSpecificHeat(state, state.dataLoopNodes->Node(inletChWReturnNodeNum).Temp, "EvaluateChillerHeaterChangeoverOpScheme");
1375 : Real64 CW_Qdot =
1376 0 : CW_RetMdot * CpCW *
1377 0 : (this->Setpoint.SecCW - state.dataLoopNodes->Node(inletChWReturnNodeNum).Temp); // power = Mdot Cp Delta T, cooling load is negative
1378 : Real64 const CpHW =
1379 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.sourceSidePlantLoc.loopNum)
1380 0 : .glycol->getSpecificHeat(state, state.dataLoopNodes->Node(inletHWReturnNodeNum).Temp, "EvaluateChillerHeaterChangeoverOpScheme");
1381 0 : Real64 HW_Qdot = HW_RetMdot * CpHW * (this->Setpoint.SecHW - state.dataLoopNodes->Node(inletHWReturnNodeNum).Temp); // power = Mdot Cp Delta T
1382 :
1383 : // store for reporting
1384 0 : this->Report.SecondaryPlantCoolingLoad = CW_Qdot;
1385 0 : this->Report.SecondaryPlantHeatingLoad = HW_Qdot;
1386 :
1387 : // step 3 decide if Dedicated HR is on and which leads based
1388 0 : bool CoolLedNeed = false;
1389 0 : bool HeatLedNeed = false;
1390 :
1391 0 : if (this->PlantOps.AirSourcePlantHeatingOnly && (CW_Qdot < DataPrecisionGlobals::constant_minusone * HVAC::SmallLoad) && flowInEach) {
1392 : // polled building loads are heating only, but secondary ChW plant has some cooling load and there is mass flow in each. So turn dedicated
1393 : // HR on in cooling lead mode
1394 0 : CoolLedNeed = true;
1395 : }
1396 :
1397 0 : if (this->PlantOps.AirSourcePlantCoolingOnly && (HW_Qdot > HVAC::SmallLoad) && flowInEach) {
1398 : // polled building loads are cooling only, but secondary HW plant has some heating load and there is mass flow in each. So turn dedicated
1399 : // HR on in heating lead mode
1400 0 : HeatLedNeed = true;
1401 : }
1402 :
1403 0 : if (this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling && this->PlantOps.SimultaneousHeatingCoolingWithHeatingDominant &&
1404 : flowInEach) {
1405 : // polled building loads are simultaneous with heating dominating and there is mass flow in each, So turn
1406 : // dedicated HR on in heating lead mode
1407 0 : HeatLedNeed = true;
1408 : }
1409 :
1410 0 : if (this->PlantOps.AirSourcePlantSimultaneousHeatingAndCooling && this->PlantOps.SimultaneousHeatingCoolingWithCoolingDominant &&
1411 : flowInEach) {
1412 : // polled building loads are simultaneous with cooling dominating and there is mass flow in each, So turn
1413 : // dedicated HR on in cooling lead mode
1414 0 : CoolLedNeed = true;
1415 : }
1416 :
1417 : // step 4. check that there is sufficient flow in source side for chosen leader to avoid runaway plant conditions on source side
1418 : // if not, see if other side could run beneficially as leader and switch to it if so
1419 : // Real64 FlowImbalanceRatioThreshold = 10.0; // TODO, check with TRANE engineering about WWHP operating limits wrt to relative flows (real
1420 : // // systems have a pumped sided arm flow situation and do not have low flow problems)
1421 :
1422 : // if (CoolLedNeed) {
1423 : // if (CW_RetMdot / HW_RetMdot > FlowImbalanceRatioThreshold) { // insufficient flow in source side relative to load side
1424 : // CoolLedNeed = false;
1425 : // // if (HW_Qdot > 1.0) {
1426 : // // HeatLedNeed = true;
1427 : // //}
1428 : // }
1429 : //}
1430 : // if (HeatLedNeed) {
1431 : // if (HW_RetMdot / CW_RetMdot > FlowImbalanceRatioThreshold) { // insufficient flow in source side relative to load side
1432 : // HeatLedNeed = false;
1433 : // // if (CW_Qdot < -1.0) {
1434 : // // CoolLedNeed = true;
1435 : // //}
1436 : // }
1437 : //}
1438 :
1439 0 : this->Report.DedicHR_OpMode = 0;
1440 0 : if (CoolLedNeed) {
1441 0 : this->Report.DedicHR_OpMode = 2;
1442 : // turn ON load side of this water to water heat pump
1443 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum)
1444 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopSideNum)
1445 0 : .Branch(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.branchNum)
1446 0 : .Comp(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.compNum)
1447 0 : .Available = true;
1448 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum)
1449 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopSideNum)
1450 0 : .Branch(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.branchNum)
1451 0 : .Comp(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.compNum)
1452 0 : .ON = true;
1453 :
1454 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum)
1455 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopSideNum)
1456 0 : .Branch(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.branchNum)
1457 0 : .Comp(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.compNum)
1458 0 : .CurOpSchemeType = this->Type;
1459 :
1460 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum)
1461 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopSideNum)
1462 0 : .Branch(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.branchNum)
1463 0 : .Comp(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.compNum)
1464 0 : .MyLoad = CW_Qdot; // cooling load is negative
1465 :
1466 0 : int OutletChWReturnNodeNum = state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum)
1467 0 : .LoopSide(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopSideNum)
1468 0 : .Branch(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.branchNum)
1469 0 : .Comp(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.compNum)
1470 0 : .NodeNumOut;
1471 0 : state.dataLoopNodes->Node(OutletChWReturnNodeNum).TempSetPoint = this->Setpoint.SecCW;
1472 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum).TempSetPointNodeNum)
1473 0 : .TempSetPoint = this->Setpoint.SecCW;
1474 :
1475 0 : if (this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum ==
1476 0 : SecondaryPlantLoopIndicesBeingSupervised(this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum)) {
1477 : // search for HX on this loop and place setpoint on outlet
1478 0 : for (int HXnum = 1; HXnum <= this->PlantOps.numPlantHXs; ++HXnum) {
1479 0 : if (this->PlantHXComps(HXnum).loopNum == this->DedicatedHR_CoolingPLHP.loadSidePlantLoc.loopNum) {
1480 0 : int outletnode = state.dataPlnt->PlantLoop(this->PlantHXComps(HXnum).loopNum)
1481 0 : .LoopSide(this->PlantHXComps(HXnum).loopSideNum)
1482 0 : .Branch(this->PlantHXComps(HXnum).branchNum)
1483 0 : .Comp(this->PlantHXComps(HXnum).compNum)
1484 0 : .NodeNumOut;
1485 0 : state.dataLoopNodes->Node(outletnode).TempSetPoint = this->Setpoint.SecCW;
1486 : }
1487 : }
1488 : }
1489 :
1490 0 : } else if (HeatLedNeed) {
1491 0 : this->Report.DedicHR_OpMode = 1;
1492 : // turn load side of this water to water heat pump
1493 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum)
1494 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopSideNum)
1495 0 : .Branch(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.branchNum)
1496 0 : .Comp(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.compNum)
1497 0 : .Available = true;
1498 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum)
1499 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopSideNum)
1500 0 : .Branch(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.branchNum)
1501 0 : .Comp(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.compNum)
1502 0 : .ON = true;
1503 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum)
1504 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopSideNum)
1505 0 : .Branch(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.branchNum)
1506 0 : .Comp(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.compNum)
1507 0 : .CurOpSchemeType = this->Type;
1508 0 : state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum)
1509 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopSideNum)
1510 0 : .Branch(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.branchNum)
1511 0 : .Comp(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.compNum)
1512 0 : .MyLoad = HW_Qdot;
1513 :
1514 0 : int OutletHWReturnNodeNum = state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum)
1515 0 : .LoopSide(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopSideNum)
1516 0 : .Branch(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.branchNum)
1517 0 : .Comp(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.compNum)
1518 0 : .NodeNumOut;
1519 :
1520 0 : state.dataLoopNodes->Node(OutletHWReturnNodeNum).TempSetPoint = this->Setpoint.SecHW;
1521 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum).TempSetPointNodeNum)
1522 0 : .TempSetPoint = this->Setpoint.SecHW;
1523 :
1524 0 : if (this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum ==
1525 0 : SecondaryPlantLoopIndicesBeingSupervised(this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum)) {
1526 : // search for HX on this loop and place setpoint on outlet
1527 0 : for (int HXnum = 1; HXnum <= this->PlantOps.numPlantHXs; ++HXnum) {
1528 0 : if (this->PlantHXComps(HXnum).loopNum == this->DedicatedHR_HeatingPLHP.loadSidePlantLoc.loopNum) {
1529 0 : int outletnode = state.dataPlnt->PlantLoop(this->PlantHXComps(HXnum).loopNum)
1530 0 : .LoopSide(this->PlantHXComps(HXnum).loopSideNum)
1531 0 : .Branch(this->PlantHXComps(HXnum).branchNum)
1532 0 : .Comp(this->PlantHXComps(HXnum).compNum)
1533 0 : .NodeNumOut;
1534 0 : state.dataLoopNodes->Node(outletnode).TempSetPoint = min(this->Setpoint.SecHW, this->DetermineHWSetpointOARest(state));
1535 : }
1536 : }
1537 : }
1538 : }
1539 : }
1540 :
1541 11 : void ChillerHeaterSupervisoryOperationData::ProcessAndSetAuxilBoiler(EnergyPlusData &state)
1542 : {
1543 : // Check for boiler used as auxiliary or supplemental
1544 : // Assume boilers are in-line on supply side outlet branch, typically on secondary loop but may be on primary loop
1545 11 : this->Report.BoilerAux_OpMode = 0;
1546 11 : if (this->PlantOps.numBoilers <= 0) {
1547 11 : return;
1548 : }
1549 :
1550 : // first initialize them to be off
1551 0 : if (this->PlantOps.numBoilers > 0) {
1552 0 : for (int BoilerNum = 1; BoilerNum <= this->PlantOps.numBoilers; ++BoilerNum) {
1553 0 : state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum)
1554 0 : .LoopSide(this->PlantBoilerComps(BoilerNum).loopSideNum)
1555 0 : .Branch(this->PlantBoilerComps(BoilerNum).branchNum)
1556 0 : .Comp(this->PlantBoilerComps(BoilerNum).compNum)
1557 0 : .Available = false;
1558 0 : state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum)
1559 0 : .LoopSide(this->PlantBoilerComps(BoilerNum).loopSideNum)
1560 0 : .Branch(this->PlantBoilerComps(BoilerNum).branchNum)
1561 0 : .Comp(this->PlantBoilerComps(BoilerNum).compNum)
1562 0 : .ON = false;
1563 0 : state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum)
1564 0 : .LoopSide(this->PlantBoilerComps(BoilerNum).loopSideNum)
1565 0 : .Branch(this->PlantBoilerComps(BoilerNum).branchNum)
1566 0 : .Comp(this->PlantBoilerComps(BoilerNum).compNum)
1567 0 : .MyLoad = 0.0;
1568 : }
1569 : }
1570 :
1571 0 : if (this->PlantOps.numBoilers > 0) {
1572 : // Boilers will run if outdoor air temperature is too low and there is flow in HW return loop
1573 :
1574 0 : bool LowOAAuxiliaryNeeded = false;
1575 0 : if (state.dataEnvrn->OutDryBulbTemp < this->TempReset.LowOutdoorTemp) {
1576 0 : LowOAAuxiliaryNeeded = true;
1577 : }
1578 0 : for (int BoilerNum = 1; BoilerNum <= this->PlantOps.numBoilers; ++BoilerNum) {
1579 : // determine if primary or secondary setpoint in use
1580 0 : Real64 HWsetpt = 0.0;
1581 0 : if (this->SecondaryPlantLoopIndicesBeingSupervised(this->PlantBoilerComps(BoilerNum).loopNum) >
1582 : 0) { // appears to be on secondary loop, supplemental boiler
1583 0 : HWsetpt = min(this->Setpoint.SecHW,
1584 : DetermineHWSetpointOARest(
1585 : state)); // Assume if OA reset is lower than setting for secondary HW loop, then use the lower of the two
1586 : } else { // primary loop, auxiliary boiler
1587 0 : HWsetpt = DetermineHWSetpointOARest(state);
1588 : }
1589 :
1590 0 : HWsetpt = HWsetpt - this->TempReset.BoilerTemperatureOffset;
1591 :
1592 : // check inlet temperature
1593 0 : int inletBoilerNodeNum = state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum)
1594 0 : .LoopSide(this->PlantBoilerComps(BoilerNum).loopSideNum)
1595 0 : .Branch(this->PlantBoilerComps(BoilerNum).branchNum)
1596 0 : .Comp(this->PlantBoilerComps(BoilerNum).compNum)
1597 0 : .NodeNumIn;
1598 0 : Real64 Tin = state.dataLoopNodes->Node(inletBoilerNodeNum).Temp;
1599 0 : Real64 Mdot = state.dataLoopNodes->Node(inletBoilerNodeNum).MassFlowRate;
1600 :
1601 0 : Real64 const CpHW = state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum)
1602 0 : .glycol->getSpecificHeat(state, Tin, "ChillerHeaterSupervisoryOperationData::ProcessAndSetAuxilBoiler");
1603 0 : Real64 LoadToSetpoint = max(0.0, Mdot * CpHW * (HWsetpt - Tin));
1604 0 : int pltSizNum = state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum).PlantSizNum;
1605 : Real64 const thresholdPlantLoad =
1606 0 : 0.001 * state.dataSize->PlantSizData(pltSizNum).DesCapacity; // model an operating threshold at 0.1% of loop capacity, only run if
1607 : // larger than that
1608 :
1609 0 : if (((LoadToSetpoint > thresholdPlantLoad) &&
1610 0 : ((this->Report.AirSourcePlant_OpMode == 0) ||
1611 0 : LowOAAuxiliaryNeeded)) || // run boiler if there is any heating load and also heatpumps are off or too cold outside
1612 0 : ((LoadToSetpoint > thresholdPlantLoad) &&
1613 0 : (this->Report.AirSourcePlant_OpMode ==
1614 : 2))) { // run boiler if there is a somewhat significant heating load and heat pumps in cooling only mode
1615 :
1616 0 : state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum)
1617 0 : .LoopSide(this->PlantBoilerComps(BoilerNum).loopSideNum)
1618 0 : .Branch(this->PlantBoilerComps(BoilerNum).branchNum)
1619 0 : .Comp(this->PlantBoilerComps(BoilerNum).compNum)
1620 0 : .Available = true;
1621 0 : state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum)
1622 0 : .LoopSide(this->PlantBoilerComps(BoilerNum).loopSideNum)
1623 0 : .Branch(this->PlantBoilerComps(BoilerNum).branchNum)
1624 0 : .Comp(this->PlantBoilerComps(BoilerNum).compNum)
1625 0 : .ON = true;
1626 0 : state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum)
1627 0 : .LoopSide(this->PlantBoilerComps(BoilerNum).loopSideNum)
1628 0 : .Branch(this->PlantBoilerComps(BoilerNum).branchNum)
1629 0 : .Comp(this->PlantBoilerComps(BoilerNum).compNum)
1630 0 : .CurOpSchemeType = this->Type;
1631 : // boilers don't really have setpoint control mode, so set value for myLoad
1632 0 : state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum)
1633 0 : .LoopSide(this->PlantBoilerComps(BoilerNum).loopSideNum)
1634 0 : .Branch(this->PlantBoilerComps(BoilerNum).branchNum)
1635 0 : .Comp(this->PlantBoilerComps(BoilerNum).compNum)
1636 0 : .MyLoad = LoadToSetpoint;
1637 0 : int OutletBoilerNodeNum = state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum)
1638 0 : .LoopSide(this->PlantBoilerComps(BoilerNum).loopSideNum)
1639 0 : .Branch(this->PlantBoilerComps(BoilerNum).branchNum)
1640 0 : .Comp(this->PlantBoilerComps(BoilerNum).compNum)
1641 0 : .NodeNumOut;
1642 0 : state.dataLoopNodes->Node(OutletBoilerNodeNum).TempSetPoint = HWsetpt;
1643 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum).TempSetPointNodeNum).TempSetPoint =
1644 : HWsetpt;
1645 0 : this->Report.BoilerAux_OpMode = 1;
1646 0 : } else { // still apply the setpoint, but don't turn on
1647 0 : int OutletBoilerNodeNum = state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum)
1648 0 : .LoopSide(this->PlantBoilerComps(BoilerNum).loopSideNum)
1649 0 : .Branch(this->PlantBoilerComps(BoilerNum).branchNum)
1650 0 : .Comp(this->PlantBoilerComps(BoilerNum).compNum)
1651 0 : .NodeNumOut;
1652 0 : state.dataLoopNodes->Node(OutletBoilerNodeNum).TempSetPoint = HWsetpt;
1653 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->PlantBoilerComps(BoilerNum).loopNum).TempSetPointNodeNum).TempSetPoint =
1654 : HWsetpt;
1655 : }
1656 : }
1657 : }
1658 : }
1659 :
1660 15 : Real64 ChillerHeaterSupervisoryOperationData::DetermineHWSetpointOARest(EnergyPlusData &state)
1661 : {
1662 : // algorithm from calcSetPointLinInt
1663 15 : Real64 HWSetpoint = 0.0;
1664 :
1665 15 : if ((this->TempReset.LowOutdoorTemp == this->TempReset.BackupLowOutdoorTemp) &&
1666 15 : (this->Setpoint.PrimHW_Low == this->Setpoint.PrimHW_BackupLow)) { // no second-stage reset scheme
1667 :
1668 15 : if (this->TempReset.LowOutdoorTemp < this->TempReset.HighOutdoorTemp) {
1669 15 : if (state.dataEnvrn->OutDryBulbTemp <= this->TempReset.LowOutdoorTemp) {
1670 15 : HWSetpoint = this->Setpoint.PrimHW_Low;
1671 0 : } else if (state.dataEnvrn->OutDryBulbTemp >= this->TempReset.HighOutdoorTemp) {
1672 0 : HWSetpoint = this->Setpoint.PrimHW_High;
1673 : } else {
1674 0 : HWSetpoint = this->Setpoint.PrimHW_Low - ((state.dataEnvrn->OutDryBulbTemp - this->TempReset.LowOutdoorTemp) /
1675 0 : (this->TempReset.HighOutdoorTemp - this->TempReset.LowOutdoorTemp)) *
1676 0 : (this->Setpoint.PrimHW_Low - this->Setpoint.PrimHW_High);
1677 0 : HWSetpoint = min(HWSetpoint, this->Setpoint.PrimHW_High); // don't extrapolate, hold at high limit of primary HW
1678 : }
1679 :
1680 : } else {
1681 0 : HWSetpoint = 0.5 * (this->Setpoint.PrimHW_Low + this->Setpoint.PrimHW_High);
1682 : }
1683 : } else { // apply two stage reset scheme
1684 0 : if ((this->TempReset.LowOutdoorTemp < this->TempReset.HighOutdoorTemp) &&
1685 0 : (this->TempReset.BackupLowOutdoorTemp < this->TempReset.LowOutdoorTemp)) { // expected configuration
1686 :
1687 0 : if (state.dataEnvrn->OutDryBulbTemp <= this->TempReset.BackupLowOutdoorTemp) {
1688 0 : HWSetpoint = this->Setpoint.PrimHW_BackupLow;
1689 0 : } else if (state.dataEnvrn->OutDryBulbTemp >= this->TempReset.HighOutdoorTemp) {
1690 0 : HWSetpoint = this->Setpoint.PrimHW_High;
1691 0 : } else if ((state.dataEnvrn->OutDryBulbTemp >= this->TempReset.LowOutdoorTemp) &&
1692 0 : (state.dataEnvrn->OutDryBulbTemp < this->TempReset.HighOutdoorTemp)) { // first stage for Heat pump reset down
1693 0 : HWSetpoint = this->Setpoint.PrimHW_Low - ((state.dataEnvrn->OutDryBulbTemp - this->TempReset.LowOutdoorTemp) /
1694 0 : (this->TempReset.HighOutdoorTemp - this->TempReset.LowOutdoorTemp)) *
1695 0 : (this->Setpoint.PrimHW_Low - this->Setpoint.PrimHW_High);
1696 0 : HWSetpoint = min(HWSetpoint, this->Setpoint.PrimHW_High); // don't extrapolate, hold at high limit of primary HW
1697 0 : } else if ((state.dataEnvrn->OutDryBulbTemp > this->TempReset.BackupLowOutdoorTemp) &&
1698 0 : (state.dataEnvrn->OutDryBulbTemp < this->TempReset.LowOutdoorTemp)) { // second stage for backup boiler reset up
1699 0 : HWSetpoint = this->Setpoint.PrimHW_BackupLow - ((state.dataEnvrn->OutDryBulbTemp - this->TempReset.BackupLowOutdoorTemp) /
1700 0 : (this->TempReset.LowOutdoorTemp - this->TempReset.BackupLowOutdoorTemp)) *
1701 0 : (this->Setpoint.PrimHW_BackupLow - this->Setpoint.PrimHW_Low);
1702 0 : HWSetpoint = min(HWSetpoint, this->Setpoint.PrimHW_BackupLow); // don't extrapolate
1703 0 : HWSetpoint = max(HWSetpoint, this->Setpoint.PrimHW_Low); // don't extrapolate
1704 : } else {
1705 : // shouldn't get here, throw error?
1706 : }
1707 : } else { // malformed input, take average of three setpoints
1708 0 : HWSetpoint = (this->Setpoint.PrimHW_Low + this->Setpoint.PrimHW_High + this->Setpoint.PrimHW_BackupLow) / 3.0;
1709 : }
1710 : }
1711 15 : return HWSetpoint;
1712 : }
1713 :
1714 : } // namespace DataPlant
1715 : } // namespace EnergyPlus
|