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