Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <algorithm>
50 : #include <cassert>
51 : #include <cmath>
52 : #include <vector>
53 :
54 : // ObjexxFCL Headers
55 : #include <ObjexxFCL/Array.functions.hh>
56 : #include <ObjexxFCL/Array1D.hh>
57 : #include <ObjexxFCL/Fmath.hh>
58 :
59 : // EnergyPlus Headers
60 : #include <EnergyPlus/Autosizing/Base.hh>
61 : #include <EnergyPlus/BranchNodeConnections.hh>
62 : #include <EnergyPlus/Data/EnergyPlusData.hh>
63 : #include <EnergyPlus/DataEnvironment.hh>
64 : #include <EnergyPlus/DataHVACGlobals.hh>
65 : #include <EnergyPlus/DataIPShortCuts.hh>
66 : #include <EnergyPlus/DataRuntimeLanguage.hh>
67 : #include <EnergyPlus/DataSizing.hh>
68 : #include <EnergyPlus/EMSManager.hh>
69 : #include <EnergyPlus/FluidProperties.hh>
70 : #include <EnergyPlus/General.hh>
71 : #include <EnergyPlus/GeneralRoutines.hh>
72 : #include <EnergyPlus/GlobalNames.hh>
73 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
74 : #include <EnergyPlus/NodeInputManager.hh>
75 : #include <EnergyPlus/Plant/DataPlant.hh>
76 : #include <EnergyPlus/Plant/EquipAndOperations.hh>
77 : #include <EnergyPlus/PlantCondLoopOperation.hh>
78 : #include <EnergyPlus/PlantUtilities.hh>
79 : #include <EnergyPlus/PluginManager.hh>
80 : #include <EnergyPlus/ScheduleManager.hh>
81 : #include <EnergyPlus/SetPointManager.hh>
82 : #include <EnergyPlus/UtilityRoutines.hh>
83 :
84 : namespace EnergyPlus::PlantCondLoopOperation {
85 :
86 : // MODIFIED LKL Sep 03: adding integer/pointers for various parts of operation schemes
87 : // MODIFIED DEF JUL 10: complete re-write to support new Plant manager
88 :
89 : // PURPOSE OF THIS MODULE: This module assigns loads to the equipment on
90 : // the plant and condenser loops that will operate
91 : // for a given timestep.
92 :
93 : // METHODOLOGY EMPLOYED: The main driver, "ManagePlantLoadDistribution",
94 : // gets 'Plant Operation scheme' and 'Plant Equipment List' input. Pointers are
95 : // set up in the PlantLoop data structure to allow components to directly access the
96 : // operation schemes and plant lists that the component shows up on.
97 : // ManagePlantLoadDistribution is called one time for each component on the loop.
98 : // It finds the operation scheme and equipment list associated with the component
99 : // and calculates the component load. If the component is part of a 'load range'
100 : // based scheme, it also assigns a component load to each of the components on the
101 : // equipment list.
102 :
103 : // Using/Aliasing
104 : using namespace DataPlant;
105 : using FluidProperties::GetSpecificHeatGlycol;
106 : using HVAC::SmallLoad;
107 :
108 38710704 : void ManagePlantLoadDistribution(EnergyPlusData &state,
109 : PlantLocation const &plantLoc, // PlantLoop data structure Location struct
110 : Real64 &LoopDemand,
111 : Real64 &RemLoopDemand,
112 : bool const FirstHVACIteration,
113 : bool &LoopShutDownFlag, // EMS flag to tell loop solver to shut down pumps
114 : bool &LoadDistributionWasPerformed)
115 : {
116 : // SUBROUTINE INFORMATION:
117 : // AUTHOR: Dan Fisher
118 : // DATE WRITTEN: April 1999
119 : // REVISED: March 2001
120 : // July 2001, Rick Strand (revision of pump and loop control code)
121 : // July 2010, Dan Fisher, complete rewrite to component based control
122 :
123 : // PURPOSE OF THIS SUBROUTINE:
124 : // ManageLoopOperation is the driver routine
125 : // for plant equipment selection. It calls the general "Get-
126 : // Input" routines, initializes the loop pointers, then calls the
127 : // appropriate type of control algorithm (setpoint, load range based,
128 : // or uncontrolled) for the component
129 :
130 : // Indices in PlantLoop.LoopSide.Branch.Comp data structure
131 : int CurCompLevelOpNum; // This is set by the init routine at each FirstHVACIteration.
132 : // It tells which scheme for this component is currently scheduled
133 : // and is used to avoid a 'schedule search' on each call
134 : // It is used as the OpScheme index in PlantLoop.LoopSide.Branch.Comp.OpScheme(CurCompLevelOpNum)
135 : // Value of pointers held in PlantLoop.LoopSide.Branch.Comp() data structure
136 : // Used as indices in PlantLoop.OpScheme() data structure
137 : int CurSchemePtr; // set by PlantLoop.LoopSide.Branch.Comp.OpScheme.OpSchemePtr
138 : // used to locate data in PL()%OpScheme(CurSchemePtr)
139 : // used to locate data in PL()%OpScheme(CurSchemePtr)%EquipList(ListPtr)
140 : // Local values from the PlantLoop()%OpScheme() data structure
141 38710704 : Real64 RangeVariable(0.0); // holds the 'loop demand', wetbulb temp, etc.
142 : Real64 TestRangeVariable; // abs of RangeVariable for logic tests etc.
143 : Real64 RangeHiLimit; // upper limit of the range variable
144 : Real64 RangeLoLimit; // lower limit of the range variable
145 : // Local values from the PlantLoop()%LoopSide()%Branch()%Comp() data structure
146 : int NumEquipLists; // number of equipment lists
147 : // Error control flags
148 :
149 : // Shut down equipment and return if so instructed by LoopShutDownFlag
150 38710704 : if (LoopShutDownFlag) {
151 8356 : TurnOffLoopEquipment(state, plantLoc.loopNum);
152 8356 : return;
153 : }
154 :
155 : // Return if there are no loop operation schemes available
156 38702348 : if (!std::any_of(state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme.begin(),
157 38702348 : state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme.end(),
158 41472260 : [](DataPlant::OperationData const &e) { return e.Available; }))
159 0 : return;
160 :
161 : // set up references
162 38702348 : auto &loop_side = state.dataPlnt->PlantLoop(plantLoc.loopNum).LoopSide(plantLoc.loopSideNum);
163 38702348 : auto &this_component = loop_side.Branch(plantLoc.branchNum).Comp(plantLoc.compNum);
164 :
165 : // Implement EMS control commands
166 38702348 : ActivateEMSControls(state, plantLoc, LoopShutDownFlag);
167 :
168 : // Schedules are checked and CurOpScheme updated on FirstHVACIteration in InitLoadDistribution
169 : // Here we just load CurOpScheme to a local variable
170 38702348 : CurCompLevelOpNum = this_component.CurCompLevelOpNum;
171 : // If no current operation scheme for component, RETURN
172 38702348 : if (CurCompLevelOpNum == 0) return;
173 : // set local variables from data structure
174 38702348 : NumEquipLists = this_component.OpScheme(CurCompLevelOpNum).NumEquipLists;
175 38702348 : CurSchemePtr = this_component.OpScheme(CurCompLevelOpNum).OpSchemePtr;
176 38702348 : DataPlant::OpScheme CurSchemeType = state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).Type;
177 :
178 : // another reference
179 38702348 : auto &this_op_scheme = state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr);
180 :
181 : // Load the 'range variable' according to the type of control scheme specified
182 38702348 : switch (CurSchemeType) {
183 1160704 : case OpScheme::Uncontrolled:
184 : case OpScheme::CompSetPtBased: {
185 : // No RangeVariable specified for these types
186 1160704 : break;
187 : }
188 322816 : case OpScheme::EMS: {
189 322816 : InitLoadDistribution(state, FirstHVACIteration);
190 : // No RangeVariable specified for these types
191 322816 : break;
192 : }
193 15895078 : case OpScheme::HeatingRB: {
194 : // For zero demand, we need to clean things out before we leave
195 15895078 : if (LoopDemand < SmallLoad) {
196 6793266 : InitLoadDistribution(state, FirstHVACIteration);
197 6793266 : this_component.MyLoad = 0.0;
198 6793266 : this_component.ON = false;
199 6793266 : return;
200 : }
201 9101812 : RangeVariable = LoopDemand;
202 9101812 : break;
203 : }
204 20865874 : case OpScheme::CoolingRB: {
205 : // For zero demand, we need to clean things out before we leave
206 20865874 : if (LoopDemand > (-1.0 * SmallLoad)) {
207 12437831 : InitLoadDistribution(state, FirstHVACIteration);
208 12437831 : this_component.MyLoad = 0.0;
209 12437831 : this_component.ON = false;
210 12437831 : return;
211 : }
212 8428043 : RangeVariable = LoopDemand;
213 8428043 : break;
214 : }
215 14544 : case OpScheme::DryBulbRB: {
216 14544 : RangeVariable = state.dataEnvrn->OutDryBulbTemp;
217 14544 : break;
218 : }
219 14544 : case OpScheme::WetBulbRB: {
220 14544 : RangeVariable = state.dataEnvrn->OutWetBulbTemp;
221 14544 : break;
222 : }
223 14544 : case OpScheme::RelHumRB: {
224 14544 : RangeVariable = state.dataEnvrn->OutRelHum;
225 14544 : break;
226 : }
227 14544 : case OpScheme::DewPointRB: {
228 14544 : RangeVariable = state.dataEnvrn->OutDewPointTemp;
229 14544 : break;
230 : }
231 399700 : case OpScheme::DryBulbTDB:
232 : case OpScheme::WetBulbTDB:
233 : case OpScheme::DewPointTDB: {
234 399700 : RangeVariable = FindRangeVariable(state, plantLoc.loopNum, CurSchemePtr, CurSchemeType);
235 399700 : break;
236 : }
237 0 : default: {
238 : // No controls specified. This is a fatal error
239 0 : ShowFatalError(state,
240 0 : format("Invalid Operation Scheme Type Requested={}, in ManagePlantLoadDistribution",
241 0 : state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).TypeOf));
242 : }
243 : }
244 :
245 19471251 : switch (CurSchemeType) {
246 0 : case OpScheme::Uncontrolled: {
247 : //!***what else do we do with 'uncontrolled' equipment?
248 : // There's an equipment list...but I think the idea is to just
249 : // Set one component to run in an 'uncontrolled' way (whatever that means!)
250 0 : break;
251 : }
252 1160704 : case OpScheme::CompSetPtBased: {
253 : // check for EMS Control
254 1160704 : TurnOnPlantLoopPipes(state, plantLoc.loopNum, plantLoc.loopSideNum);
255 1160704 : FindCompSPLoad(state, plantLoc, CurCompLevelOpNum);
256 1160704 : break;
257 : }
258 322816 : case OpScheme::EMS: {
259 322816 : TurnOnPlantLoopPipes(state, plantLoc.loopNum, plantLoc.loopSideNum);
260 322816 : DistributeUserDefinedPlantLoad(state, plantLoc, CurCompLevelOpNum, CurSchemePtr, LoopDemand, RemLoopDemand);
261 322816 : break;
262 : }
263 17987731 : default: { // it's a range based control type with multiple equipment lists
264 17987731 : int ListPtr = 0;
265 17987731 : int CurListNum = 0;
266 18417031 : for (int ListNum = 1; ListNum <= NumEquipLists; ++ListNum) {
267 : // setpointers to 'PlantLoop()%OpScheme()...'structure
268 18125893 : ListPtr = this_component.OpScheme(CurCompLevelOpNum).EquipList(ListNum).ListPtr;
269 18125893 : RangeHiLimit = this_op_scheme.EquipList(ListPtr).RangeUpperLimit;
270 18125893 : RangeLoLimit = this_op_scheme.EquipList(ListPtr).RangeLowerLimit;
271 18125893 : if (CurSchemeType == OpScheme::HeatingRB || CurSchemeType == OpScheme::CoolingRB) {
272 : // these limits are stored with absolute values, but the LoopDemand can be negative for cooling
273 17638075 : TestRangeVariable = std::abs(RangeVariable);
274 : } else {
275 487818 : TestRangeVariable = RangeVariable;
276 : }
277 :
278 : // trying to do something where the last stage still runs the equipment but at the hi limit.
279 :
280 18125893 : if (TestRangeVariable < RangeLoLimit || TestRangeVariable > RangeHiLimit) {
281 465708 : if ((TestRangeVariable > RangeHiLimit) && (ListPtr == this_op_scheme.EquipListNumForLastStage)) {
282 : // let this go thru, later AdjustChangeInLoadForLastStageUpperRangeLimit will cap dispatch to RangeHiLimit
283 36408 : CurListNum = ListNum;
284 36408 : break;
285 : } else {
286 429300 : continue;
287 : }
288 : } else {
289 17660185 : CurListNum = ListNum;
290 17660185 : break;
291 : }
292 : }
293 :
294 17987731 : if (CurListNum > 0) {
295 : // there could be equipment on another list that needs to be nulled out, it may have a load from earlier iteration
296 35644218 : for (int ListNum = 1; ListNum <= NumEquipLists; ++ListNum) {
297 17947625 : if (ListNum == CurListNum) continue; // leave current one alone
298 251032 : int NumCompsOnList = this_op_scheme.EquipList(ListNum).NumComps;
299 582618 : for (int CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
300 331586 : int EquipBranchNum = this_op_scheme.EquipList(ListNum).Comp(CompIndex).BranchNumPtr;
301 331586 : int EquipCompNum = this_op_scheme.EquipList(ListNum).Comp(CompIndex).CompNumPtr;
302 331586 : loop_side.Branch(EquipBranchNum).Comp(EquipCompNum).MyLoad = 0.0;
303 : }
304 : }
305 17696593 : if (this_op_scheme.EquipList(ListPtr).NumComps > 0) {
306 17696593 : TurnOnPlantLoopPipes(state, plantLoc.loopNum, plantLoc.loopSideNum);
307 17696593 : DistributePlantLoad(state, plantLoc.loopNum, plantLoc.loopSideNum, CurSchemePtr, ListPtr, LoopDemand, RemLoopDemand);
308 17696593 : LoadDistributionWasPerformed = true;
309 : }
310 : }
311 :
312 : } // End of range based schemes
313 : }
314 : }
315 :
316 : // Beginning of GetInput subroutines for the Module
317 : //******************************************************************************
318 :
319 458 : void GetPlantOperationInput(EnergyPlusData &state, bool &GetInputOK)
320 : {
321 :
322 : // SUBROUTINE INFORMATION:
323 : // AUTHOR Dan Fisher
324 : // DATE WRITTEN October 1998
325 : // MODIFIED July 2010, Dan Fisher, restructure input data
326 : // RE-ENGINEERED na
327 :
328 : // PURPOSE OF THIS SUBROUTINE: This subroutine reads the primary plant loop
329 : // operation schemes from the input file
330 :
331 : // METHODOLOGY EMPLOYED: calls the Input Processor to retrieve data from input file.
332 : // The format of the Energy+.idd (the EnergyPlus input data dictionary) for the
333 : // following keywords is reflected exactly in this subroutine:
334 : // PlantEquipmentOperationSchemes
335 : // CondenserEquipmentOperationSchemes
336 :
337 : // Using/Aliasing
338 : using ScheduleManager::GetScheduleIndex;
339 :
340 : // SUBROUTINE PARAMETER DEFINITIONS:
341 : static constexpr std::string_view RoutineName("GetPlantOperationInput: "); // include trailing blank space
342 :
343 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
344 : int LoopNum; // Loop counter (Plant or Cond)
345 : int OpNum; // Scheme counter
346 : int Num; // Item counter
347 : int NumPlantOpSchemes; // Total Number of PlantEquipmentOperationSchemes
348 : int NumCondOpSchemes; // Total Number of CondenserEquipmentOperationSchemes
349 : int NumAlphas; // Number of alpha items in the input object
350 : int NumNums; // Number of numeric items in the input object
351 : int IOStat;
352 458 : std::string CurrentModuleObject; // for ease in renaming
353 458 : std::string PlantLoopObject; // for ease in renaming
354 : bool ErrorsFound; // Passed in from OpSchemeInput
355 :
356 458 : ErrorsFound = false;
357 :
358 458 : if (!allocated(state.dataPlnt->PlantLoop)) {
359 0 : GetInputOK = false;
360 0 : return;
361 : } else {
362 458 : GetInputOK = true;
363 : }
364 :
365 : // get number of operation schemes
366 458 : CurrentModuleObject = "PlantEquipmentOperationSchemes";
367 458 : NumPlantOpSchemes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
368 1341 : for (OpNum = 1; OpNum <= NumPlantOpSchemes; ++OpNum) {
369 1766 : state.dataInputProcessing->inputProcessor->getObjectItem(
370 883 : state, CurrentModuleObject, OpNum, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNums, IOStat);
371 883 : if (Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), CurrentModuleObject, ErrorsFound)) continue;
372 : }
373 :
374 458 : CurrentModuleObject = "CondenserEquipmentOperationSchemes";
375 458 : NumCondOpSchemes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
376 718 : for (OpNum = 1; OpNum <= NumCondOpSchemes; ++OpNum) {
377 520 : state.dataInputProcessing->inputProcessor->getObjectItem(
378 260 : state, CurrentModuleObject, OpNum, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNums, IOStat);
379 260 : if (Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), CurrentModuleObject, ErrorsFound)) continue;
380 : }
381 :
382 : // Load the Plant data structure
383 1605 : for (LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
384 1147 : std::string PlantOpSchemeName = state.dataPlnt->PlantLoop(LoopNum).OperationScheme;
385 1147 : if (LoopNum <= state.dataHVACGlobal->NumPlantLoops) {
386 889 : CurrentModuleObject = "PlantEquipmentOperationSchemes";
387 889 : PlantLoopObject = "PlantLoop";
388 : } else {
389 258 : CurrentModuleObject = "CondenserEquipmentOperationSchemes";
390 258 : PlantLoopObject = "CondenserLoop";
391 : }
392 1147 : OpNum = state.dataInputProcessing->inputProcessor->getObjectItemNum(state, CurrentModuleObject, PlantOpSchemeName);
393 1147 : if (OpNum > 0) {
394 2294 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
395 : CurrentModuleObject,
396 : OpNum,
397 1147 : state.dataIPShortCut->cAlphaArgs,
398 : NumAlphas,
399 1147 : state.dataIPShortCut->rNumericArgs,
400 : NumNums,
401 : IOStat,
402 1147 : state.dataIPShortCut->lNumericFieldBlanks,
403 1147 : state.dataIPShortCut->lAlphaFieldBlanks,
404 1147 : state.dataIPShortCut->cAlphaFieldNames,
405 1147 : state.dataIPShortCut->cNumericFieldNames);
406 1147 : state.dataPlnt->PlantLoop(LoopNum).NumOpSchemes = (NumAlphas - 1) / 3;
407 1147 : if (state.dataPlnt->PlantLoop(LoopNum).NumOpSchemes > 0) {
408 1147 : state.dataPlnt->PlantLoop(LoopNum).OpScheme.clear();
409 1147 : state.dataPlnt->PlantLoop(LoopNum).OpScheme.allocate(state.dataPlnt->PlantLoop(LoopNum).NumOpSchemes);
410 2416 : for (Num = 1; Num <= state.dataPlnt->PlantLoop(LoopNum).NumOpSchemes; ++Num) {
411 1269 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).TypeOf = state.dataIPShortCut->cAlphaArgs(Num * 3 - 1);
412 :
413 : {
414 1269 : std::string const &plantLoopOperation = state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).TypeOf;
415 1269 : if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:COOLINGLOAD") {
416 695 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::CoolingRB;
417 574 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:HEATINGLOAD") {
418 494 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::HeatingRB;
419 80 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:COMPONENTSETPOINT") { //* Temp Based Control
420 14 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::CompSetPtBased;
421 66 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:CHILLERHEATERCHANGEOVER") {
422 10 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::ChillerHeaterSupervisory;
423 56 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:THERMALENERGYSTORAGE") { //* Simple TES Control
424 1 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type =
425 : OpScheme::CompSetPtBased; // set this to component based as it will be converted to this
426 55 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:USERDEFINED") {
427 6 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::EMS;
428 6 : state.dataPlnt->AnyEMSPlantOpSchemesInModel = true;
429 49 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDRYBULB") {
430 1 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::DryBulbRB;
431 48 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORWETBULB") {
432 1 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::WetBulbRB;
433 47 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDEWPOINT") {
434 1 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::DewPointRB;
435 46 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORRELATIVEHUMIDITY") {
436 1 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::RelHumRB;
437 45 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDRYBULBDIFFERENCE") {
438 1 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::DryBulbTDB;
439 44 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORWETBULBDIFFERENCE") {
440 1 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::WetBulbTDB;
441 43 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDEWPOINTDIFFERENCE") {
442 1 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::DewPointTDB;
443 42 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:UNCONTROLLED") {
444 42 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Type = OpScheme::Uncontrolled;
445 : } else { // invalid op scheme type for plant loop
446 0 : ShowSevereError(state,
447 0 : format("{}Invalid {}={}, entered in {}={}",
448 : RoutineName,
449 0 : state.dataIPShortCut->cAlphaFieldNames(Num * 3 - 1),
450 0 : state.dataIPShortCut->cAlphaArgs(Num * 3 - 1),
451 : CurrentModuleObject,
452 0 : state.dataIPShortCut->cAlphaArgs(1)));
453 0 : ErrorsFound = true;
454 : }
455 : }
456 :
457 1269 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Name = state.dataIPShortCut->cAlphaArgs(Num * 3);
458 1269 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Sched = state.dataIPShortCut->cAlphaArgs(Num * 3 + 1);
459 1269 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).SchedPtr =
460 1269 : GetScheduleIndex(state, state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).Sched);
461 1269 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(Num).SchedPtr == 0) {
462 0 : ShowSevereError(state,
463 0 : format("{}Invalid {} = \"{}\", entered in {}= \"{}\".",
464 : RoutineName,
465 0 : state.dataIPShortCut->cAlphaFieldNames(Num * 3 + 1),
466 0 : state.dataIPShortCut->cAlphaArgs(Num * 3 + 1),
467 : CurrentModuleObject,
468 0 : state.dataIPShortCut->cAlphaArgs(1)));
469 0 : ErrorsFound = true;
470 : }
471 : }
472 : } else {
473 0 : ShowSevereError(state,
474 0 : format("{} = \"{}\", requires at least {}, {} and {} to be specified.",
475 : CurrentModuleObject,
476 0 : state.dataIPShortCut->cAlphaArgs(1),
477 0 : state.dataIPShortCut->cAlphaFieldNames(2),
478 0 : state.dataIPShortCut->cAlphaFieldNames(3),
479 0 : state.dataIPShortCut->cAlphaFieldNames(4)));
480 0 : ErrorsFound = true;
481 : }
482 : } else {
483 0 : ShowSevereError(state, format("{}{}={} is expecting", RoutineName, PlantLoopObject, state.dataPlnt->PlantLoop(LoopNum).Name));
484 0 : ShowContinueError(state, format("{}={}, but not found.", CurrentModuleObject, PlantOpSchemeName));
485 0 : ErrorsFound = true;
486 : }
487 1147 : }
488 :
489 458 : if (ErrorsFound) {
490 0 : ShowFatalError(
491 0 : state, format("{}Errors found in getting input for PlantEquipmentOperationSchemes or CondenserEquipmentOperationSchemes", RoutineName));
492 : }
493 458 : }
494 :
495 458 : void GetOperationSchemeInput(EnergyPlusData &state)
496 : {
497 :
498 : // SUBROUTINE INFORMATION:
499 : // AUTHOR Dan Fisher
500 : // DATE WRITTEN October 1998
501 : // MODIFIED August 2001, LKL -- Validations
502 : // RE-ENGINEERED July 2010, Dan Fisher, restructure input data
503 :
504 : // PURPOSE OF THIS SUBROUTINE:
505 : // This subroutine reads the primary plant loop
506 : // operation schemes from the input file
507 :
508 : // METHODOLOGY EMPLOYED:
509 : // calls the Input Processor to retrieve data from input file.
510 : // The format of the Energy+.idd (the EnergyPlus input data dictionary) for the
511 : // following keywords is reflected exactly in this subroutine:
512 : // PlantEquipmentOperation:*
513 :
514 : // Using/Aliasing
515 : using namespace DataLoopNode;
516 : using namespace DataSizing;
517 :
518 : // SUBROUTINE PARAMETER DEFINITIONS:
519 : static constexpr std::string_view RoutineName("GetOperationSchemeInput: "); // include trailing blank space
520 :
521 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
522 : int SchemeNum;
523 : int Num;
524 : int NumAlphas;
525 : int NumNums;
526 : int IOStat;
527 : bool ErrorsFound; // May be set here and passed on
528 : int CLRBO; // Number ofCooling Load Range Based Operation Inputs
529 : int HLRBO; // Number ofHeating Load Range Based Operation Inputs
530 : int DBRBO; // Number ofDry Bulb Temperature Range Based Operation Inputs
531 : int WBRBO; // Number ofWet Bulb Temperature Range Based Operation Inputs
532 : int DPRBO; // Number ofDewPoint Temperature Range Based Operation Inputs
533 : int RHRBO; // Number ofRelative Humidity Range Based Operation Inputs
534 : int CSPBO; // Number of Component SetPoint Based Operation Inputs
535 : int DBTDBO; // Number ofDry Bulb Temperature Range Based Operation Inputs
536 : int WBTDBO; // Number ofWet Bulb Temperature Range Based Operation Inputs
537 : int DPTDBO; // Number ofDewPoint Temperature Range Based Operation Inputs
538 : int TESSPBO; // Number of Thermal Energy Storage Setpoint Based Operation Inputs
539 : int ACXSPBO; // Number of Chiller Heater setpoint based operation inputs
540 : int NumSchemes; // Number of Condenser equipment lists
541 : int NumUncontrolledSchemes; // Number of Condenser equipment lists
542 : int NumUserDefOpSchemes; // number of user defined EMS op schemes
543 : int CELists; // Number of Condenser equipment lists
544 : int PELists; // Number of Plant equipment lists
545 : int Count; // Loop counter
546 : int NumSchemeLists;
547 : int LoopNum;
548 458 : std::string CurrentModuleObject; // for ease in renaming.
549 458 : std::unordered_map<std::string, std::string> UniqueNames;
550 :
551 458 : ErrorsFound = false;
552 :
553 : //**********VERIFY THE 'PLANTEQUIPMENTOPERATION:...' KEYWORDS**********
554 458 : CLRBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:CoolingLoad");
555 458 : HLRBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:HeatingLoad");
556 458 : DBRBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorDryBulb");
557 458 : WBRBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorWetBulb");
558 458 : DPRBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorDewpoint");
559 458 : RHRBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorRelativeHumidity");
560 458 : CSPBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:ComponentSetpoint"); //* Temp Based Control
561 458 : NumUserDefOpSchemes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:UserDefined");
562 458 : DBTDBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorDryBulbDifference");
563 458 : WBTDBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorWetBulbDifference");
564 458 : DPTDBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:OutdoorDewpointDifference");
565 458 : TESSPBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:ThermalEnergyStorage");
566 458 : ACXSPBO = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:ChillerHeaterChangeover");
567 458 : NumSchemes = CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO + DPTDBO + NumUserDefOpSchemes + TESSPBO + ACXSPBO;
568 458 : NumUncontrolledSchemes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentOperation:Uncontrolled");
569 458 : if ((NumSchemes + NumUncontrolledSchemes) <= 0) {
570 0 : ShowFatalError(state, "No PlantEquipmentOperation:* objects specified. Stop simulation.");
571 : }
572 :
573 : // test for blank or duplicates -- this section just determines if there are any duplicate operation scheme names
574 458 : UniqueNames.reserve(static_cast<unsigned>(NumSchemes));
575 :
576 : // Check for existence of duplicates in keyword names
577 458 : Count = 0;
578 1687 : for (Num = 1; Num <= NumSchemes; ++Num) {
579 1229 : if (CLRBO > 0 && Num <= CLRBO) {
580 704 : CurrentModuleObject = "PlantEquipmentOperation:CoolingLoad";
581 704 : Count = Num;
582 525 : } else if (HLRBO > 0 && Num <= (CLRBO + HLRBO)) {
583 494 : CurrentModuleObject = "PlantEquipmentOperation:HeatingLoad";
584 494 : Count = Num - CLRBO;
585 31 : } else if (DBRBO > 0 && Num <= (CLRBO + HLRBO + DBRBO)) {
586 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorDryBulb";
587 1 : Count = Num - CLRBO - HLRBO;
588 30 : } else if (WBRBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO)) {
589 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorWetBulb";
590 1 : Count = Num - CLRBO - HLRBO - DBRBO;
591 29 : } else if (DPRBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO)) {
592 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorDewpoint";
593 1 : Count = Num - CLRBO - HLRBO - DBRBO - WBRBO;
594 28 : } else if (RHRBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO)) {
595 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorRelativeHumidity";
596 1 : Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO;
597 27 : } else if (CSPBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO)) {
598 14 : CurrentModuleObject = "PlantEquipmentOperation:ComponentSetpoint";
599 14 : Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO;
600 13 : } else if (DBTDBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO)) {
601 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorDryBulbDifference";
602 1 : Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO;
603 12 : } else if (WBTDBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO)) {
604 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorWetBulbDifference";
605 1 : Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO - DBTDBO;
606 11 : } else if (DPTDBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO + DPTDBO)) {
607 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorDewpointDifference";
608 1 : Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO - DBTDBO - WBTDBO;
609 10 : } else if (NumUncontrolledSchemes > 0 &&
610 1 : Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO + DPTDBO + NumUncontrolledSchemes)) {
611 1 : CurrentModuleObject = "PlantEquipmentOperation:Uncontrolled";
612 1 : Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO - DBTDBO - WBTDBO - DPTDBO;
613 9 : } else if (NumUserDefOpSchemes > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO + DPTDBO +
614 6 : NumUncontrolledSchemes + NumUserDefOpSchemes)) {
615 6 : CurrentModuleObject = "PlantEquipmentOperation:UserDefined";
616 6 : Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO - DBTDBO - WBTDBO - DPTDBO - NumUncontrolledSchemes;
617 3 : } else if (TESSPBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO + DPTDBO + NumUncontrolledSchemes +
618 1 : NumUserDefOpSchemes + TESSPBO)) {
619 1 : CurrentModuleObject = "PlantEquipmentOperation:ThermalEnergyStorage";
620 1 : Count =
621 1 : Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO - DBTDBO - WBTDBO - DPTDBO - NumUncontrolledSchemes - NumUserDefOpSchemes;
622 2 : } else if (ACXSPBO > 0 && Num <= (CLRBO + HLRBO + DBRBO + WBRBO + DPRBO + RHRBO + CSPBO + DBTDBO + WBTDBO + DPTDBO + NumUncontrolledSchemes +
623 2 : NumUserDefOpSchemes + TESSPBO + ACXSPBO)) {
624 2 : CurrentModuleObject = "PlantEquipmentOperation:ChillerHeaterChangeover";
625 2 : Count = Num - CLRBO - HLRBO - DBRBO - WBRBO - DPRBO - RHRBO - CSPBO - DBTDBO - WBTDBO - DPTDBO - NumUncontrolledSchemes -
626 : NumUserDefOpSchemes - TESSPBO;
627 : } else {
628 0 : ShowFatalError(state, "Error in control scheme identification");
629 : }
630 :
631 2458 : state.dataInputProcessing->inputProcessor->getObjectItem(
632 1229 : state, CurrentModuleObject, Count, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNums, IOStat);
633 1229 : if (GlobalNames::VerifyUniqueInterObjectName(state, UniqueNames, state.dataIPShortCut->cAlphaArgs(1), CurrentModuleObject, ErrorsFound)) {
634 0 : continue;
635 : }
636 : }
637 :
638 : //**********VERIFY THE 'PlantEquipmentList' AND 'CondenserEquipmentList' KEYWORDS*********
639 458 : PELists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentList");
640 458 : CELists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "CondenserEquipmentList");
641 458 : NumSchemeLists = PELists + CELists;
642 458 : UniqueNames.clear();
643 458 : UniqueNames.reserve(NumSchemeLists);
644 458 : Count = 0;
645 1952 : for (Num = 1; Num <= NumSchemeLists; ++Num) {
646 1494 : if (Num <= PELists) {
647 1225 : CurrentModuleObject = "PlantEquipmentList";
648 1225 : Count = Num;
649 : } else {
650 269 : CurrentModuleObject = "CondenserEquipmentList";
651 269 : Count = Num - PELists;
652 : }
653 2988 : state.dataInputProcessing->inputProcessor->getObjectItem(
654 1494 : state, CurrentModuleObject, Count, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNums, IOStat);
655 1494 : if (GlobalNames::VerifyUniqueInterObjectName(state, UniqueNames, state.dataIPShortCut->cAlphaArgs(1), CurrentModuleObject, ErrorsFound)) {
656 0 : continue;
657 : }
658 : }
659 :
660 : //**********GET INPUT AND LOAD PLANT DATA STRUCTURE*********
661 :
662 : // extend number of equipment lists to include one for each CSPBO
663 458 : NumSchemeLists += CSPBO + TESSPBO + NumUserDefOpSchemes;
664 1605 : for (LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
665 2416 : for (SchemeNum = 1; SchemeNum <= state.dataPlnt->PlantLoop(LoopNum).NumOpSchemes; ++SchemeNum) {
666 :
667 : {
668 1269 : std::string const &plantLoopOperation = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).TypeOf;
669 :
670 1269 : if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:COOLINGLOAD") {
671 695 : CurrentModuleObject = "PlantEquipmentOperation:CoolingLoad";
672 695 : FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, CLRBO, LoopNum, SchemeNum, ErrorsFound);
673 :
674 574 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:HEATINGLOAD") {
675 494 : CurrentModuleObject = "PlantEquipmentOperation:HeatingLoad";
676 494 : FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, HLRBO, LoopNum, SchemeNum, ErrorsFound);
677 :
678 80 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:COMPONENTSETPOINT") { //* Temp Based Control
679 14 : CurrentModuleObject = "PlantEquipmentOperation:ComponentSetPoint";
680 14 : FindCompSPInput(state, CurrentModuleObject, CSPBO, LoopNum, SchemeNum, ErrorsFound);
681 :
682 66 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:USERDEFINED") {
683 6 : CurrentModuleObject = "PlantEquipmentOperation:UserDefined";
684 6 : GetUserDefinedOpSchemeInput(state, CurrentModuleObject, NumUserDefOpSchemes, LoopNum, SchemeNum, ErrorsFound);
685 :
686 60 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDRYBULB") {
687 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorDryBulb";
688 1 : FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, DBRBO, LoopNum, SchemeNum, ErrorsFound);
689 :
690 59 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORWETBULB") {
691 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorWetBulb";
692 1 : FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, WBRBO, LoopNum, SchemeNum, ErrorsFound);
693 :
694 58 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDEWPOINT") {
695 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorDewPoint";
696 1 : FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, DPRBO, LoopNum, SchemeNum, ErrorsFound);
697 :
698 57 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORRELATIVEHUMIDITY") {
699 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorrelativeHumidity";
700 1 : FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, RHRBO, LoopNum, SchemeNum, ErrorsFound);
701 :
702 56 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDRYBULBDIFFERENCE") {
703 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorDryBulbDifference";
704 1 : FindDeltaTempRangeInput(state,
705 : DataLoopNode::ConnectionObjectType::PlantEquipmentOperationOutdoorDrybulbDifference,
706 : DBTDBO,
707 : LoopNum,
708 : SchemeNum,
709 : ErrorsFound);
710 :
711 55 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORWETBULBDIFFERENCE") {
712 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorWetBulbDifference";
713 1 : FindDeltaTempRangeInput(state,
714 : DataLoopNode::ConnectionObjectType::PlantEquipmentOperationOutdoorWetbulbDifference,
715 : WBTDBO,
716 : LoopNum,
717 : SchemeNum,
718 : ErrorsFound);
719 :
720 54 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:OUTDOORDEWPOINTDIFFERENCE") {
721 1 : CurrentModuleObject = "PlantEquipmentOperation:OutdoorDewPointDifference";
722 1 : FindDeltaTempRangeInput(state,
723 : DataLoopNode::ConnectionObjectType::PlantEquipmentOperationOutdoorDewpointDifference,
724 : DPTDBO,
725 : LoopNum,
726 : SchemeNum,
727 : ErrorsFound);
728 :
729 53 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:UNCONTROLLED") {
730 42 : CurrentModuleObject = "PlantEquipmentOperation:Uncontrolled";
731 42 : FindRangeBasedOrUncontrolledInput(state, CurrentModuleObject, NumUncontrolledSchemes, LoopNum, SchemeNum, ErrorsFound);
732 :
733 11 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:THERMALENERGYSTORAGE") { //* Temp Based Control
734 1 : CurrentModuleObject = "PlantEquipmentOperation:ThermalEnergyStorage";
735 1 : FindCompSPInput(state, CurrentModuleObject, TESSPBO, LoopNum, SchemeNum, ErrorsFound);
736 :
737 10 : } else if (plantLoopOperation == "PLANTEQUIPMENTOPERATION:CHILLERHEATERCHANGEOVER") {
738 10 : CurrentModuleObject = "PlantEquipmentOperation:ChillerHeaterChangeover";
739 10 : GetChillerHeaterChangeoverOpSchemeInput(state, CurrentModuleObject, ACXSPBO, ErrorsFound);
740 :
741 : } else { // invalid op scheme type for plant loop
742 : // Seems like the alpha args below is incorrect....
743 0 : ShowSevereError(state,
744 0 : format("Invalid operation scheme type = \"{}\", entered in {}={}",
745 0 : state.dataIPShortCut->cAlphaArgs(Num * 3 - 1),
746 : CurrentModuleObject,
747 0 : state.dataIPShortCut->cAlphaArgs(1)));
748 0 : ErrorsFound = true;
749 : }
750 : }
751 :
752 : // At this point, switch the thermal energy storage controls to setpoint based controls as all of the
753 : // internally generated setpoints and schedules have been generated and this can now be handled like
754 : // the long form setpoint based control.
755 1269 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).TypeOf == "PLANTEQUIPMENTOPERATION:THERMALENERGYSTORAGE") {
756 1 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).TypeOf = "PLANTEQUIPMENTOPERATION:COMPONENTSETPOINT";
757 : }
758 : }
759 : }
760 :
761 : // Validate that component names/types in each list correspond to a valid component in input file
762 458 : if (ErrorsFound) {
763 0 : ShowFatalError(state, format("{}Errors found getting inputs. Previous error(s) cause program termination.", RoutineName));
764 : }
765 458 : }
766 :
767 1235 : void FindRangeBasedOrUncontrolledInput(EnergyPlusData &state,
768 : std::string &CurrentModuleObject, // for ease in renaming
769 : int const NumSchemes, // May be set here and passed on
770 : int const LoopNum, // May be set here and passed on
771 : int const SchemeNum, // May be set here and passed on
772 : bool &ErrorsFound // May be set here and passed on
773 : )
774 : {
775 : // SUBROUTINE INFORMATION:
776 : // AUTHOR Dan Fisher
777 : // DATE WRITTEN July 2010
778 : // MODIFIED Chandan Sharma, August 2010
779 : // RE-ENGINEERED na
780 :
781 : // PURPOSE OF THIS SUBROUTINE:
782 : // Load range based or uncontrolled input into PLANTLOOP data structure
783 :
784 : // METHODOLOGY EMPLOYED:
785 : // calls the Input Processor to retrieve data from input file.
786 : // The format of the Energy+.idd (the EnergyPlus input data dictionary) for the
787 : // following keywords is reflected exactly in this subroutine:
788 : // PlantEquipmentOperation:CoolingLoad
789 : // PlantEquipmentOperation:HeatingLoad
790 : // PlantEquipmentOperation:OutdoorDryBulb
791 : // PlantEquipmentOperation:OutdoorWetBulb
792 : // PlantEquipmentOperation:OutdoorDewPoint
793 : // PlantEquipmentOperation:OutdoorRelativeHumidity
794 : // PlantEquipmentOperation:Uncontrolled
795 :
796 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
797 : int NumAlphas;
798 : int NumNums;
799 1235 : Array1D_string AlphArray; // Alpha input items for object
800 1235 : Array1D_string cAlphaFields; // Alpha field names
801 1235 : Array1D_string cNumericFields; // Numeric field names
802 1235 : Array1D<Real64> NumArray; // Numeric input items for object
803 1235 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
804 1235 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
805 1235 : int TotalArgs(0); // Total number of alpha and numeric arguments (max) for a
806 : // certain object in the input file
807 1235 : std::string LoopOpSchemeObj; // Used to identify the object name for loop equipment operation scheme
808 : bool SchemeNameFound; // Set to FALSE if a match of OpScheme object and OpScheme name is not found
809 : Real64 OuterListNumLowerLimit;
810 : Real64 OuterListNumUpperLimit;
811 : Real64 InnerListNumLowerLimit;
812 : Real64 InnerListNumUpperLimit;
813 :
814 1235 : SchemeNameFound = true;
815 :
816 : // Determine max number of alpha and numeric arguments for all objects being read, in order to allocate local arrays
817 1235 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, TotalArgs, NumAlphas, NumNums);
818 :
819 1235 : AlphArray.allocate(NumAlphas);
820 1235 : cAlphaFields.allocate(NumAlphas);
821 1235 : cNumericFields.allocate(NumNums);
822 1235 : NumArray.dimension(NumNums, 0.0);
823 1235 : lAlphaBlanks.dimension(NumAlphas, true);
824 1235 : lNumericBlanks.dimension(NumNums, true);
825 :
826 1235 : if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
827 982 : LoopOpSchemeObj = "PlantEquipmentOperationSchemes";
828 253 : } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Condenser) {
829 253 : LoopOpSchemeObj = "CondenserEquipmentOperationSchemes";
830 : }
831 :
832 1235 : if (NumSchemes > 0) {
833 : int IOStat;
834 1745 : for (int Num = 1; Num <= NumSchemes; ++Num) {
835 1745 : state.dataInputProcessing->inputProcessor->getObjectItem(
836 : state, CurrentModuleObject, Num, AlphArray, NumAlphas, NumArray, NumNums, IOStat);
837 1745 : if (Util::SameString(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name, AlphArray(1))) break;
838 510 : if (Num == NumSchemes) {
839 0 : ShowSevereError(state,
840 0 : format("{} = \"{}\", could not find {} = \"{}\".",
841 : LoopOpSchemeObj,
842 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
843 : CurrentModuleObject,
844 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
845 0 : ErrorsFound = true;
846 0 : SchemeNameFound = false;
847 : }
848 : }
849 1235 : if (SchemeNameFound) {
850 1235 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists = (NumAlphas - 1);
851 1235 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists <= 0) {
852 0 : ShowSevereError(state, format("{} = \"{}\", specified without equipment list.", CurrentModuleObject, AlphArray(1)));
853 0 : ErrorsFound = true;
854 : } else {
855 : int ListNum;
856 2470 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList.allocate(
857 1235 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists);
858 1235 : int NumEquipLists = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists;
859 1235 : if (NumNums <= 0) { // Uncontrolled OpScheme type
860 42 : ListNum = NumEquipLists; // NumEquipLists is always 1 for Uncontrolled OpScheme type
861 42 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Name = AlphArray(2);
862 42 : LoadEquipList(state, LoopNum, SchemeNum, ListNum, ErrorsFound);
863 : } else { // Range based OpScheme type
864 2541 : for (ListNum = 1; ListNum <= NumEquipLists; ++ListNum) {
865 1348 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit = NumArray(ListNum * 2 - 1);
866 1348 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeUpperLimit = NumArray(ListNum * 2);
867 1348 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Name = AlphArray(ListNum + 1);
868 1348 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeUpperLimit < 0.0) {
869 0 : ShowSevereError(state,
870 0 : format("{} = \"{}\", found a negative value for an upper limit in {} = \"{}\".",
871 : LoopOpSchemeObj,
872 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
873 : CurrentModuleObject,
874 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
875 0 : ErrorsFound = true;
876 : }
877 :
878 : {
879 1348 : std::string const &plantLoopOperation =
880 : CurrentModuleObject; // different op schemes have different lower limit check values
881 :
882 1855 : if (plantLoopOperation == "PlantEquipmentOperation:CoolingLoad" ||
883 1855 : plantLoopOperation == "PlantEquipmentOperation:HeatingLoad" ||
884 8 : plantLoopOperation == "PlantEquipmentOperation:OutdoorrelativeHumidity") {
885 : // these should not be less than zero
886 1342 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit < 0.0) {
887 0 : ShowSevereError(state,
888 0 : format("{} = \"{}\", found a negative value for a lower limit in {} = \"{}\".",
889 : LoopOpSchemeObj,
890 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
891 : CurrentModuleObject,
892 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
893 0 : ErrorsFound = true;
894 : }
895 : } else {
896 : // others should not be less than -70
897 6 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit < -70.0) {
898 0 : ShowSevereError(state,
899 0 : format("{} = \"{}\", found too low of a value for a lower limit in {} = \"{}\".",
900 : LoopOpSchemeObj,
901 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
902 : CurrentModuleObject,
903 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
904 0 : ErrorsFound = true;
905 : }
906 : }
907 : }
908 :
909 1348 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit >
910 1348 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeUpperLimit) {
911 0 : ShowSevereError(state,
912 0 : format("{} = \"{}\", found a lower limit that is higher than an upper limit in {} = \"{}\".",
913 : LoopOpSchemeObj,
914 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
915 : CurrentModuleObject,
916 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
917 0 : ErrorsFound = true;
918 : }
919 :
920 1348 : LoadEquipList(state, LoopNum, SchemeNum, ListNum, ErrorsFound);
921 : }
922 : // now run through lists again and check that range limits do not overlap each other
923 2541 : for (ListNum = 1; ListNum <= NumEquipLists; ++ListNum) {
924 1348 : OuterListNumLowerLimit = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit;
925 1348 : OuterListNumUpperLimit = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeUpperLimit;
926 3136 : for (int InnerListNum = 1; InnerListNum <= NumEquipLists; ++InnerListNum) {
927 1788 : if (InnerListNum == ListNum) continue; // don't check against self.
928 440 : InnerListNumLowerLimit = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(InnerListNum).RangeLowerLimit;
929 440 : InnerListNumUpperLimit = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(InnerListNum).RangeUpperLimit;
930 : // Check if inner list has a lower limit that is between an outer's lower and upper limit
931 440 : if (InnerListNumLowerLimit > OuterListNumLowerLimit && InnerListNumLowerLimit < OuterListNumUpperLimit) {
932 0 : ShowWarningError(state,
933 0 : format("{} = \"{}\", detected overlapping ranges in {} = \"{}\".",
934 : LoopOpSchemeObj,
935 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
936 : CurrentModuleObject,
937 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
938 0 : ShowContinueError(state,
939 0 : format("Range # {} Lower limit = {:.1R} lies within the Range # {} ({:.1R} to {:.1R}).",
940 : InnerListNum,
941 : InnerListNumLowerLimit,
942 : ListNum,
943 : OuterListNumLowerLimit,
944 : OuterListNumUpperLimit));
945 0 : ShowContinueError(state,
946 : "Check that input for load range limit values do not overlap, and the simulation continues...");
947 : }
948 : // Check if inner list has an upper limit that is between an outer's lower and upper limit
949 440 : if (InnerListNumUpperLimit > OuterListNumLowerLimit && InnerListNumUpperLimit < OuterListNumUpperLimit) {
950 0 : ShowWarningError(state,
951 0 : format("{} = \"{}\", detected overlapping ranges in {} = \"{}\".",
952 : LoopOpSchemeObj,
953 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
954 : CurrentModuleObject,
955 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
956 0 : ShowContinueError(state,
957 0 : format("Range # {} Upper limit = {:.1R} lies within Range # {} ({:.1R} to {:.1R}).",
958 : InnerListNum,
959 : InnerListNumUpperLimit,
960 : ListNum,
961 : OuterListNumLowerLimit,
962 : OuterListNumUpperLimit));
963 0 : ShowContinueError(state,
964 : "Check that input for load range limit values do not overlap, and the simulation continues...");
965 : }
966 : }
967 : }
968 : }
969 : }
970 : }
971 : } else {
972 0 : ShowSevereError(state,
973 0 : format("{} = \"{}\", could not find {} = \"{}\".",
974 : LoopOpSchemeObj,
975 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
976 : CurrentModuleObject,
977 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
978 0 : ErrorsFound = true;
979 : }
980 :
981 1235 : AlphArray.deallocate();
982 1235 : cAlphaFields.deallocate();
983 1235 : cNumericFields.deallocate();
984 1235 : NumArray.deallocate();
985 1235 : lAlphaBlanks.deallocate();
986 1235 : lNumericBlanks.deallocate();
987 1235 : }
988 :
989 3 : void FindDeltaTempRangeInput(EnergyPlusData &state,
990 : DataLoopNode::ConnectionObjectType const CurrentModuleObject, // for ease in renaming
991 : int const NumSchemes, // May be set here and passed on
992 : int const LoopNum, // May be set here and passed on
993 : int const SchemeNum, // May be set here and passed on
994 : bool &ErrorsFound // May be set here and passed on
995 : )
996 : {
997 : // SUBROUTINE INFORMATION:
998 : // AUTHOR Chandan Sharma
999 : // DATE WRITTEN August 2010
1000 : // MODIFIED na
1001 : // RE-ENGINEERED na
1002 :
1003 : // PURPOSE OF THIS SUBROUTINE:
1004 : // Load range based input into PLANTLOOP data structure
1005 :
1006 : // METHODOLOGY EMPLOYED:
1007 : // calls the Input Processor to retrieve data from input file.
1008 : // The format of the Energy+.idd (the EnergyPlus input data dictionary) for the
1009 : // following keywords is reflected exactly in this subroutine:
1010 : // PlantEquipmentOperation:OutdoorDryBulbDifference
1011 : // PlantEquipmentOperation:OutdoorWetBulbDifference
1012 : // PlantEquipmentOperation:OutdoorDewPointDifference
1013 :
1014 : // REFERENCES:
1015 : // Based on subroutine FindRangeBasedOrUncontrolledInput from Dan Fisher, July 2010
1016 :
1017 : // Using/Aliasing
1018 : using NodeInputManager::GetOnlySingleNode;
1019 : using namespace DataLoopNode;
1020 :
1021 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1022 : int NumAlphas;
1023 : int NumNums;
1024 3 : Array1D_string AlphArray; // Alpha input items for object
1025 3 : Array1D_string cAlphaFields; // Alpha field names
1026 3 : Array1D_string cNumericFields; // Numeric field names
1027 3 : Array1D<Real64> NumArray; // Numeric input items for object
1028 3 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
1029 3 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
1030 3 : int TotalArgs(0); // Total number of alpha and numeric arguments (max) for a
1031 : // certain object in the input file
1032 3 : std::string LoopOpSchemeObj; // Used to identify the object name for loop equipment operation scheme
1033 :
1034 3 : std::string cmoStr = std::string(BranchNodeConnections::ConnectionObjectTypeNamesUC[static_cast<int>(CurrentModuleObject)]);
1035 :
1036 : // Determine max number of alpha and numeric arguments for all objects being read, in order to allocate local arrays
1037 3 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cmoStr, TotalArgs, NumAlphas, NumNums);
1038 :
1039 3 : AlphArray.allocate(NumAlphas);
1040 3 : cAlphaFields.allocate(NumAlphas);
1041 3 : cNumericFields.allocate(NumNums);
1042 3 : NumArray.dimension(NumNums, 0.0);
1043 3 : lAlphaBlanks.dimension(NumAlphas, true);
1044 3 : lNumericBlanks.dimension(NumNums, true);
1045 :
1046 3 : if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
1047 0 : LoopOpSchemeObj = "PlantEquipmentOperationSchemes";
1048 3 : } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Condenser) {
1049 3 : LoopOpSchemeObj = "CondenserEquipmentOperationSchemes";
1050 : }
1051 :
1052 3 : if (NumSchemes > 0) {
1053 : int IOStat;
1054 3 : bool SchemeNameFound = true;
1055 :
1056 3 : for (int Num = 1; Num <= NumSchemes; ++Num) {
1057 3 : state.dataInputProcessing->inputProcessor->getObjectItem(state, cmoStr, Num, AlphArray, NumAlphas, NumArray, NumNums, IOStat);
1058 3 : if (Util::SameString(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name, AlphArray(1))) break;
1059 0 : if (Num == NumSchemes) {
1060 0 : ShowSevereError(state,
1061 0 : format("{} = \"{}\", could not find {} = \"{}\".",
1062 : LoopOpSchemeObj,
1063 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
1064 : cmoStr,
1065 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
1066 0 : ErrorsFound = true;
1067 0 : SchemeNameFound = false;
1068 : }
1069 : }
1070 3 : if (SchemeNameFound) {
1071 3 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists = (NumAlphas - 2);
1072 3 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists <= 0) {
1073 0 : ShowSevereError(state, format("{} = \"{}\", specified without equipment list.", cmoStr, AlphArray(1)));
1074 0 : ErrorsFound = true;
1075 : } else {
1076 6 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList.allocate(
1077 3 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists);
1078 3 : int NumEquipLists = state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists;
1079 3 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).ReferenceNodeName = AlphArray(2);
1080 3 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).ReferenceNodeNumber =
1081 6 : GetOnlySingleNode(state,
1082 3 : AlphArray(2),
1083 : ErrorsFound,
1084 : CurrentModuleObject,
1085 3 : AlphArray(1),
1086 : DataLoopNode::NodeFluidType::Water,
1087 : DataLoopNode::ConnectionType::Sensor,
1088 : NodeInputManager::CompFluidStream::Primary,
1089 : ObjectIsNotParent);
1090 : // For DO Loop below -- Check for lower limit > upper limit.(invalid)
1091 9 : for (int ListNum = 1; ListNum <= NumEquipLists; ++ListNum) {
1092 6 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit = NumArray(ListNum * 2 - 1);
1093 6 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeUpperLimit = NumArray(ListNum * 2);
1094 6 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Name = AlphArray(ListNum + 2);
1095 6 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeLowerLimit >
1096 6 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).RangeUpperLimit) {
1097 0 : ShowSevereError(state,
1098 0 : format("{} = \"{}\", found a lower limit that is higher than an upper limit in {} = \"{}\".",
1099 : LoopOpSchemeObj,
1100 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
1101 : cmoStr,
1102 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
1103 0 : ErrorsFound = true;
1104 : }
1105 6 : LoadEquipList(state, LoopNum, SchemeNum, ListNum, ErrorsFound);
1106 : }
1107 : }
1108 : }
1109 : } else {
1110 0 : ShowSevereError(state,
1111 0 : format("{} = \"{}\", could not find {} = \"{}\".",
1112 : LoopOpSchemeObj,
1113 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
1114 : cmoStr,
1115 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
1116 0 : ErrorsFound = true;
1117 : }
1118 :
1119 3 : AlphArray.deallocate();
1120 3 : cAlphaFields.deallocate();
1121 3 : cNumericFields.deallocate();
1122 3 : NumArray.deallocate();
1123 3 : lAlphaBlanks.deallocate();
1124 3 : lNumericBlanks.deallocate();
1125 3 : }
1126 :
1127 1396 : void LoadEquipList(EnergyPlusData &state,
1128 : int const LoopNum, // May be set here and passed on
1129 : int const SchemeNum, // May be set here and passed on
1130 : int const ListNum, // May be set here and passed on
1131 : bool &ErrorsFound // May be set here and passed on
1132 : )
1133 : {
1134 : // SUBROUTINE INFORMATION:
1135 : // AUTHOR Dan Fisher
1136 : // DATE WRITTEN July 2010
1137 : // MODIFIED B. Griffith Sept 2011, major rewrite
1138 : // allow mixing list types across plant types, store info first time
1139 : // RE-ENGINEERED na
1140 :
1141 : // PURPOSE OF THIS SUBROUTINE:
1142 : // Load delta range based input into PLANTLOOP data structure
1143 :
1144 : // METHODOLOGY EMPLOYED:
1145 : // calls the Input Processor to retrieve data from input file.
1146 :
1147 : // Using/Aliasing
1148 :
1149 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1150 :
1151 : bool FoundIntendedList;
1152 : int Num;
1153 : int MachineNum;
1154 : // INTEGER :: NumLists
1155 : int NumAlphas;
1156 : int NumNums;
1157 : int IOStat;
1158 1396 : std::string CurrentModuleObject;
1159 :
1160 1396 : if (state.dataPlantCondLoopOp->LoadEquipListOneTimeFlag) {
1161 : // assemble mapping between list names and indices one time
1162 458 : int PELists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "PlantEquipmentList");
1163 458 : int CELists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "CondenserEquipmentList");
1164 458 : state.dataPlantCondLoopOp->TotNumLists = PELists + CELists;
1165 458 : if (state.dataPlantCondLoopOp->TotNumLists > 0) {
1166 458 : state.dataPlantCondLoopOp->EquipListsNameList.allocate(state.dataPlantCondLoopOp->TotNumLists);
1167 458 : state.dataPlantCondLoopOp->EquipListsTypeList.allocate(state.dataPlantCondLoopOp->TotNumLists);
1168 458 : state.dataPlantCondLoopOp->EquipListsIndexList.allocate(state.dataPlantCondLoopOp->TotNumLists);
1169 : bool IsNotOK;
1170 :
1171 : // First load PlantEquipmentList info
1172 458 : if (PELists > 0) {
1173 441 : CurrentModuleObject = "PlantEquipmentList";
1174 1666 : for (Num = 1; Num <= PELists; ++Num) {
1175 1225 : int iIndex = Num;
1176 2450 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1177 : CurrentModuleObject,
1178 : Num,
1179 1225 : state.dataIPShortCut->cAlphaArgs,
1180 : NumAlphas,
1181 1225 : state.dataIPShortCut->rNumericArgs,
1182 : NumNums,
1183 : IOStat,
1184 1225 : state.dataIPShortCut->lNumericFieldBlanks,
1185 1225 : state.dataIPShortCut->lAlphaFieldBlanks,
1186 1225 : state.dataIPShortCut->cAlphaFieldNames,
1187 1225 : state.dataIPShortCut->cNumericFieldNames);
1188 1225 : state.dataPlantCondLoopOp->EquipListsNameList(iIndex) = state.dataIPShortCut->cAlphaArgs(1);
1189 1225 : state.dataPlantCondLoopOp->EquipListsTypeList(iIndex) = LoopType::Plant;
1190 1225 : state.dataPlantCondLoopOp->EquipListsIndexList(iIndex) = Num;
1191 1225 : MachineNum = 2;
1192 2691 : while (MachineNum <= NumAlphas) {
1193 1466 : if (state.dataIPShortCut->lAlphaFieldBlanks(MachineNum) || state.dataIPShortCut->lAlphaFieldBlanks(MachineNum + 1)) {
1194 0 : bool firstblank = false;
1195 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(MachineNum)) {
1196 0 : ShowSevereError(
1197 : state,
1198 0 : format("{}=\"{}\", invalid component specification.", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1199 0 : ShowContinueError(state, format("{} is blank.", state.dataIPShortCut->cAlphaFieldNames(MachineNum)));
1200 0 : firstblank = true;
1201 0 : ErrorsFound = true;
1202 : }
1203 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(MachineNum + 1)) {
1204 0 : if (!firstblank) {
1205 0 : ShowSevereError(state,
1206 0 : format("{}=\"{}\", invalid component specification.",
1207 : CurrentModuleObject,
1208 0 : state.dataIPShortCut->cAlphaArgs(1)));
1209 : }
1210 0 : ShowContinueError(state, format("{} is blank.", state.dataIPShortCut->cAlphaFieldNames(MachineNum + 1)));
1211 0 : ErrorsFound = true;
1212 : }
1213 : } else {
1214 2932 : ValidateComponent(state,
1215 1466 : state.dataIPShortCut->cAlphaArgs(MachineNum),
1216 1466 : state.dataIPShortCut->cAlphaArgs(MachineNum + 1),
1217 : IsNotOK,
1218 : CurrentModuleObject);
1219 1466 : if (IsNotOK) {
1220 0 : ShowContinueError(state, format("{}=\"{}\", Input Error.", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1221 0 : ErrorsFound = true;
1222 : }
1223 : }
1224 1466 : MachineNum += 2;
1225 : }
1226 : }
1227 : }
1228 458 : if (CELists > 0) {
1229 255 : CurrentModuleObject = "CondenserEquipmentList";
1230 524 : for (Num = 1; Num <= CELists; ++Num) {
1231 269 : int iIndex = Num + PELists;
1232 538 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1233 : CurrentModuleObject,
1234 : Num,
1235 269 : state.dataIPShortCut->cAlphaArgs,
1236 : NumAlphas,
1237 269 : state.dataIPShortCut->rNumericArgs,
1238 : NumNums,
1239 : IOStat,
1240 269 : state.dataIPShortCut->lNumericFieldBlanks,
1241 269 : state.dataIPShortCut->lAlphaFieldBlanks,
1242 269 : state.dataIPShortCut->cAlphaFieldNames,
1243 269 : state.dataIPShortCut->cNumericFieldNames);
1244 269 : state.dataPlantCondLoopOp->EquipListsNameList(iIndex) = state.dataIPShortCut->cAlphaArgs(1);
1245 269 : state.dataPlantCondLoopOp->EquipListsTypeList(iIndex) = LoopType::Condenser;
1246 269 : state.dataPlantCondLoopOp->EquipListsIndexList(iIndex) = Num;
1247 269 : MachineNum = 2;
1248 563 : while (MachineNum <= NumAlphas) {
1249 294 : if (state.dataIPShortCut->lAlphaFieldBlanks(MachineNum) || state.dataIPShortCut->lAlphaFieldBlanks(MachineNum + 1)) {
1250 0 : bool firstblank = false;
1251 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(MachineNum)) {
1252 0 : ShowSevereError(
1253 : state,
1254 0 : format("{}=\"{}\", invalid component specification.", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1255 0 : ShowContinueError(state, format("{} is blank.", state.dataIPShortCut->cAlphaFieldNames(MachineNum)));
1256 0 : firstblank = true;
1257 0 : ErrorsFound = true;
1258 : }
1259 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(MachineNum + 1)) {
1260 0 : if (!firstblank) {
1261 0 : ShowSevereError(state,
1262 0 : format("{}=\"{}\", invalid component specification.",
1263 : CurrentModuleObject,
1264 0 : state.dataIPShortCut->cAlphaArgs(1)));
1265 : }
1266 0 : ShowContinueError(state, format("{} is blank.", state.dataIPShortCut->cAlphaFieldNames(MachineNum + 1)));
1267 0 : ErrorsFound = true;
1268 : }
1269 : } else {
1270 588 : ValidateComponent(state,
1271 294 : state.dataIPShortCut->cAlphaArgs(MachineNum),
1272 294 : state.dataIPShortCut->cAlphaArgs(MachineNum + 1),
1273 : IsNotOK,
1274 : CurrentModuleObject);
1275 294 : if (IsNotOK) {
1276 0 : ShowContinueError(state, format("{}=\"{}\", Input Error.", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1277 0 : ErrorsFound = true;
1278 : }
1279 : }
1280 294 : MachineNum += 2;
1281 : }
1282 : }
1283 : }
1284 : }
1285 458 : if (ErrorsFound) {
1286 0 : ShowFatalError(state, "LoadEquipList/GetEquipmentLists: Failed due to preceding errors.");
1287 : }
1288 458 : state.dataPlantCondLoopOp->LoadEquipListOneTimeFlag = false;
1289 : }
1290 :
1291 1396 : FoundIntendedList = false;
1292 : // find name in set of possible list
1293 7375 : for (Num = 1; Num <= state.dataPlantCondLoopOp->TotNumLists; ++Num) {
1294 5979 : if (Util::SameString(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Name,
1295 5979 : state.dataPlantCondLoopOp->EquipListsNameList(Num))) {
1296 1396 : FoundIntendedList = true;
1297 : // get object item for real this time
1298 : {
1299 1396 : if (state.dataPlantCondLoopOp->EquipListsTypeList(Num) == LoopType::Plant) {
1300 1127 : CurrentModuleObject = "PlantEquipmentList";
1301 269 : } else if (state.dataPlantCondLoopOp->EquipListsTypeList(Num) == LoopType::Condenser) {
1302 269 : CurrentModuleObject = "CondenserEquipmentList";
1303 : }
1304 : }
1305 2792 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1306 : CurrentModuleObject,
1307 1396 : state.dataPlantCondLoopOp->EquipListsIndexList(Num),
1308 1396 : state.dataIPShortCut->cAlphaArgs,
1309 : NumAlphas,
1310 1396 : state.dataIPShortCut->rNumericArgs,
1311 : NumNums,
1312 : IOStat,
1313 1396 : state.dataIPShortCut->lNumericFieldBlanks,
1314 1396 : state.dataIPShortCut->lAlphaFieldBlanks,
1315 1396 : state.dataIPShortCut->cAlphaFieldNames,
1316 1396 : state.dataIPShortCut->cNumericFieldNames);
1317 1396 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).NumComps = (NumAlphas - 1) / 2;
1318 1396 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).NumComps > 0) {
1319 2784 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Comp.allocate(
1320 1392 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).NumComps);
1321 2985 : for (MachineNum = 1; MachineNum <= state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).NumComps; ++MachineNum) {
1322 1593 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Comp(MachineNum).TypeOf =
1323 3186 : state.dataIPShortCut->cAlphaArgs(MachineNum * 2);
1324 1593 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Comp(MachineNum).Name =
1325 3186 : state.dataIPShortCut->cAlphaArgs(MachineNum * 2 + 1);
1326 : } // MachineList
1327 : }
1328 : }
1329 : }
1330 :
1331 1396 : if (!FoundIntendedList) {
1332 0 : ShowSevereError(state,
1333 0 : format("LoadEquipList: Failed to find PlantEquipmentList or CondenserEquipmentList object named = {}",
1334 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(ListNum).Name));
1335 0 : ErrorsFound = true;
1336 : }
1337 1396 : }
1338 :
1339 15 : void FindCompSPInput(EnergyPlusData &state,
1340 : std::string &CurrentModuleObject, // for ease in renaming
1341 : int const NumSchemes, // May be set here and passed on
1342 : int const LoopNum, // May be set here and passed on
1343 : int const SchemeNum, // May be set here and passed on
1344 : bool &ErrorsFound // May be set here and passed on
1345 : )
1346 : {
1347 : // SUBROUTINE INFORMATION:
1348 : // AUTHOR Dan Fisher
1349 : // DATE WRITTEN July 2010
1350 : // MODIFIED B. Griffith, check setpoint nodes have setpoint managers on EMS on them.
1351 : // Rick Strand, Aug 2014, added simple thermal energy storage controls
1352 : // RE-ENGINEERED na
1353 :
1354 : // PURPOSE OF THIS SUBROUTINE:
1355 : // Load component setpoint based input into PLANTLOOP data structure
1356 :
1357 : // METHODOLOGY EMPLOYED:
1358 : // calls the Input Processor to retrieve data from input file.
1359 : // The format of the Energy+.idd (the EnergyPlus input data dictionary) for the
1360 : // following keywords is reflected exactly in this subroutine:
1361 : // PlantEquipmentOperation:ComponentSetPoint
1362 : // PlantEquipmentOperation:ThermalEnergyStorage
1363 :
1364 : // Using/Aliasing
1365 : using namespace DataLoopNode;
1366 : using NodeInputManager::GetOnlySingleNode;
1367 : using namespace DataSizing;
1368 : using EMSManager::CheckIfNodeSetPointManagedByEMS;
1369 : using ScheduleManager::GetScheduleIndex;
1370 : using SetPointManager::SetUpNewScheduledTESSetPtMgr;
1371 :
1372 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1373 15 : Real64 CompFlowRate(0.0);
1374 15 : std::string LoopOpSchemeObj; // Used to identify the object name for loop equipment operation scheme
1375 : bool SchemeNameFound; // Set to FALSE if a match of OpScheme object and OpScheme name is not found
1376 : Real64 NonChargCHWTemp;
1377 : Real64 OffPeakCHWTemp;
1378 : CtrlType CompOpType; // 1=cooling, 2=dual(or other)
1379 :
1380 15 : SchemeNameFound = true;
1381 :
1382 : DataLoopNode::ConnectionObjectType objType = static_cast<DataLoopNode::ConnectionObjectType>(
1383 15 : getEnumValue(BranchNodeConnections::ConnectionObjectTypeNamesUC, Util::makeUPPER(CurrentModuleObject)));
1384 :
1385 15 : if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
1386 15 : LoopOpSchemeObj = "PlantEquipmentOperationSchemes";
1387 0 : } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Condenser) {
1388 0 : LoopOpSchemeObj = "CondenserEquipmentOperationSchemes";
1389 : }
1390 :
1391 15 : if (NumSchemes > 0) {
1392 : int NumAlphas;
1393 : int NumNums;
1394 : int IOStat;
1395 15 : for (int Num = 1; Num <= NumSchemes; ++Num) {
1396 30 : state.dataInputProcessing->inputProcessor->getObjectItem(
1397 15 : state, CurrentModuleObject, Num, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNums, IOStat);
1398 15 : if (Util::SameString(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name, state.dataIPShortCut->cAlphaArgs(1))) break;
1399 0 : if (Num == NumSchemes) {
1400 0 : ShowSevereError(state,
1401 0 : format("{} = \"{}\", could not find {} = \"{}\".",
1402 : LoopOpSchemeObj,
1403 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
1404 : CurrentModuleObject,
1405 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
1406 0 : ErrorsFound = true;
1407 0 : SchemeNameFound = false;
1408 : }
1409 : }
1410 15 : if (SchemeNameFound) {
1411 : // why only one equip list assumed here? because component setpoint managers have their own lists contained.
1412 15 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists = 1;
1413 15 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList.allocate(1);
1414 15 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps = (NumAlphas - 1) / 5;
1415 : int ChargeSchedPtr;
1416 : int OnPeakSchedPtr;
1417 :
1418 15 : if (CurrentModuleObject == "PlantEquipmentOperation:ThermalEnergyStorage") {
1419 : // Read all of the additional parameters for ice storage control scheme and error check various parameters
1420 1 : std::string OnPeakSchedName = state.dataIPShortCut->cAlphaArgs(2);
1421 1 : OnPeakSchedPtr = GetScheduleIndex(state, OnPeakSchedName);
1422 1 : if (OnPeakSchedPtr == 0) {
1423 0 : ShowSevereError(state,
1424 0 : format("Could not find On Peak Schedule {} in {}{}\".",
1425 : OnPeakSchedName,
1426 : CurrentModuleObject,
1427 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
1428 0 : ErrorsFound = true;
1429 : }
1430 1 : std::string ChargeSchedName = state.dataIPShortCut->cAlphaArgs(3);
1431 1 : ChargeSchedPtr = GetScheduleIndex(state, ChargeSchedName);
1432 1 : if (ChargeSchedPtr == 0) {
1433 0 : ShowSevereError(state,
1434 0 : format("Could not find Charging Availability Schedule {} in {}{}\".",
1435 : ChargeSchedName,
1436 : CurrentModuleObject,
1437 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
1438 0 : ErrorsFound = true;
1439 : }
1440 1 : NonChargCHWTemp = state.dataIPShortCut->rNumericArgs(1);
1441 1 : OffPeakCHWTemp = state.dataIPShortCut->rNumericArgs(2);
1442 1 : }
1443 :
1444 15 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps > 0) {
1445 30 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp.allocate(
1446 15 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps);
1447 : int CompNumA;
1448 : int CompNumN;
1449 47 : for (int CompNum = 1; CompNum <= state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps; ++CompNum) {
1450 32 : if (CurrentModuleObject == "PlantEquipmentOperation:ComponentSetPoint") {
1451 30 : CompNumA = CompNum * 5;
1452 30 : CompNumN = CompNum;
1453 2 : } else if (CurrentModuleObject == "PlantEquipmentOperation:ThermalEnergyStorage") {
1454 2 : CompNumA = CompNum * 5 + 2;
1455 2 : CompNumN = CompNum + 2;
1456 : }
1457 32 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).TypeOf =
1458 64 : state.dataIPShortCut->cAlphaArgs(CompNumA - 3);
1459 32 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).Name =
1460 64 : state.dataIPShortCut->cAlphaArgs(CompNumA - 2);
1461 32 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).DemandNodeName =
1462 64 : state.dataIPShortCut->cAlphaArgs(CompNumA - 1);
1463 32 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).DemandNodeNum =
1464 64 : GetOnlySingleNode(state,
1465 32 : state.dataIPShortCut->cAlphaArgs(CompNumA - 1),
1466 : ErrorsFound,
1467 : objType,
1468 32 : state.dataIPShortCut->cAlphaArgs(1),
1469 : DataLoopNode::NodeFluidType::Water,
1470 : DataLoopNode::ConnectionType::Sensor,
1471 : NodeInputManager::CompFluidStream::Primary,
1472 : ObjectIsNotParent);
1473 32 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName =
1474 64 : state.dataIPShortCut->cAlphaArgs(CompNumA);
1475 32 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum =
1476 64 : GetOnlySingleNode(state,
1477 32 : state.dataIPShortCut->cAlphaArgs(CompNumA),
1478 : ErrorsFound,
1479 : objType,
1480 32 : state.dataIPShortCut->cAlphaArgs(1),
1481 : DataLoopNode::NodeFluidType::Water,
1482 : DataLoopNode::ConnectionType::Sensor,
1483 : NodeInputManager::CompFluidStream::Primary,
1484 : ObjectIsNotParent);
1485 32 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointFlowRate =
1486 32 : state.dataIPShortCut->rNumericArgs(CompNumN);
1487 :
1488 32 : if (state.dataIPShortCut->rNumericArgs(CompNumN) == AutoSize) {
1489 15 : int Num = 1;
1490 480 : for (; Num <= state.dataSize->SaveNumPlantComps; ++Num) {
1491 465 : int CompInNode = state.dataSize->CompDesWaterFlow(Num).SupNode;
1492 465 : CompFlowRate = state.dataSize->CompDesWaterFlow(Num).DesVolFlowRate;
1493 465 : if (CompInNode == state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).DemandNodeNum) {
1494 15 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointFlowRate = CompFlowRate;
1495 : } else {
1496 : // call error...Demand node must be component inlet node for autosizing
1497 : }
1498 : }
1499 60 : BaseSizer::reportSizerOutput(state,
1500 : CurrentModuleObject,
1501 15 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name,
1502 30 : format("Design Water Flow Rate [m3/s] Equipment # {}", Num),
1503 : CompFlowRate);
1504 : }
1505 :
1506 : {
1507 32 : std::string const &controlType = state.dataIPShortCut->cAlphaArgs(CompNumA + 1);
1508 32 : if (controlType == "COOLING") {
1509 18 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType = CtrlType::CoolingOp;
1510 14 : } else if (controlType == "HEATING") {
1511 5 : if (CurrentModuleObject == "PlantEquipmentOperation:ThermalEnergyStorage") {
1512 0 : ShowSevereError(
1513 : state,
1514 0 : format(
1515 : "Equipment Operation Mode cannot be HEATING for any equipment found in {} in thermal energy storage control",
1516 0 : state.dataIPShortCut->cAlphaArgs(1)));
1517 0 : ErrorsFound = true;
1518 : }
1519 5 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType = CtrlType::HeatingOp;
1520 9 : } else if (controlType == "DUAL") {
1521 9 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType = CtrlType::DualOp;
1522 : }
1523 : }
1524 :
1525 46 : if ((state.dataIPShortCut->cAlphaArgs(CompNumA + 1) != "COOLING") &&
1526 46 : (state.dataIPShortCut->cAlphaArgs(CompNumA + 1) != "HEATING") && (state.dataIPShortCut->cAlphaArgs(CompNumA + 1) != "DUAL")) {
1527 0 : ShowSevereError(state,
1528 0 : format("Equipment Operation Mode should be either HEATING or COOLING or DUAL mode, for {}={}",
1529 : CurrentModuleObject,
1530 0 : state.dataIPShortCut->cAlphaArgs(1)));
1531 : }
1532 :
1533 32 : if (CurrentModuleObject == "PlantEquipmentOperation:ThermalEnergyStorage") {
1534 :
1535 : // Special case for ThermalStorage:Ice:XXXX objects which can only be dual (cf #6958)
1536 4 : if (((state.dataIPShortCut->cAlphaArgs(CompNumA - 3) == "THERMALSTORAGE:ICE:SIMPLE") ||
1537 4 : (state.dataIPShortCut->cAlphaArgs(CompNumA - 3) == "THERMALSTORAGE:ICE:DETAILED")) &&
1538 1 : (state.dataIPShortCut->cAlphaArgs(CompNumA + 1) != "DUAL")) {
1539 :
1540 0 : ShowWarningError(state,
1541 0 : format("Equipment Operation Mode was reset to 'DUAL' for Component '{}' in {}='{}'.",
1542 0 : state.dataIPShortCut->cAlphaArgs(CompNumA - 2),
1543 : CurrentModuleObject,
1544 0 : state.dataIPShortCut->cAlphaArgs(1)));
1545 0 : ShowContinueError(state,
1546 0 : format("Equipment Operation Mode can only be 'DUAL' for {} objects.",
1547 0 : state.dataIPShortCut->cAlphaArgs(CompNumA - 3)));
1548 :
1549 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType = CtrlType::DualOp;
1550 : }
1551 :
1552 : // This block forces CompOpType to be either Cooling if explicitly provided, all other cases = Dual
1553 2 : switch (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType) {
1554 1 : case CtrlType::DualOp:
1555 1 : CompOpType = CtrlType::CoolingOp;
1556 1 : break;
1557 1 : case CtrlType::CoolingOp:
1558 1 : CompOpType = CtrlType::HeatingOp;
1559 1 : break;
1560 0 : case CtrlType::HeatingOp:
1561 0 : CompOpType = CtrlType::CoolingOp;
1562 0 : break;
1563 0 : default:
1564 0 : assert(false);
1565 : }
1566 :
1567 : // for each component, a new scheduled setpoint manager needs to be defined to internally generate the more
1568 : // detailed input that is necessary to get thermal energy storage to work from the simpler input.
1569 2 : SetUpNewScheduledTESSetPtMgr(
1570 : state,
1571 : OnPeakSchedPtr,
1572 : ChargeSchedPtr,
1573 : NonChargCHWTemp,
1574 : OffPeakCHWTemp,
1575 : CompOpType,
1576 2 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum);
1577 : }
1578 :
1579 : // check that setpoint node has valid setpoint managers or EMS
1580 :
1581 32 : switch (state.dataPlnt->PlantLoop(LoopNum).LoopDemandCalcScheme) {
1582 24 : case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
1583 24 : if (state.dataLoopNodes
1584 24 : ->Node(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum)
1585 24 : .TempSetPoint == SensedNodeFlagValue) {
1586 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
1587 0 : ShowSevereError(
1588 : state,
1589 0 : format("Missing temperature setpoint for {} named {}", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1590 0 : ShowContinueError(
1591 : state,
1592 0 : format("A temperature setpoint is needed at the node named {}",
1593 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
1594 0 : if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
1595 0 : ShowContinueError(state,
1596 0 : format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=SingleSetpoint",
1597 0 : state.dataPlnt->PlantLoop(LoopNum).Name));
1598 0 : } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
1599 : LoopType::Condenser) { // not applicable to Condenser loops
1600 : }
1601 0 : ShowContinueError(state, " Use a setpoint manager to place a single temperature setpoint on the node");
1602 0 : ErrorsFound = true;
1603 : } else {
1604 : // need call to EMS to check node
1605 0 : bool NodeEMSSetPointMissing = false;
1606 0 : CheckIfNodeSetPointManagedByEMS(
1607 : state,
1608 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum,
1609 : HVAC::CtrlVarType::Temp,
1610 : NodeEMSSetPointMissing);
1611 0 : if (NodeEMSSetPointMissing) {
1612 0 : ShowSevereError(state,
1613 0 : format("Missing temperature setpoint for {} named {}",
1614 : CurrentModuleObject,
1615 0 : state.dataIPShortCut->cAlphaArgs(1)));
1616 0 : ShowContinueError(
1617 : state,
1618 0 : format("A temperature setpoint is needed at the node named {}",
1619 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
1620 0 : if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
1621 0 : ShowContinueError(state,
1622 0 : format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=SingleSetpoint",
1623 0 : state.dataPlnt->PlantLoop(LoopNum).Name));
1624 0 : } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
1625 : LoopType::Condenser) { // not applicable to Condenser loops
1626 : }
1627 0 : ShowContinueError(state,
1628 : " Use a setpoint manager or EMS actuator to place a single temperature setpoint on node");
1629 0 : ErrorsFound = true;
1630 : }
1631 : }
1632 : }
1633 24 : break;
1634 : }
1635 8 : case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
1636 8 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType == CtrlType::CoolingOp) {
1637 4 : if (state.dataLoopNodes
1638 4 : ->Node(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum)
1639 4 : .TempSetPointHi == SensedNodeFlagValue) {
1640 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
1641 0 : ShowSevereError(state,
1642 0 : format("Missing temperature high setpoint for {} named {}",
1643 : CurrentModuleObject,
1644 0 : state.dataIPShortCut->cAlphaArgs(1)));
1645 0 : ShowContinueError(
1646 : state,
1647 0 : format("A temperature high setpoint is needed at the node named {}",
1648 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
1649 0 : if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
1650 0 : ShowContinueError(state,
1651 0 : format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=DualSetpointDeadband",
1652 0 : state.dataPlnt->PlantLoop(LoopNum).Name));
1653 0 : } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
1654 : LoopType::Condenser) { // not applicable to Condenser loops
1655 : }
1656 0 : ShowContinueError(state, " Use a setpoint manager to place a dual temperature setpoint on the node");
1657 0 : ErrorsFound = true;
1658 : } else {
1659 : // need call to EMS to check node
1660 0 : bool NodeEMSSetPointMissing = false;
1661 0 : CheckIfNodeSetPointManagedByEMS(
1662 : state,
1663 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum,
1664 : HVAC::CtrlVarType::Temp,
1665 : NodeEMSSetPointMissing);
1666 0 : if (NodeEMSSetPointMissing) {
1667 0 : ShowSevereError(state,
1668 0 : format("Missing high temperature setpoint for {} named {}",
1669 : CurrentModuleObject,
1670 0 : state.dataIPShortCut->cAlphaArgs(1)));
1671 0 : ShowContinueError(
1672 : state,
1673 0 : format(
1674 : "A high temperature setpoint is needed at the node named {}",
1675 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
1676 0 : if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
1677 0 : ShowContinueError(state,
1678 0 : format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=DualSetpointDeadband",
1679 0 : state.dataPlnt->PlantLoop(LoopNum).Name));
1680 0 : } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
1681 : LoopType::Condenser) { // not applicable to Condenser loops
1682 : }
1683 0 : ShowContinueError(
1684 : state, " Use a setpoint manager or EMS actuator to place a dual or high temperature setpoint on node");
1685 0 : ErrorsFound = true;
1686 : }
1687 : }
1688 : }
1689 4 : } else if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType ==
1690 : CtrlType::HeatingOp) {
1691 4 : if (state.dataLoopNodes
1692 4 : ->Node(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum)
1693 4 : .TempSetPointLo == SensedNodeFlagValue) {
1694 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
1695 0 : ShowSevereError(state,
1696 0 : format("Missing temperature low setpoint for {} named {}",
1697 : CurrentModuleObject,
1698 0 : state.dataIPShortCut->cAlphaArgs(1)));
1699 0 : ShowContinueError(
1700 : state,
1701 0 : format("A temperature low setpoint is needed at the node named {}",
1702 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
1703 0 : if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
1704 0 : ShowContinueError(state,
1705 0 : format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=DualSetpointDeadband",
1706 0 : state.dataPlnt->PlantLoop(LoopNum).Name));
1707 0 : } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
1708 : LoopType::Condenser) { // not applicable to Condenser loops
1709 : }
1710 0 : ShowContinueError(state, " Use a setpoint manager to place a dual temperature setpoint on the node");
1711 0 : ErrorsFound = true;
1712 : } else {
1713 : // need call to EMS to check node
1714 0 : bool NodeEMSSetPointMissing = false;
1715 0 : CheckIfNodeSetPointManagedByEMS(
1716 : state,
1717 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum,
1718 : HVAC::CtrlVarType::Temp,
1719 : NodeEMSSetPointMissing);
1720 0 : CheckIfNodeSetPointManagedByEMS(
1721 : state,
1722 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum,
1723 : HVAC::CtrlVarType::Temp,
1724 : NodeEMSSetPointMissing);
1725 0 : if (NodeEMSSetPointMissing) {
1726 0 : ShowSevereError(state,
1727 0 : format("Missing low temperature setpoint for {} named {}",
1728 : CurrentModuleObject,
1729 0 : state.dataIPShortCut->cAlphaArgs(1)));
1730 0 : ShowContinueError(
1731 : state,
1732 0 : format(
1733 : "A low temperature setpoint is needed at the node named {}",
1734 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
1735 0 : if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
1736 0 : ShowContinueError(state,
1737 0 : format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=DualSetpointDeadband",
1738 0 : state.dataPlnt->PlantLoop(LoopNum).Name));
1739 0 : } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
1740 : LoopType::Condenser) { // not applicable to Condenser loops
1741 : }
1742 0 : ShowContinueError(
1743 : state, " Use a setpoint manager or EMS actuator to place a dual or low temperature setpoint on node");
1744 0 : ErrorsFound = true;
1745 : }
1746 : }
1747 : }
1748 0 : } else if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).CtrlType == CtrlType::DualOp) {
1749 0 : if ((state.dataLoopNodes
1750 0 : ->Node(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum)
1751 0 : .TempSetPointHi == SensedNodeFlagValue) ||
1752 : (state.dataLoopNodes
1753 0 : ->Node(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum)
1754 0 : .TempSetPointLo == SensedNodeFlagValue)) {
1755 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
1756 0 : ShowSevereError(state,
1757 0 : format("Missing temperature dual setpoints for {} named {}",
1758 : CurrentModuleObject,
1759 0 : state.dataIPShortCut->cAlphaArgs(1)));
1760 0 : ShowContinueError(
1761 : state,
1762 0 : format("A dual temperaturesetpoint is needed at the node named {}",
1763 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
1764 0 : if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
1765 0 : ShowContinueError(state,
1766 0 : format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=DualSetpointDeadband",
1767 0 : state.dataPlnt->PlantLoop(LoopNum).Name));
1768 0 : } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
1769 : LoopType::Condenser) { // not applicable to Condenser loops
1770 : }
1771 0 : ShowContinueError(state, " Use a setpoint manager to place a dual temperature setpoint on the node");
1772 0 : ErrorsFound = true;
1773 : } else {
1774 : // need call to EMS to check node
1775 0 : bool NodeEMSSetPointMissing = false;
1776 0 : CheckIfNodeSetPointManagedByEMS(
1777 : state,
1778 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeNum,
1779 : HVAC::CtrlVarType::Temp,
1780 : NodeEMSSetPointMissing);
1781 0 : if (NodeEMSSetPointMissing) {
1782 0 : ShowSevereError(state,
1783 0 : format("Missing dual temperature setpoint for {} named {}",
1784 : CurrentModuleObject,
1785 0 : state.dataIPShortCut->cAlphaArgs(1)));
1786 0 : ShowContinueError(
1787 : state,
1788 0 : format(
1789 : "A dual temperature setpoint is needed at the node named {}",
1790 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).SetPointNodeName));
1791 0 : if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
1792 0 : ShowContinueError(state,
1793 0 : format("PlantLoop=\"{}\", Plant Loop Demand Calculation Scheme=DualSetpointDeadband",
1794 0 : state.dataPlnt->PlantLoop(LoopNum).Name));
1795 0 : } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop ==
1796 : LoopType::Condenser) { // not applicable to Condenser loops
1797 : }
1798 0 : ShowContinueError(state,
1799 : " Use a setpoint manager or EMS actuator to place a dual temperature setpoint on node");
1800 0 : ErrorsFound = true;
1801 : }
1802 : }
1803 : }
1804 : }
1805 8 : break;
1806 : }
1807 0 : default:
1808 0 : break;
1809 : }
1810 : }
1811 : } else {
1812 0 : ShowSevereError(state,
1813 0 : format("{} = \"{}\", specified without any machines.", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
1814 0 : ErrorsFound = true;
1815 : }
1816 : }
1817 : } else {
1818 0 : ShowSevereError(state,
1819 0 : format("{} = \"{}\", could not find {} = \"{}\".",
1820 : LoopOpSchemeObj,
1821 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
1822 : CurrentModuleObject,
1823 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
1824 0 : ErrorsFound = true;
1825 : }
1826 15 : }
1827 :
1828 10 : void GetChillerHeaterChangeoverOpSchemeInput(EnergyPlusData &state,
1829 : [[maybe_unused]] std::string &CurrentModuleObject,
1830 : int const NumSchemes,
1831 : bool &ErrorsFound)
1832 : {
1833 : // process input objects for advanced operation scheme, use json type input patterns
1834 :
1835 10 : if (NumSchemes > 0 && state.dataPlantCondLoopOp->LoadSupervisoryChillerHeaterOpScheme) {
1836 :
1837 3 : state.dataPlantCondLoopOp->ChillerHeaterSupervisoryOperationSchemes.allocate(NumSchemes);
1838 3 : std::string heatingOnlyLoadOpName;
1839 3 : std::string coolingOnlyLoadOpName;
1840 3 : std::string simultHeatCoolHeatingOpName;
1841 3 : std::string simulHeatCoolCoolingOpName;
1842 6 : for (int Num = 1; Num <= NumSchemes; ++Num) {
1843 3 : auto &scheme = state.dataPlantCondLoopOp->ChillerHeaterSupervisoryOperationSchemes(Num);
1844 3 : std::string cCurrentModuleObject("PlantEquipmentOperation:ChillerHeaterChangeover");
1845 3 : static const std::string routineName("GetChillerHeaterChangeoverOpSchemeInput: ");
1846 3 : auto const schemeInstances = state.dataInputProcessing->inputProcessor->epJSON.find(cCurrentModuleObject);
1847 3 : auto &ip = state.dataInputProcessing->inputProcessor;
1848 3 : if (schemeInstances != ip->epJSON.end()) {
1849 3 : auto &instancesValue = schemeInstances.value();
1850 6 : for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
1851 3 : auto const &fields = instance.value();
1852 3 : auto const &thisObjectName = Util::makeUPPER(instance.key());
1853 3 : state.dataInputProcessing->inputProcessor->markObjectAsUsed(cCurrentModuleObject, thisObjectName);
1854 3 : scheme.Name = thisObjectName;
1855 3 : scheme.TypeOf = "PlantEquipmentOperation:ChillerHeaterChangeover";
1856 3 : scheme.Type = OpScheme::ChillerHeaterSupervisory;
1857 3 : scheme.Setpoint.PrimCW = fields.at("primary_cooling_plant_setpoint_temperature").get<Real64>();
1858 3 : auto const secCWSP = fields.find("secondary_distribution_cooling_plant_setpoint_temperature");
1859 3 : if (secCWSP != fields.end()) { // not required field
1860 3 : scheme.Setpoint.SecCW = secCWSP.value().get<Real64>();
1861 : }
1862 3 : scheme.Setpoint.PrimHW_High = fields.at("primary_heating_plant_setpoint_at_outdoor_high_temperature").get<Real64>();
1863 3 : scheme.TempReset.HighOutdoorTemp = fields.at("outdoor_high_temperature").get<Real64>();
1864 3 : scheme.Setpoint.PrimHW_Low = fields.at("primary_heating_plant_setpoint_at_outdoor_low_temperature").get<Real64>();
1865 3 : scheme.TempReset.LowOutdoorTemp = fields.at("outdoor_low_temperature").get<Real64>();
1866 3 : auto const secHWSP = fields.find("secondary_distribution_heating_plant_setpoint_temperature");
1867 3 : if (secHWSP != fields.end()) { // not required field
1868 3 : scheme.Setpoint.SecHW = secHWSP.value().get<Real64>();
1869 : }
1870 3 : auto const boilerOffset = fields.find("boiler_setpoint_temperature_offset");
1871 6 : (boilerOffset != fields.end()) ? (scheme.TempReset.BoilerTemperatureOffset = boilerOffset.value().get<Real64>())
1872 3 : : (scheme.TempReset.BoilerTemperatureOffset = 0.5);
1873 3 : auto const backUpLow_HWset = fields.find("primary_heating_plant_setpoint_at_backup_outdoor_low_temperature");
1874 6 : (backUpLow_HWset != fields.end()) ? (scheme.Setpoint.PrimHW_BackupLow = backUpLow_HWset.value().get<Real64>())
1875 3 : : (scheme.Setpoint.PrimHW_BackupLow = scheme.Setpoint.PrimHW_Low);
1876 3 : auto const backUpLowTemp = fields.find("backup_outdoor_low_temperature");
1877 6 : (backUpLowTemp != fields.end()) ? (scheme.TempReset.BackupLowOutdoorTemp = backUpLowTemp.value().get<Real64>())
1878 3 : : (scheme.TempReset.BackupLowOutdoorTemp = scheme.TempReset.LowOutdoorTemp);
1879 3 : auto const zoneNameList = fields.find("zone_load_polling_zonelist_name");
1880 3 : if (zoneNameList != fields.end()) {
1881 3 : scheme.ZoneListName = Util::makeUPPER(zoneNameList.value().get<std::string>());
1882 : }
1883 3 : auto const coolPlantEqOpCoolingLoad = fields.find("cooling_only_load_plant_equipment_operation_cooling_load_name");
1884 3 : if (coolPlantEqOpCoolingLoad != fields.end()) {
1885 3 : coolingOnlyLoadOpName = Util::makeUPPER(coolPlantEqOpCoolingLoad.value().get<std::string>());
1886 : }
1887 3 : auto const heatPlantEqOpHeatingLoad = fields.find("heating_only_load_plant_equipment_operation_heating_load_name");
1888 3 : if (heatPlantEqOpHeatingLoad != fields.end()) {
1889 3 : heatingOnlyLoadOpName = Util::makeUPPER(heatPlantEqOpHeatingLoad.value().get<std::string>());
1890 : }
1891 3 : auto const simulEqOpCoolingLoad = fields.find("simultaneous_cooling_and_heating_plant_equipment_operation_cooling_load_name");
1892 3 : if (simulEqOpCoolingLoad != fields.end()) {
1893 2 : simulHeatCoolCoolingOpName = Util::makeUPPER(simulEqOpCoolingLoad.value().get<std::string>());
1894 2 : scheme.PlantOps.SimulHeatCoolCoolingOpInput = true;
1895 : }
1896 3 : auto const simulEqOpHeatingLoad = fields.find("simultaneous_cooling_and_heating_plant_equipment_operation_heating_load_name");
1897 3 : if (simulEqOpHeatingLoad != fields.end()) {
1898 2 : simultHeatCoolHeatingOpName = Util::makeUPPER(simulEqOpHeatingLoad.value().get<std::string>());
1899 2 : scheme.PlantOps.SimultHeatCoolHeatingOpInput = true;
1900 : }
1901 3 : auto const dedicatedCWHPName = fields.find("dedicated_chilled_water_return_recovery_heat_pump_name");
1902 3 : if (dedicatedCWHPName != fields.end()) {
1903 1 : scheme.DedicatedHR_ChWRetControl_Name = Util::makeUPPER(dedicatedCWHPName.value().get<std::string>());
1904 1 : scheme.PlantOps.DedicatedHR_ChWRetControl_Input = true;
1905 : }
1906 3 : auto const dedicatedHWHPName = fields.find("dedicated_hot_water_return_recovery_heat_pump_name");
1907 3 : if (dedicatedHWHPName != fields.end()) {
1908 1 : scheme.DedicatedHR_HWRetControl_Name = Util::makeUPPER(dedicatedHWHPName.value().get<std::string>());
1909 1 : scheme.PlantOps.DedicatedHR_HWRetControl_Input = true;
1910 : }
1911 6 : }
1912 : }
1913 :
1914 : // Load input instances from input processor
1915 3 : cCurrentModuleObject = "PlantEquipmentOperation:CoolingLoad";
1916 3 : auto const coolLoadInstances = ip->epJSON.find(cCurrentModuleObject);
1917 3 : auto &coolLoadInstancesValue = coolLoadInstances.value();
1918 :
1919 3 : cCurrentModuleObject = "PlantEquipmentOperation:HeatingLoad";
1920 3 : auto const heatLoadInstances = ip->epJSON.find(cCurrentModuleObject);
1921 3 : auto &heatLoadInstancesValue = heatLoadInstances.value();
1922 :
1923 3 : cCurrentModuleObject = "PlantEquipmentList";
1924 3 : auto const equipListInstances = ip->epJSON.find(cCurrentModuleObject);
1925 3 : auto const &equipListObjectSchemaProps = ip->getObjectSchemaProps(state, cCurrentModuleObject);
1926 3 : auto &equipListInstancesValue = equipListInstances.value();
1927 :
1928 : // process cooling only mode equipment lists and ranges
1929 8 : for (auto instance = coolLoadInstancesValue.begin(); instance != coolLoadInstancesValue.end(); ++instance) {
1930 5 : auto const &fields = instance.value();
1931 5 : auto const &thisObjectName = Util::makeUPPER(instance.key());
1932 5 : if (!Util::SameString(coolingOnlyLoadOpName, thisObjectName)) continue;
1933 :
1934 3 : int numfields = fields.size();
1935 3 : scheme.PlantOps.NumCoolingOnlyEquipLists = (numfields - 1) / 3; // assume correctly formed field sets?
1936 3 : scheme.CoolingOnlyEquipList.allocate(scheme.PlantOps.NumCoolingOnlyEquipLists);
1937 9 : for (int listNum = 1; listNum <= scheme.PlantOps.NumCoolingOnlyEquipLists; ++listNum) {
1938 6 : switch (listNum) {
1939 3 : case 1: {
1940 3 : scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_1_equipment_list_name").get<std::string>());
1941 3 : scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_1_lower_limit").get<Real64>();
1942 3 : scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_1_upper_limit").get<Real64>();
1943 3 : } break;
1944 :
1945 3 : case 2: {
1946 3 : scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_2_equipment_list_name").get<std::string>());
1947 3 : scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_2_lower_limit").get<Real64>();
1948 3 : scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_2_upper_limit").get<Real64>();
1949 :
1950 3 : } break;
1951 :
1952 0 : case 3: {
1953 0 : scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_3_equipment_list_name").get<std::string>());
1954 0 : scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_3_lower_limit").get<Real64>();
1955 0 : scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_3_upper_limit").get<Real64>();
1956 :
1957 0 : } break;
1958 :
1959 0 : case 4: {
1960 0 : scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_4_equipment_list_name").get<std::string>());
1961 0 : scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_4_lower_limit").get<Real64>();
1962 0 : scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_4_upper_limit").get<Real64>();
1963 :
1964 0 : } break;
1965 0 : case 5: {
1966 0 : scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_5_equipment_list_name").get<std::string>());
1967 0 : scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_5_lower_limit").get<Real64>();
1968 0 : scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_5_upper_limit").get<Real64>();
1969 :
1970 0 : } break;
1971 0 : case 6: {
1972 0 : scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_6_equipment_list_name").get<std::string>());
1973 0 : scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_6_lower_limit").get<Real64>();
1974 0 : scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_6_upper_limit").get<Real64>();
1975 :
1976 0 : } break;
1977 :
1978 0 : case 7: {
1979 0 : scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_7_equipment_list_name").get<std::string>());
1980 0 : scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_7_lower_limit").get<Real64>();
1981 0 : scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_7_upper_limit").get<Real64>();
1982 :
1983 0 : } break;
1984 :
1985 0 : case 8: {
1986 0 : scheme.CoolingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_8_equipment_list_name").get<std::string>());
1987 0 : scheme.CoolingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_8_lower_limit").get<Real64>();
1988 0 : scheme.CoolingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_8_upper_limit").get<Real64>();
1989 :
1990 0 : } break;
1991 : }
1992 : }
1993 8 : }
1994 :
1995 3 : if (!allocated(scheme.CoolingOnlyEquipList)) { // never found a match
1996 0 : ShowSevereError(state,
1997 0 : format("GetChillerHeaterChangeoverOpSchemeInput problem with PlantEquipmentOperation:ChillerHeaterChangeover name "
1998 : "=\"{}\", PlantEquipmentOperation:CoolingLoad name = \"{}\" was not found.",
1999 0 : scheme.Name,
2000 : coolingOnlyLoadOpName));
2001 0 : ErrorsFound = true;
2002 : }
2003 :
2004 9 : for (int listNum = 1; listNum <= scheme.PlantOps.NumCoolingOnlyEquipLists; ++listNum) {
2005 :
2006 44 : for (auto instance = equipListInstancesValue.begin(); instance != equipListInstancesValue.end(); ++instance) {
2007 38 : auto const &objectFields = instance.value();
2008 38 : auto const &thisObjectName = Util::makeUPPER(instance.key());
2009 38 : if (!Util::SameString(scheme.CoolingOnlyEquipList(listNum).Name, thisObjectName)) continue;
2010 :
2011 6 : auto extensibles = objectFields.find("equipment");
2012 6 : auto const &extensionSchemaProps = equipListObjectSchemaProps["equipment"]["items"]["properties"];
2013 6 : if (extensibles != objectFields.end()) {
2014 6 : auto extensiblesArray = extensibles.value();
2015 6 : int numExtensibles = extensiblesArray.size();
2016 6 : scheme.CoolingOnlyEquipList(listNum).NumComps = numExtensibles;
2017 6 : scheme.CoolingOnlyEquipList(listNum).Comp.allocate(numExtensibles);
2018 6 : int listItem = 0;
2019 15 : for (nlohmann::json const &extensibleInstance : extensiblesArray) {
2020 9 : ++listItem;
2021 9 : scheme.CoolingOnlyEquipList(listNum).Comp(listItem).TypeOf =
2022 18 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_object_type");
2023 9 : scheme.CoolingOnlyEquipList(listNum).Comp(listItem).Name =
2024 18 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_name");
2025 6 : }
2026 6 : }
2027 44 : }
2028 : }
2029 :
2030 : // process heating only mode equipment lists and ranges
2031 14 : for (auto instance = heatLoadInstancesValue.begin(); instance != heatLoadInstancesValue.end(); ++instance) {
2032 11 : auto const &fields = instance.value();
2033 11 : auto const &thisObjectName = Util::makeUPPER(instance.key());
2034 11 : if (!Util::SameString(heatingOnlyLoadOpName, thisObjectName)) continue;
2035 :
2036 3 : int numfields = fields.size();
2037 3 : scheme.PlantOps.NumHeatingOnlyEquipLists = (numfields - 1) / 3; // assume correctly formed field sets?
2038 3 : scheme.HeatingOnlyEquipList.allocate(scheme.PlantOps.NumHeatingOnlyEquipLists);
2039 9 : for (int listNum = 1; listNum <= scheme.PlantOps.NumHeatingOnlyEquipLists; ++listNum) {
2040 6 : switch (listNum) {
2041 3 : case 1: {
2042 3 : scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_1_equipment_list_name").get<std::string>());
2043 3 : scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_1_lower_limit").get<Real64>();
2044 3 : scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_1_upper_limit").get<Real64>();
2045 3 : } break;
2046 :
2047 3 : case 2: {
2048 3 : scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_2_equipment_list_name").get<std::string>());
2049 3 : scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_2_lower_limit").get<Real64>();
2050 3 : scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_2_upper_limit").get<Real64>();
2051 :
2052 3 : } break;
2053 :
2054 0 : case 3: {
2055 0 : scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_3_equipment_list_name").get<std::string>());
2056 0 : scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_3_lower_limit").get<Real64>();
2057 0 : scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_3_upper_limit").get<Real64>();
2058 :
2059 0 : } break;
2060 :
2061 0 : case 4: {
2062 0 : scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_4_equipment_list_name").get<std::string>());
2063 0 : scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_4_lower_limit").get<Real64>();
2064 0 : scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_4_upper_limit").get<Real64>();
2065 :
2066 0 : } break;
2067 0 : case 5: {
2068 0 : scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_5_equipment_list_name").get<std::string>());
2069 0 : scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_5_lower_limit").get<Real64>();
2070 0 : scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_5_upper_limit").get<Real64>();
2071 :
2072 0 : } break;
2073 0 : case 6: {
2074 0 : scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_6_equipment_list_name").get<std::string>());
2075 0 : scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_6_lower_limit").get<Real64>();
2076 0 : scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_6_upper_limit").get<Real64>();
2077 :
2078 0 : } break;
2079 :
2080 0 : case 7: {
2081 0 : scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_7_equipment_list_name").get<std::string>());
2082 0 : scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_7_lower_limit").get<Real64>();
2083 0 : scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_7_upper_limit").get<Real64>();
2084 :
2085 0 : } break;
2086 :
2087 0 : case 8: {
2088 0 : scheme.HeatingOnlyEquipList(listNum).Name = Util::makeUPPER(fields.at("range_8_equipment_list_name").get<std::string>());
2089 0 : scheme.HeatingOnlyEquipList(listNum).RangeLowerLimit = fields.at("load_range_8_lower_limit").get<Real64>();
2090 0 : scheme.HeatingOnlyEquipList(listNum).RangeUpperLimit = fields.at("load_range_8_upper_limit").get<Real64>();
2091 :
2092 0 : } break;
2093 : }
2094 : }
2095 14 : }
2096 :
2097 3 : if (!allocated(scheme.HeatingOnlyEquipList)) { // never found a match
2098 0 : ShowSevereError(state,
2099 0 : format("GetChillerHeaterChangeoverOpSchemeInput problem with PlantEquipmentOperation:ChillerHeaterChangeover name "
2100 : "=\"{}\", PlantEquipmentOperation:HeatingLoad name = \"{}\" was not found.",
2101 0 : scheme.Name,
2102 : heatingOnlyLoadOpName));
2103 0 : ErrorsFound = true;
2104 : }
2105 :
2106 9 : for (int listNum = 1; listNum <= scheme.PlantOps.NumHeatingOnlyEquipLists; ++listNum) {
2107 :
2108 44 : for (auto instance = equipListInstancesValue.begin(); instance != equipListInstancesValue.end(); ++instance) {
2109 38 : auto const &objectFields = instance.value();
2110 38 : auto const &thisObjectName = Util::makeUPPER(instance.key());
2111 38 : if (!Util::SameString(scheme.HeatingOnlyEquipList(listNum).Name, thisObjectName)) continue;
2112 :
2113 6 : auto extensibles = objectFields.find("equipment");
2114 6 : auto const &extensionSchemaProps = equipListObjectSchemaProps["equipment"]["items"]["properties"];
2115 6 : if (extensibles != objectFields.end()) {
2116 6 : auto extensiblesArray = extensibles.value();
2117 6 : int numExtensibles = extensiblesArray.size();
2118 6 : scheme.HeatingOnlyEquipList(listNum).NumComps = numExtensibles;
2119 6 : scheme.HeatingOnlyEquipList(listNum).Comp.allocate(numExtensibles);
2120 6 : int listItem = 0;
2121 15 : for (nlohmann::json const &extensibleInstance : extensiblesArray) {
2122 9 : ++listItem;
2123 9 : scheme.HeatingOnlyEquipList(listNum).Comp(listItem).TypeOf =
2124 18 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_object_type");
2125 9 : scheme.HeatingOnlyEquipList(listNum).Comp(listItem).Name =
2126 18 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_name");
2127 6 : }
2128 6 : }
2129 44 : }
2130 : }
2131 :
2132 : // process simulataneous heating and cooling mode cooling equipment lists and ranges
2133 :
2134 8 : for (auto instance = coolLoadInstancesValue.begin(); instance != coolLoadInstancesValue.end(); ++instance) {
2135 5 : auto const &fields = instance.value();
2136 5 : auto const &thisObjectName = Util::makeUPPER(instance.key());
2137 5 : if (!Util::SameString(simulHeatCoolCoolingOpName, thisObjectName)) continue;
2138 :
2139 2 : int numfields = fields.size();
2140 2 : scheme.PlantOps.NumSimultHeatCoolCoolingEquipLists = (numfields - 1) / 3; // assume correctly formed field sets?
2141 2 : scheme.SimultHeatCoolCoolingEquipList.allocate(scheme.PlantOps.NumSimultHeatCoolCoolingEquipLists);
2142 4 : for (int listNum = 1; listNum <= scheme.PlantOps.NumSimultHeatCoolCoolingEquipLists; ++listNum) {
2143 2 : switch (listNum) {
2144 2 : case 1: {
2145 2 : scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
2146 4 : Util::makeUPPER(fields.at("range_1_equipment_list_name").get<std::string>());
2147 2 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_1_lower_limit").get<Real64>();
2148 2 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_1_upper_limit").get<Real64>();
2149 2 : } break;
2150 :
2151 0 : case 2: {
2152 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
2153 0 : Util::makeUPPER(fields.at("range_2_equipment_list_name").get<std::string>());
2154 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_2_lower_limit").get<Real64>();
2155 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_2_upper_limit").get<Real64>();
2156 :
2157 0 : } break;
2158 :
2159 0 : case 3: {
2160 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
2161 0 : Util::makeUPPER(fields.at("range_3_equipment_list_name").get<std::string>());
2162 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_3_lower_limit").get<Real64>();
2163 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_3_upper_limit").get<Real64>();
2164 :
2165 0 : } break;
2166 :
2167 0 : case 4: {
2168 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
2169 0 : Util::makeUPPER(fields.at("range_4_equipment_list_name").get<std::string>());
2170 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_4_lower_limit").get<Real64>();
2171 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_4_upper_limit").get<Real64>();
2172 :
2173 0 : } break;
2174 0 : case 5: {
2175 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
2176 0 : Util::makeUPPER(fields.at("range_5_equipment_list_name").get<std::string>());
2177 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_5_lower_limit").get<Real64>();
2178 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_5_upper_limit").get<Real64>();
2179 :
2180 0 : } break;
2181 0 : case 6: {
2182 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
2183 0 : Util::makeUPPER(fields.at("range_6_equipment_list_name").get<std::string>());
2184 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_6_lower_limit").get<Real64>();
2185 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_6_upper_limit").get<Real64>();
2186 :
2187 0 : } break;
2188 :
2189 0 : case 7: {
2190 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
2191 0 : Util::makeUPPER(fields.at("range_7_equipment_list_name").get<std::string>());
2192 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_7_lower_limit").get<Real64>();
2193 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_7_upper_limit").get<Real64>();
2194 :
2195 0 : } break;
2196 :
2197 0 : case 8: {
2198 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).Name =
2199 0 : Util::makeUPPER(fields.at("range_8_equipment_list_name").get<std::string>());
2200 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeLowerLimit = fields.at("load_range_8_lower_limit").get<Real64>();
2201 0 : scheme.SimultHeatCoolCoolingEquipList(listNum).RangeUpperLimit = fields.at("load_range_8_upper_limit").get<Real64>();
2202 :
2203 0 : } break;
2204 : }
2205 : }
2206 8 : }
2207 :
2208 3 : if (scheme.PlantOps.SimulHeatCoolCoolingOpInput && !allocated(scheme.SimultHeatCoolCoolingEquipList)) {
2209 0 : ShowSevereError(state,
2210 0 : format("GetChillerHeaterChangeoverOpSchemeInput problem with PlantEquipmentOperation:ChillerHeaterChangeover name "
2211 : "=\"{}\", PlantEquipmentOperation:CoolingLoad name = \"{}\" was not found.",
2212 0 : scheme.Name,
2213 : simulHeatCoolCoolingOpName));
2214 0 : ErrorsFound = true;
2215 : }
2216 :
2217 5 : for (int listNum = 1; listNum <= scheme.PlantOps.NumSimultHeatCoolCoolingEquipLists; ++listNum) {
2218 :
2219 14 : for (auto instance = equipListInstancesValue.begin(); instance != equipListInstancesValue.end(); ++instance) {
2220 12 : auto const &objectFields = instance.value();
2221 12 : auto const &thisObjectName = Util::makeUPPER(instance.key());
2222 12 : if (!Util::SameString(scheme.SimultHeatCoolCoolingEquipList(listNum).Name, thisObjectName)) continue;
2223 :
2224 2 : auto extensibles = objectFields.find("equipment");
2225 2 : auto const &extensionSchemaProps = equipListObjectSchemaProps["equipment"]["items"]["properties"];
2226 2 : if (extensibles != objectFields.end()) {
2227 2 : auto extensiblesArray = extensibles.value();
2228 2 : int numExtensibles = extensiblesArray.size();
2229 2 : scheme.SimultHeatCoolCoolingEquipList(listNum).NumComps = numExtensibles;
2230 2 : scheme.SimultHeatCoolCoolingEquipList(listNum).Comp.allocate(numExtensibles);
2231 2 : int listItem = 0;
2232 4 : for (nlohmann::json const &extensibleInstance : extensiblesArray) {
2233 2 : ++listItem;
2234 2 : scheme.SimultHeatCoolCoolingEquipList(listNum).Comp(listItem).TypeOf =
2235 4 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_object_type");
2236 2 : scheme.SimultHeatCoolCoolingEquipList(listNum).Comp(listItem).Name =
2237 4 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_name");
2238 2 : }
2239 2 : }
2240 14 : }
2241 : }
2242 :
2243 : // process simultaneous heating and cooling mode heating equipment lists and ranges
2244 :
2245 14 : for (auto instance = heatLoadInstancesValue.begin(); instance != heatLoadInstancesValue.end(); ++instance) {
2246 11 : auto const &fields = instance.value();
2247 11 : auto const &thisObjectName = Util::makeUPPER(instance.key());
2248 11 : if (!Util::SameString(simultHeatCoolHeatingOpName, thisObjectName)) continue;
2249 :
2250 2 : int numfields = fields.size();
2251 2 : scheme.PlantOps.NumSimultHeatCoolHeatingEquipLists = (numfields - 1) / 3; // assume correctly formed field sets?
2252 2 : scheme.SimultHeatCoolHeatingEquipList.allocate(scheme.PlantOps.NumSimultHeatCoolHeatingEquipLists);
2253 4 : for (int listNum = 1; listNum <= scheme.PlantOps.NumSimultHeatCoolHeatingEquipLists; ++listNum) {
2254 2 : switch (listNum) {
2255 2 : case 1: {
2256 2 : scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
2257 4 : Util::makeUPPER(fields.at("range_1_equipment_list_name").get<std::string>());
2258 2 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_1_lower_limit").get<Real64>();
2259 2 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_1_upper_limit").get<Real64>();
2260 2 : } break;
2261 :
2262 0 : case 2: {
2263 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
2264 0 : Util::makeUPPER(fields.at("range_2_equipment_list_name").get<std::string>());
2265 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_2_lower_limit").get<Real64>();
2266 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_2_upper_limit").get<Real64>();
2267 :
2268 0 : } break;
2269 :
2270 0 : case 3: {
2271 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
2272 0 : Util::makeUPPER(fields.at("range_3_equipment_list_name").get<std::string>());
2273 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_3_lower_limit").get<Real64>();
2274 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_3_upper_limit").get<Real64>();
2275 :
2276 0 : } break;
2277 :
2278 0 : case 4: {
2279 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
2280 0 : Util::makeUPPER(fields.at("range_4_equipment_list_name").get<std::string>());
2281 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_4_lower_limit").get<Real64>();
2282 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_4_upper_limit").get<Real64>();
2283 :
2284 0 : } break;
2285 0 : case 5: {
2286 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
2287 0 : Util::makeUPPER(fields.at("range_5_equipment_list_name").get<std::string>());
2288 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_5_lower_limit").get<Real64>();
2289 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_5_upper_limit").get<Real64>();
2290 :
2291 0 : } break;
2292 0 : case 6: {
2293 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
2294 0 : Util::makeUPPER(fields.at("range_6_equipment_list_name").get<std::string>());
2295 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_6_lower_limit").get<Real64>();
2296 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_6_upper_limit").get<Real64>();
2297 :
2298 0 : } break;
2299 :
2300 0 : case 7: {
2301 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
2302 0 : Util::makeUPPER(fields.at("range_7_equipment_list_name").get<std::string>());
2303 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_7_lower_limit").get<Real64>();
2304 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_7_upper_limit").get<Real64>();
2305 :
2306 0 : } break;
2307 :
2308 0 : case 8: {
2309 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).Name =
2310 0 : Util::makeUPPER(fields.at("range_8_equipment_list_name").get<std::string>());
2311 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeLowerLimit = fields.at("load_range_8_lower_limit").get<Real64>();
2312 0 : scheme.SimultHeatCoolHeatingEquipList(listNum).RangeUpperLimit = fields.at("load_range_8_upper_limit").get<Real64>();
2313 :
2314 0 : } break;
2315 : }
2316 : }
2317 14 : }
2318 3 : if (scheme.PlantOps.SimultHeatCoolHeatingOpInput && !allocated(scheme.SimultHeatCoolHeatingEquipList)) {
2319 0 : ShowSevereError(state,
2320 0 : format("GetChillerHeaterChangeoverOpSchemeInput problem with PlantEquipmentOperation:ChillerHeaterChangeover name "
2321 : "=\"{}\", PlantEquipmentOperation:HeatingLoad name = \"{}\" was not found.",
2322 0 : scheme.Name,
2323 : simultHeatCoolHeatingOpName));
2324 0 : ErrorsFound = true;
2325 : }
2326 :
2327 3 : cCurrentModuleObject = "PlantEquipmentList";
2328 :
2329 5 : for (int listNum = 1; listNum <= scheme.PlantOps.NumSimultHeatCoolHeatingEquipLists; ++listNum) {
2330 :
2331 2 : auto const instances = ip->epJSON.find(cCurrentModuleObject);
2332 2 : auto const &objectSchemaProps = ip->getObjectSchemaProps(state, cCurrentModuleObject);
2333 :
2334 2 : auto &instancesValue = instances.value();
2335 14 : for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
2336 12 : auto const &objectFields = instance.value();
2337 12 : auto const &thisObjectName = Util::makeUPPER(instance.key());
2338 12 : if (!Util::SameString(scheme.SimultHeatCoolHeatingEquipList(listNum).Name, thisObjectName)) continue;
2339 :
2340 2 : auto extensibles = objectFields.find("equipment");
2341 2 : auto const &extensionSchemaProps = objectSchemaProps["equipment"]["items"]["properties"];
2342 2 : if (extensibles != objectFields.end()) {
2343 2 : auto extensiblesArray = extensibles.value();
2344 2 : int numExtensibles = extensiblesArray.size();
2345 2 : scheme.SimultHeatCoolHeatingEquipList(listNum).NumComps = numExtensibles;
2346 2 : scheme.SimultHeatCoolHeatingEquipList(listNum).Comp.allocate(numExtensibles);
2347 2 : int listItem = 0;
2348 4 : for (nlohmann::json const &extensibleInstance : extensiblesArray) {
2349 2 : ++listItem;
2350 2 : scheme.SimultHeatCoolHeatingEquipList(listNum).Comp(listItem).TypeOf =
2351 4 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_object_type");
2352 2 : scheme.SimultHeatCoolHeatingEquipList(listNum).Comp(listItem).Name =
2353 4 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "equipment_name");
2354 2 : }
2355 2 : }
2356 14 : }
2357 2 : }
2358 3 : }
2359 3 : }
2360 10 : state.dataPlantCondLoopOp->LoadSupervisoryChillerHeaterOpScheme = false;
2361 10 : }
2362 :
2363 6 : void GetUserDefinedOpSchemeInput(EnergyPlusData &state,
2364 : std::string &CurrentModuleObject, // for ease in renaming
2365 : int const NumSchemes, // May be set here and passed on
2366 : int const LoopNum, // May be set here and passed on
2367 : int const SchemeNum, // May be set here and passed on
2368 : bool &ErrorsFound // May be set here and passed on
2369 : )
2370 : {
2371 :
2372 : // SUBROUTINE INFORMATION:
2373 : // AUTHOR <author>
2374 : // DATE WRITTEN <date_written>
2375 : // MODIFIED na
2376 : // RE-ENGINEERED na
2377 :
2378 : // PURPOSE OF THIS SUBROUTINE:
2379 : // <description>
2380 :
2381 : // Using/Aliasing
2382 : using namespace DataPlant;
2383 :
2384 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2385 : bool SchemeNameFound; // Set to FALSE if a match of OpScheme object and OpScheme name is not found
2386 6 : std::string LoopOpSchemeObj; // Used to identify the object name for loop equipment operation scheme
2387 :
2388 6 : SchemeNameFound = true;
2389 :
2390 6 : if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Plant) {
2391 4 : LoopOpSchemeObj = "PlantEquipmentOperationSchemes";
2392 2 : } else if (state.dataPlnt->PlantLoop(LoopNum).TypeOfLoop == LoopType::Condenser) {
2393 2 : LoopOpSchemeObj = "CondenserEquipmentOperationSchemes";
2394 : }
2395 :
2396 6 : if (NumSchemes > 0) {
2397 : int NumAlphas, NumNums, Num, IOStat;
2398 :
2399 12 : for (Num = 1; Num <= NumSchemes; ++Num) {
2400 24 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
2401 : CurrentModuleObject,
2402 : Num,
2403 12 : state.dataIPShortCut->cAlphaArgs,
2404 : NumAlphas,
2405 12 : state.dataIPShortCut->rNumericArgs,
2406 : NumNums,
2407 : IOStat,
2408 12 : state.dataIPShortCut->lNumericFieldBlanks,
2409 12 : state.dataIPShortCut->lAlphaFieldBlanks,
2410 12 : state.dataIPShortCut->cAlphaFieldNames,
2411 12 : state.dataIPShortCut->cNumericFieldNames);
2412 12 : if (Util::SameString(state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name, state.dataIPShortCut->cAlphaArgs(1)))
2413 6 : break; // found the correct one
2414 6 : if (Num == NumSchemes) { // did not find it
2415 0 : ShowSevereError(state,
2416 0 : format("{} = \"{}\", could not find {} = \"{}\".",
2417 : LoopOpSchemeObj,
2418 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
2419 : CurrentModuleObject,
2420 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
2421 0 : ErrorsFound = true;
2422 0 : SchemeNameFound = false;
2423 : }
2424 : }
2425 6 : if (SchemeNameFound) {
2426 6 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).NumEquipLists = 1;
2427 6 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList.allocate(1);
2428 :
2429 6 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps = (NumAlphas - 3) / 2;
2430 6 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps > 0) {
2431 12 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp.allocate(
2432 6 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps);
2433 14 : for (int CompNum = 1; CompNum <= state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).NumComps; ++CompNum) {
2434 8 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).TypeOf =
2435 16 : state.dataIPShortCut->cAlphaArgs(CompNum * 2 + 2);
2436 8 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).Name =
2437 16 : state.dataIPShortCut->cAlphaArgs(CompNum * 2 + 3);
2438 :
2439 : // Setup EMS actuators for machines' MyLoad.
2440 16 : SetupEMSActuator(
2441 : state,
2442 : "Plant Equipment Operation",
2443 16 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name + ':' +
2444 8 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).Name,
2445 : "Distributed Load Rate",
2446 : "[W]",
2447 8 : state.dataPlantCondLoopOp->lDummy,
2448 8 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).EMSActuatorDispatchedLoadValue);
2449 : // TODO: I think this should be a sensor really
2450 8 : SetupEMSInternalVariable(
2451 : state,
2452 : "Component Remaining Current Demand Rate",
2453 16 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name + ':' +
2454 8 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).Name,
2455 : "[W]",
2456 8 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EquipList(1).Comp(CompNum).EMSIntVarRemainingLoadValue);
2457 : }
2458 : }
2459 6 : int StackMngrNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataRuntimeLang->EMSProgramCallManager);
2460 6 : if (StackMngrNum > 0) { // found it
2461 3 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).ErlSimProgramMngr = StackMngrNum;
2462 : } else {
2463 3 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).simPluginLocation =
2464 3 : state.dataPluginManager->pluginManager->getLocationOfUserDefinedPlugin(state, state.dataIPShortCut->cAlphaArgs(2));
2465 3 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).simPluginLocation == -1) {
2466 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
2467 0 : ShowContinueError(state, format("Entered in {}={}", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2468 0 : ShowContinueError(state, "Not found as either an EMS Program Manager or a Python Plugin instance.");
2469 0 : ErrorsFound = true;
2470 : }
2471 : }
2472 6 : if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) {
2473 1 : StackMngrNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataRuntimeLang->EMSProgramCallManager);
2474 1 : if (StackMngrNum > 0) { // found it
2475 1 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).ErlInitProgramMngr = StackMngrNum;
2476 : } else {
2477 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).initPluginLocation =
2478 0 : state.dataPluginManager->pluginManager->getLocationOfUserDefinedPlugin(state, state.dataIPShortCut->cAlphaArgs(3));
2479 0 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).initPluginLocation == -1) {
2480 0 : ShowSevereError(state,
2481 0 : format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
2482 0 : ShowContinueError(state, format("Entered in {}={}", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2483 0 : ShowContinueError(state, "Not found as either an EMS Program Manager or a Python Plugin instance.");
2484 0 : ErrorsFound = true;
2485 : }
2486 : }
2487 : }
2488 :
2489 : // setup internal variable for Supply Side Current Demand Rate [W]
2490 6 : SetupEMSInternalVariable(state,
2491 : "Supply Side Current Demand Rate",
2492 6 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name,
2493 : "[W]",
2494 6 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).EMSIntVarLoopDemandRate);
2495 : }
2496 :
2497 : } else {
2498 0 : ShowSevereError(state,
2499 0 : format("{} = \"{}\", could not find {} = \"{}\".",
2500 : LoopOpSchemeObj,
2501 0 : state.dataPlnt->PlantLoop(LoopNum).OperationScheme,
2502 : CurrentModuleObject,
2503 0 : state.dataPlnt->PlantLoop(LoopNum).OpScheme(SchemeNum).Name));
2504 0 : ErrorsFound = true;
2505 : }
2506 6 : }
2507 :
2508 : // End of GetInput subroutines for the Module
2509 : //******************************************************************************
2510 :
2511 : // Beginning Initialization Section of the Plant Loop Module
2512 : //******************************************************************************
2513 :
2514 31741579 : void InitLoadDistribution(EnergyPlusData &state, bool const FirstHVACIteration)
2515 : {
2516 : // SUBROUTINE INFORMATION:
2517 : // AUTHOR: Dan Fisher
2518 : // DATE WRITTEN: July 2010
2519 : // REVISED:
2520 :
2521 : // PURPOSE OF THIS SUBROUTINE:
2522 : // This subroutine scans equipment lists and matches a particular
2523 : // plant component with a component on the list. Pointers to the
2524 : // operation scheme and equipment list are saved on the plant data
2525 : // structure to facilitate a new load management routine that calls
2526 : // ManageLoadDistribution for every component.
2527 :
2528 : // Using/Aliasing
2529 : using EMSManager::ManageEMS;
2530 : using ScheduleManager::GetCurrentScheduleValue;
2531 : using ScheduleManager::GetScheduleIndex;
2532 :
2533 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2534 : DataPlant::LoopSideLocation LoopSidePtr;
2535 31741579 : PlantLocation plantLoc{};
2536 :
2537 : DataPlant::PlantEquipmentType Type;
2538 :
2539 : bool errFlag2;
2540 : Real64 HighestRange;
2541 :
2542 : // Object Data
2543 :
2544 31741579 : errFlag2 = false;
2545 : // Get Input
2546 31741579 : if (state.dataPlantCondLoopOp->GetPlantOpInput) {
2547 : bool GetInputOK; // successful Get Input
2548 458 : GetPlantOperationInput(state, GetInputOK);
2549 458 : if (GetInputOK) {
2550 458 : GetOperationSchemeInput(state);
2551 458 : state.dataPlantCondLoopOp->GetPlantOpInput = false;
2552 : } else {
2553 0 : return;
2554 : }
2555 : }
2556 :
2557 : // ONE TIME INITS
2558 31741579 : if (state.dataPlantCondLoopOp->InitLoadDistributionOneTimeFlag) {
2559 : // Set up 'component' to 'op scheme' pointers in Plant data structure
2560 : // We're looking for matches between a component on a PlantLoop.OpScheme.List()
2561 : // and the same component in the PlantLoop.LoopSide.Branch.Comp() data structure
2562 : int NumSearchResults;
2563 :
2564 : // first loop over main operation scheme data and finish filling out indexes to plant topology for the components in the lists
2565 1605 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
2566 1147 : auto &this_plant_loop = state.dataPlnt->PlantLoop(LoopNum);
2567 2416 : for (int OpNum = 1, OpNum_end = this_plant_loop.NumOpSchemes; OpNum <= OpNum_end; ++OpNum) {
2568 1269 : auto &this_op_scheme = this_plant_loop.OpScheme(OpNum);
2569 2686 : for (int ListNum = 1, ListNum_end = this_op_scheme.NumEquipLists; ListNum <= ListNum_end; ++ListNum) {
2570 1417 : auto &this_equip_list = this_op_scheme.EquipList(ListNum);
2571 3050 : for (int EquipNum = 1, EquipNum_end = this_equip_list.NumComps; EquipNum <= EquipNum_end; ++EquipNum) {
2572 1633 : auto &this_equip = this_equip_list.Comp(EquipNum);
2573 1633 : Type = static_cast<DataPlant::PlantEquipmentType>(getEnumValue(PlantEquipTypeNamesUC, Util::makeUPPER(this_equip.TypeOf)));
2574 1633 : bool errFlag1 = false;
2575 1633 : PlantUtilities::ScanPlantLoopsForObject(state, this_equip.Name, Type, plantLoc, errFlag1, _, _, NumSearchResults, _, LoopNum);
2576 :
2577 1633 : if (errFlag1) {
2578 0 : ShowSevereError(state, "InitLoadDistribution: Equipment specified for operation scheme not found on correct loop");
2579 0 : ShowContinueError(state, format("Operation Scheme name = {}", this_op_scheme.Name));
2580 0 : ShowContinueError(state, format("Loop name = {}", this_plant_loop.Name));
2581 0 : ShowContinueError(state, format("Component name = {}", this_equip.Name));
2582 0 : ShowFatalError(state, "InitLoadDistribution: Simulation terminated because of error in operation scheme.");
2583 : }
2584 :
2585 1633 : this_equip.LoopNumPtr = plantLoc.loopNum;
2586 1633 : this_equip.LoopSideNumPtr = plantLoc.loopSideNum;
2587 1633 : this_equip.BranchNumPtr = plantLoc.branchNum;
2588 1633 : this_equip.CompNumPtr = plantLoc.compNum;
2589 :
2590 1633 : if (ValidLoopEquipTypes[static_cast<int>(Type)] == LoopType::Plant && this_plant_loop.TypeOfLoop == LoopType::Condenser) {
2591 0 : ShowSevereError(state,
2592 0 : format("InitLoadDistribution: CondenserLoop=\"{}\", Operation Scheme=\"{}\",",
2593 0 : this_plant_loop.Name,
2594 0 : this_plant_loop.OperationScheme));
2595 0 : ShowContinueError(state,
2596 0 : format("Scheme type={}, Name=\"{}\" includes equipment that is not valid on a Condenser Loop",
2597 0 : this_op_scheme.TypeOf,
2598 0 : this_op_scheme.Name));
2599 0 : ShowContinueError(state,
2600 0 : format("Component {} not allowed as supply equipment on this type of loop.",
2601 0 : PlantEquipTypeNames[static_cast<int>(Type)]));
2602 0 : ShowContinueError(state, format("Component name = {}", this_equip.Name));
2603 0 : errFlag2 = true;
2604 : }
2605 1633 : if (ValidLoopEquipTypes[static_cast<int>(Type)] == LoopType::Condenser && this_plant_loop.TypeOfLoop == LoopType::Plant) {
2606 0 : ShowSevereError(state,
2607 0 : format("InitLoadDistribution: PlantLoop=\"{}\", Operation Scheme=\"{}\",",
2608 0 : this_plant_loop.Name,
2609 0 : this_plant_loop.OperationScheme));
2610 0 : ShowContinueError(state,
2611 0 : format("Scheme type={}, Name=\"{}\" includes equipment that is not valid on a Plant Loop",
2612 0 : this_op_scheme.TypeOf,
2613 0 : this_op_scheme.Name));
2614 0 : ShowContinueError(state,
2615 0 : format("Component {} not allowed as supply equipment on this type of loop.",
2616 0 : PlantEquipTypeNames[static_cast<int>(Type)]));
2617 0 : ShowContinueError(state, format("Component name = {}", this_equip.Name));
2618 0 : errFlag2 = true;
2619 : }
2620 :
2621 : } // Equipment on List
2622 : } // List
2623 1269 : if (this_op_scheme.Type == OpScheme::ChillerHeaterSupervisory) {
2624 : // do one time set up for custom chillerheater controls
2625 10 : bool found = false;
2626 10 : for (auto &s : state.dataPlantCondLoopOp->ChillerHeaterSupervisoryOperationSchemes) {
2627 10 : if (s.Name == this_op_scheme.Name) {
2628 10 : this_op_scheme.ChillerHeaterSupervisoryOperation = &s; // assign as pointer
2629 10 : found = true;
2630 10 : break;
2631 : }
2632 : }
2633 10 : if (found) {
2634 10 : this_op_scheme.ChillerHeaterSupervisoryOperation->OneTimeInitChillerHeaterChangeoverOpScheme(state);
2635 : } else {
2636 0 : ShowSevereError(state,
2637 0 : format("InitLoadDistribution: PlantLoop=\"{}\", Operation Scheme=\"{}\", was not found, check input",
2638 0 : this_plant_loop.Name,
2639 0 : this_op_scheme.Name));
2640 0 : ShowFatalError(state, "Program halted because ChillerHeaterSupervisory operation scheme not found.");
2641 : }
2642 : }
2643 : } // operation scheme
2644 : } // loop
2645 :
2646 : // second loop, fill op schemes info at each component.
2647 1605 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
2648 1147 : auto &this_plant_loop = state.dataPlnt->PlantLoop(LoopNum);
2649 2416 : for (int OpNum = 1, OpNum_end = this_plant_loop.NumOpSchemes; OpNum <= OpNum_end; ++OpNum) {
2650 1269 : auto &this_op_scheme = this_plant_loop.OpScheme(OpNum);
2651 2686 : for (int ListNum = 1, ListNum_end = this_op_scheme.NumEquipLists; ListNum <= ListNum_end; ++ListNum) {
2652 1417 : auto &this_equip_list = this_op_scheme.EquipList(ListNum);
2653 : int thisSchemeNum;
2654 3050 : for (int EquipNum = 1, EquipNum_end = this_equip_list.NumComps; EquipNum <= EquipNum_end; ++EquipNum) {
2655 1633 : auto const &this_equip = this_equip_list.Comp(EquipNum);
2656 : // dereference indices (stored in previous loop)
2657 1633 : plantLoc.loopNum = this_equip.LoopNumPtr;
2658 1633 : plantLoc.loopSideNum = this_equip.LoopSideNumPtr;
2659 1633 : plantLoc.branchNum = this_equip.BranchNumPtr;
2660 1633 : plantLoc.compNum = this_equip.CompNumPtr;
2661 1633 : auto &dummy_loop_equip = DataPlant::CompData::getPlantComponent(state, plantLoc);
2662 :
2663 1633 : if (dummy_loop_equip.NumOpSchemes == 0) {
2664 : // first op scheme for this component, allocate OpScheme and its EquipList to size 1
2665 1362 : dummy_loop_equip.OpScheme.allocate(1);
2666 1362 : auto &dummy_op_scheme_1(dummy_loop_equip.OpScheme(1));
2667 1362 : dummy_op_scheme_1.EquipList.allocate(1);
2668 1362 : dummy_loop_equip.NumOpSchemes = 1;
2669 1362 : dummy_op_scheme_1.NumEquipLists = 1;
2670 : // store pointers
2671 1362 : dummy_op_scheme_1.OpSchemePtr = OpNum;
2672 1362 : dummy_op_scheme_1.EquipList(1).ListPtr = ListNum;
2673 1362 : dummy_op_scheme_1.EquipList(1).CompPtr = EquipNum;
2674 : } else { // already an op scheme
2675 271 : int OldNumOpSchemes = dummy_loop_equip.NumOpSchemes;
2676 :
2677 : // could be new list on existing scheme or new scheme with new list. Check and see
2678 271 : bool FoundSchemeMatch = false;
2679 452 : for (thisSchemeNum = 1; thisSchemeNum <= OldNumOpSchemes; ++thisSchemeNum) { // Loop index used below
2680 : // compare the OpScheme index, 'opnum', in the PlantLoop()%OpScheme()data structure
2681 : // with the OpSchemePtr in the PlantLoop()%LoopSide()%Branch()%Comp() data structure.
2682 271 : if (OpNum != dummy_loop_equip.OpScheme(thisSchemeNum).OpSchemePtr) continue;
2683 90 : FoundSchemeMatch = true;
2684 90 : break;
2685 : }
2686 271 : if (FoundSchemeMatch) { // op scheme already exists, but need to add a list to the existing OpScheme
2687 90 : auto &this_op_schemeAdd = dummy_loop_equip.OpScheme(thisSchemeNum);
2688 90 : int NewNumEquipLists = this_op_schemeAdd.NumEquipLists + 1;
2689 90 : this_op_schemeAdd.EquipList.redimension(NewNumEquipLists);
2690 90 : this_op_schemeAdd.NumEquipLists = NewNumEquipLists;
2691 90 : this_op_schemeAdd.EquipList(NewNumEquipLists).ListPtr = ListNum;
2692 90 : this_op_schemeAdd.EquipList(NewNumEquipLists).CompPtr = EquipNum;
2693 : } else { // !FoundSchemeMatch: Add new op scheme and a new list
2694 181 : int NewNumOpSchemes = OldNumOpSchemes + 1;
2695 181 : dummy_loop_equip.OpScheme.redimension(NewNumOpSchemes);
2696 181 : auto &new_op_scheme = dummy_loop_equip.OpScheme(NewNumOpSchemes);
2697 181 : new_op_scheme.EquipList.allocate(1);
2698 181 : dummy_loop_equip.NumOpSchemes = NewNumOpSchemes;
2699 181 : new_op_scheme.NumEquipLists = 1;
2700 181 : new_op_scheme.OpSchemePtr = OpNum;
2701 181 : new_op_scheme.EquipList(1).ListPtr = ListNum;
2702 181 : new_op_scheme.EquipList(1).CompPtr = EquipNum;
2703 : }
2704 : }
2705 :
2706 : } // Equipment on List
2707 : } // List
2708 : } // operation scheme
2709 : } // loop
2710 :
2711 : // check the pointers to see if a single component is attached to more than one type of control scheme
2712 1605 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
2713 1147 : auto &this_plant_loop = state.dataPlnt->PlantLoop(LoopNum);
2714 3441 : for (DataPlant::LoopSideLocation LoopSideNum : DataPlant::LoopSideKeys) {
2715 2294 : auto const &this_loop_side = this_plant_loop.LoopSide(LoopSideNum);
2716 15736 : for (int BranchNum = 1, BranchNum_end = this_loop_side.TotalBranches; BranchNum <= BranchNum_end; ++BranchNum) {
2717 13442 : auto const &this_branch = this_loop_side.Branch(BranchNum);
2718 26968 : for (int CompNum = 1, CompNum_end = this_branch.TotalComponents; CompNum <= CompNum_end; ++CompNum) {
2719 13526 : auto const &this_component = this_branch.Comp(CompNum);
2720 13526 : if (allocated(this_component.OpScheme)) {
2721 2921 : for (int Index = 1; Index <= this_component.NumOpSchemes; ++Index) {
2722 1543 : int OpSchemePtr = this_component.OpScheme(Index).OpSchemePtr;
2723 1543 : if (OpSchemePtr == 0) {
2724 0 : ShowSevereError(state,
2725 0 : format("InitLoadDistribution: no operation scheme index found for component on PlantLoop={}",
2726 0 : this_plant_loop.Name));
2727 0 : ShowContinueError(state, format("Component name = {}", this_component.Name));
2728 0 : errFlag2 = true;
2729 : }
2730 1543 : DataPlant::OpScheme SchemeType{};
2731 1543 : if (Index == 1) {
2732 1362 : SchemeType = this_plant_loop.OpScheme(OpSchemePtr).Type;
2733 : } else {
2734 181 : if (SchemeType != this_plant_loop.OpScheme(OpSchemePtr).Type) {
2735 : // CALL FATAL ERROR 'component may not be specified on two types of operation schemes
2736 : // Cannot different op schemes be in effect at different times?
2737 : // I thought this would be allowed??
2738 : }
2739 : }
2740 : }
2741 : }
2742 : }
2743 : }
2744 : }
2745 : }
2746 :
2747 : // fill out information on which equipment list is the "last" meaning it has the highest upper limit for load range
2748 1605 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
2749 1147 : auto &this_plant_loop = state.dataPlnt->PlantLoop(LoopNum);
2750 2416 : for (int OpNum = 1, OpNum_end = this_plant_loop.NumOpSchemes; OpNum <= OpNum_end; ++OpNum) {
2751 1269 : auto &this_op_scheme = this_plant_loop.OpScheme(OpNum);
2752 : // skip non-load based op schemes
2753 1269 : if ((this_op_scheme.Type != OpScheme::HeatingRB) && (this_op_scheme.Type != OpScheme::CoolingRB)) continue;
2754 1189 : HighestRange = 0.0;
2755 2529 : for (int ListNum = 1, ListNum_end = this_op_scheme.NumEquipLists; ListNum <= ListNum_end; ++ListNum) {
2756 1340 : HighestRange = max(HighestRange, this_op_scheme.EquipList(ListNum).RangeUpperLimit);
2757 : } // List
2758 2529 : for (int ListNum = 1, ListNum_end = this_op_scheme.NumEquipLists; ListNum <= ListNum_end; ++ListNum) {
2759 1340 : if (HighestRange == this_op_scheme.EquipList(ListNum).RangeUpperLimit) {
2760 1189 : this_op_scheme.EquipListNumForLastStage = ListNum;
2761 : }
2762 : }
2763 : } // operation scheme
2764 : } // loop
2765 :
2766 458 : state.dataPlantCondLoopOp->InitLoadDistributionOneTimeFlag = false;
2767 : }
2768 :
2769 31741579 : if (state.dataPlnt->AnyEMSPlantOpSchemesInModel) { // Execute any Initialization EMS program calling managers for User-Defined operation.
2770 1943560 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
2771 1554848 : auto &this_plant_loop = state.dataPlnt->PlantLoop(LoopNum);
2772 3109696 : for (int OpNum = 1, OpNum_end = this_plant_loop.NumOpSchemes; OpNum <= OpNum_end; ++OpNum) {
2773 1554848 : auto &this_op_scheme = this_plant_loop.OpScheme(OpNum);
2774 1554848 : if (this_op_scheme.Type == OpScheme::EMS) {
2775 1166136 : if (state.dataGlobal->BeginEnvrnFlag && this_op_scheme.MyEnvrnFlag) {
2776 30 : if (this_op_scheme.ErlInitProgramMngr > 0) {
2777 : bool anyEMSRan;
2778 5 : ManageEMS(state, EMSManager::EMSCallFrom::UserDefinedComponentModel, anyEMSRan, this_op_scheme.ErlInitProgramMngr);
2779 25 : } else if (this_op_scheme.initPluginLocation > -1) {
2780 0 : state.dataPluginManager->pluginManager->runSingleUserDefinedPlugin(state, this_op_scheme.initPluginLocation);
2781 : }
2782 30 : this_op_scheme.MyEnvrnFlag = false;
2783 : }
2784 1166136 : if (!state.dataGlobal->BeginEnvrnFlag) this_op_scheme.MyEnvrnFlag = true;
2785 : }
2786 : } // operation scheme
2787 : } // loop
2788 : }
2789 :
2790 : // FIRST HVAC INITS
2791 31741579 : if (FirstHVACIteration) {
2792 62901638 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
2793 47555535 : auto &this_plant_loop = state.dataPlnt->PlantLoop(LoopNum);
2794 142666605 : for (DataPlant::LoopSideLocation LoopSideNum : LoopSideKeys) {
2795 95111070 : auto &this_loop_side = this_plant_loop.LoopSide(LoopSideNum);
2796 675251648 : for (int BranchNum = 1, BranchNum_end = this_loop_side.TotalBranches; BranchNum <= BranchNum_end; ++BranchNum) {
2797 580140578 : auto &this_branch = this_loop_side.Branch(BranchNum);
2798 1163896283 : for (int CompNum = 1, CompNum_end = this_branch.TotalComponents; CompNum <= CompNum_end; ++CompNum) {
2799 583755705 : auto &this_component = this_branch.Comp(CompNum);
2800 : // initalize components 'ON-AVAILABLE-NO LOAD-NO EMS CTRL'
2801 583755705 : this_component.ON = true;
2802 583755705 : this_component.Available = true;
2803 583755705 : this_component.MyLoad = 0.0;
2804 583755705 : this_component.EMSLoadOverrideOn = false;
2805 : // Zero out the old curOpSchemePtr so that we don't get 'carry-over' when we update schedules
2806 583755705 : if (this_component.CurOpSchemeType != OpScheme::Demand && this_component.CurOpSchemeType != OpScheme::Pump &&
2807 298206723 : this_component.CurOpSchemeType != OpScheme::WSEcon && this_component.CurOpSchemeType != OpScheme::NoControl) {
2808 57414960 : this_component.CurOpSchemeType = OpScheme::NoControl;
2809 : }
2810 583755705 : this_component.CurCompLevelOpNum = 0;
2811 : }
2812 : }
2813 : }
2814 : }
2815 : // set sim flag so each supervisor is only simulated once in the plant loop below
2816 15449755 : for (DataPlant::ChillerHeaterSupervisoryOperationData &supervisor : state.dataPlantCondLoopOp->ChillerHeaterSupervisoryOperationSchemes) {
2817 103652 : supervisor.needsSimulation = true;
2818 : }
2819 : // Update the OpScheme schedules
2820 62901638 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
2821 47555535 : auto &this_loop = state.dataPlnt->PlantLoop(LoopNum);
2822 100691478 : for (int OpNum = 1; OpNum <= this_loop.NumOpSchemes; ++OpNum) {
2823 53135943 : auto &this_op_scheme = this_loop.OpScheme(OpNum);
2824 :
2825 53135943 : if (this_op_scheme.Type == OpScheme::ChillerHeaterSupervisory) {
2826 326552 : if (this_op_scheme.ChillerHeaterSupervisoryOperation != nullptr &&
2827 326552 : this_op_scheme.ChillerHeaterSupervisoryOperation->needsSimulation) {
2828 103652 : this_op_scheme.ChillerHeaterSupervisoryOperation->EvaluateChillerHeaterChangeoverOpScheme(state);
2829 103652 : this_op_scheme.ChillerHeaterSupervisoryOperation->needsSimulation = false;
2830 : }
2831 326552 : continue;
2832 : }
2833 :
2834 52809391 : if (GetCurrentScheduleValue(state, this_op_scheme.SchedPtr) > 0.0) {
2835 47261177 : this_op_scheme.Available = true;
2836 98408674 : for (int ListNum = 1, ListNum_end = this_op_scheme.NumEquipLists; ListNum <= ListNum_end; ++ListNum) {
2837 51147497 : auto &this_equip_list = this_op_scheme.EquipList(ListNum);
2838 : // The component loop loads the pointers from the OpScheme data structure
2839 : // If the component happens to be active in more than schedule, the *LAST*
2840 : // schedule found will be activated
2841 110454635 : for (int CompNum = 1; CompNum <= this_equip_list.NumComps; ++CompNum) {
2842 :
2843 : // set up a reference to the component instance on the list data structure
2844 59307138 : auto const &this_list_component = this_equip_list.Comp(CompNum);
2845 :
2846 : // then look up the component topological position from this structure
2847 59307138 : int LoopPtr = this_list_component.LoopNumPtr;
2848 59307138 : LoopSidePtr = this_list_component.LoopSideNumPtr;
2849 59307138 : int BranchPtr = this_list_component.BranchNumPtr;
2850 59307138 : int CompPtr = this_list_component.CompNumPtr;
2851 :
2852 : // then set up a reference to the component on the plant data structure
2853 59307138 : auto &this_loop_component = state.dataPlnt->PlantLoop(LoopPtr).LoopSide(LoopSidePtr).Branch(BranchPtr).Comp(CompPtr);
2854 :
2855 59307138 : if (this_loop_component.CurOpSchemeType != OpScheme::Pump) {
2856 59307138 : this_loop_component.CurOpSchemeType = this_op_scheme.Type;
2857 : } else {
2858 0 : ShowSevereError(state,
2859 : "Invalid [pump] component found on equipment list. Pumps are not allowed on equipment lists.");
2860 0 : ShowContinueError(state, format("Problem component name = {}", this_op_scheme.EquipList(ListNum).Comp(CompNum).Name));
2861 0 : ShowContinueError(state, "Remove pump component and place other plant equipment on the list to correct.");
2862 0 : errFlag2 = true;
2863 : }
2864 :
2865 127609820 : for (int CompOpNum = 1; CompOpNum <= this_loop_component.NumOpSchemes; ++CompOpNum) {
2866 68302682 : if (this_loop_component.OpScheme(CompOpNum).OpSchemePtr == OpNum) {
2867 59307138 : this_loop_component.CurCompLevelOpNum = CompOpNum;
2868 : }
2869 : }
2870 : }
2871 : }
2872 : } else {
2873 5548214 : this_op_scheme.Available = false;
2874 : }
2875 : }
2876 : }
2877 : } else { // call supervisory scheme every iteration
2878 16395476 : if (!state.dataPlantCondLoopOp->ChillerHeaterSupervisoryOperationSchemes.empty()) {
2879 : // set sim flag so each supervisor is only simulated once in the plant loop below
2880 453386 : for (DataPlant::ChillerHeaterSupervisoryOperationData &supervisor : state.dataPlantCondLoopOp->ChillerHeaterSupervisoryOperationSchemes) {
2881 226693 : supervisor.needsSimulation = true;
2882 : }
2883 1231306 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
2884 1004613 : auto &this_loop = state.dataPlnt->PlantLoop(LoopNum);
2885 2009226 : for (int OpNum = 1; OpNum <= this_loop.NumOpSchemes; ++OpNum) {
2886 1004613 : auto &this_op_scheme = this_loop.OpScheme(OpNum);
2887 1004613 : if (this_op_scheme.Type == OpScheme::ChillerHeaterSupervisory) {
2888 649068 : if (this_op_scheme.ChillerHeaterSupervisoryOperation != nullptr &&
2889 649068 : this_op_scheme.ChillerHeaterSupervisoryOperation->needsSimulation) {
2890 226693 : this_op_scheme.ChillerHeaterSupervisoryOperation->EvaluateChillerHeaterChangeoverOpScheme(state);
2891 226693 : this_op_scheme.ChillerHeaterSupervisoryOperation->needsSimulation = false;
2892 : }
2893 649068 : continue;
2894 : }
2895 : }
2896 : }
2897 : }
2898 : }
2899 :
2900 31741579 : if (errFlag2) {
2901 0 : ShowFatalError(state, "InitLoadDistribution: Fatal error caused by previous severe error(s).");
2902 : }
2903 : }
2904 :
2905 : // End Initialization Section of the Plant Loop Module
2906 : //******************************************************************************
2907 :
2908 : // Begin Load Calculation/Distribution Section of the Plant Loop Module
2909 : //******************************************************************************
2910 :
2911 17696593 : void DistributePlantLoad(EnergyPlusData &state,
2912 : int const LoopNum,
2913 : const LoopSideLocation LoopSideNum,
2914 : int const CurSchemePtr, // use as index in PlantLoop()OpScheme() data structure
2915 : int const ListPtr, // use as index in PlantLoop()OpScheme() data structure
2916 : Real64 const LoopDemand,
2917 : Real64 &RemLoopDemand)
2918 : {
2919 :
2920 : // SUBROUTINE INFORMATION:
2921 : // AUTHOR Dan Fisher
2922 : // DATE WRITTEN July 1998
2923 : // MODIFIED na
2924 : // RE-ENGINEERED July 2010
2925 : // Sept 2010 B. Griffith, retain actual sign of load values
2926 : // July 2014 M. Mitchell, added SequentialUniformPLR and UniformPLR schemes
2927 :
2928 : // PURPOSE OF THIS SUBROUTINE: This subroutine distributes the load
2929 : // to plant equipment according to one of two distribution schemes:
2930 : // OPTIMAL = 1
2931 : // SEQUENTIALLOAD = 2
2932 : // UNIFORMLOAD = 3
2933 : // UNIFORMPLR = 4
2934 : // SEQUENTIALUNIFORMPLR = 5
2935 : // METHODOLOGY EMPLOYED:
2936 : // na
2937 : // REFERENCES:
2938 : // na
2939 : // Using/Aliasing
2940 : using namespace DataLoopNode;
2941 :
2942 : // Locals
2943 : // SUBROUTINE ARGUMENT DEFINITIONS:
2944 :
2945 : // SUBROUTINE PARAMETER DEFINITIONS:
2946 : // na
2947 : // INTERFACE BLOCK SPECIFICATIONS
2948 : // na
2949 : // DERIVED TYPE DEFINITIONS
2950 : // na
2951 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2952 : Real64 ChangeInLoad;
2953 : Real64 DivideLoad;
2954 : Real64 UniformLoad;
2955 : Real64 NewLoad;
2956 : Real64 PlantCapacity;
2957 : Real64 MinCompPLR;
2958 : Real64 LargestMinCompPLR;
2959 : Real64 PlantPLR;
2960 : Real64 CompLoad;
2961 :
2962 : int BranchNum;
2963 : int CompNum;
2964 : int CompIndex;
2965 : int NumCompsOnList;
2966 :
2967 : // start with some references
2968 17696593 : auto &this_loop = state.dataPlnt->PlantLoop(LoopNum);
2969 17696593 : auto &this_loopside = this_loop.LoopSide(LoopSideNum);
2970 17696593 : auto &this_equiplist = this_loop.OpScheme(CurSchemePtr).EquipList(ListPtr);
2971 :
2972 : struct LoadPLRPoint
2973 : {
2974 : Real64 plant_capacity_to_this_point;
2975 : Real64 largest_min_plr_to_this_point;
2976 0 : LoadPLRPoint(Real64 capacity, Real64 plr) : plant_capacity_to_this_point(capacity), largest_min_plr_to_this_point(plr)
2977 : {
2978 0 : }
2979 : };
2980 17696593 : std::vector<LoadPLRPoint> accrued_load_plr_values;
2981 :
2982 : // load local variables
2983 17696593 : NumCompsOnList = this_equiplist.NumComps;
2984 :
2985 : // Allocate array once
2986 17696593 : accrued_load_plr_values.reserve(NumCompsOnList);
2987 17696593 : RemLoopDemand = LoopDemand;
2988 17696593 : if (NumCompsOnList <= 0) return;
2989 :
2990 17696593 : if (std::abs(RemLoopDemand) < SmallLoad) {
2991 : // no load to distribute
2992 : } else {
2993 :
2994 : // OPTIMAL DISTRIBUTION SCHEME
2995 17582025 : int numAvail = 0;
2996 17582025 : switch (this_loop.LoadDistribution) {
2997 9570883 : case DataPlant::LoadingScheme::Optimal:
2998 : // step 1: load all machines to optimal PLR
2999 19665714 : for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
3000 :
3001 : // look up topology from the equipment list
3002 10094831 : BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
3003 10094831 : CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
3004 :
3005 : // create a reference to the component itself
3006 10094831 : auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
3007 :
3008 10094831 : if (!this_component.Available) continue;
3009 10094828 : ++numAvail;
3010 :
3011 10094828 : if (this_component.OptLoad > 0.0) {
3012 10001624 : ChangeInLoad = min(this_component.OptLoad, std::abs(RemLoopDemand));
3013 : } else {
3014 : // this is for some components like cooling towers don't have well defined OptLoad
3015 93204 : ChangeInLoad = std::abs(RemLoopDemand);
3016 : }
3017 :
3018 10094828 : AdjustChangeInLoadForLastStageUpperRangeLimit(state, LoopNum, CurSchemePtr, ListPtr, ChangeInLoad);
3019 :
3020 10094828 : AdjustChangeInLoadByEMSControls(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
3021 :
3022 10094828 : AdjustChangeInLoadByHowServed(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
3023 :
3024 10094828 : ChangeInLoad = max(0.0, ChangeInLoad);
3025 10094828 : this_component.MyLoad = sign(ChangeInLoad, RemLoopDemand);
3026 :
3027 10094828 : RemLoopDemand -= this_component.MyLoad;
3028 10094828 : if (std::abs(RemLoopDemand) < SmallLoad) RemLoopDemand = 0.0; // CR8631 don't just exit or %MyLoad on second device isn't reset
3029 : }
3030 :
3031 : // step 2: Evenly distribute remaining loop demand
3032 9570883 : if (numAvail > 0 && std::abs(RemLoopDemand) > SmallLoad) {
3033 523275 : DivideLoad = std::abs(RemLoopDemand) / numAvail;
3034 1083226 : for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
3035 :
3036 559951 : BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
3037 559951 : CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
3038 :
3039 : // create a reference to the component itself
3040 559951 : auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
3041 :
3042 559951 : if (!this_component.Available) continue;
3043 :
3044 559950 : NewLoad = this_component.MyLoad;
3045 559950 : NewLoad = min(this_component.MaxLoad, std::abs(NewLoad) + DivideLoad);
3046 559950 : ChangeInLoad = NewLoad - std::abs(this_component.MyLoad);
3047 559950 : this_component.MyLoad = sign(NewLoad, RemLoopDemand);
3048 559950 : RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
3049 559950 : if (std::abs(RemLoopDemand) < SmallLoad)
3050 178978 : RemLoopDemand = 0.0; // CR8631 don't just exit or %MyLoad on second device isn't
3051 : // reset
3052 : }
3053 : }
3054 :
3055 : // step 3: If RemLoopDemand is still greater than zero, look for any machine
3056 9570883 : if (numAvail > 0 && std::abs(RemLoopDemand) > SmallLoad) {
3057 722464 : for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
3058 :
3059 378167 : BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
3060 378167 : CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
3061 :
3062 : // create a reference to the component itself
3063 378167 : auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
3064 :
3065 378167 : if (!this_component.Available) continue;
3066 378166 : DivideLoad = this_component.MaxLoad - std::abs(this_component.MyLoad);
3067 378166 : ChangeInLoad = min(std::abs(RemLoopDemand), DivideLoad);
3068 378166 : this_component.MyLoad += sign(ChangeInLoad, RemLoopDemand);
3069 378166 : RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
3070 378166 : if (std::abs(RemLoopDemand) < SmallLoad)
3071 4229 : RemLoopDemand = 0.0; // CR8631 don't just exit or %MyLoad on second device isn't
3072 : // reset
3073 : }
3074 : }
3075 :
3076 9570883 : break;
3077 :
3078 : // SEQUENTIALLOAD DISTRIBUTION SCHEME
3079 7432098 : case DataPlant::LoadingScheme::Sequential:
3080 :
3081 : // step 1: Load machines in list order
3082 15206562 : for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
3083 :
3084 7774464 : BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
3085 7774464 : CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
3086 :
3087 : // create a reference to the component itself
3088 7774464 : auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
3089 :
3090 7774464 : if (!this_component.Available) continue;
3091 :
3092 7774464 : if (this_component.MaxLoad > 0.0) { // apply known limit
3093 7741984 : ChangeInLoad = min(this_component.MaxLoad, std::abs(RemLoopDemand));
3094 : } else {
3095 : // this is for some components like cooling towers don't have well defined MaxLoad
3096 32480 : ChangeInLoad = std::abs(RemLoopDemand);
3097 : }
3098 :
3099 7774464 : AdjustChangeInLoadForLastStageUpperRangeLimit(state, LoopNum, CurSchemePtr, ListPtr, ChangeInLoad);
3100 :
3101 7774464 : AdjustChangeInLoadByEMSControls(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
3102 :
3103 7774464 : AdjustChangeInLoadByHowServed(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
3104 :
3105 7774464 : ChangeInLoad = max(0.0, ChangeInLoad);
3106 7774464 : this_component.MyLoad = sign(ChangeInLoad, RemLoopDemand);
3107 7774464 : RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
3108 7774464 : if (std::abs(RemLoopDemand) < SmallLoad) RemLoopDemand = 0.0; // CR8631 don't just exit or %MyLoad on second device isn't reset
3109 : }
3110 :
3111 7432098 : break;
3112 :
3113 : // UNIFORMLOAD DISTRIBUTION SCHEME
3114 579044 : case DataPlant::LoadingScheme::Uniform:
3115 :
3116 : // step 1: distribute load equally to all available machines
3117 579044 : numAvail = 0;
3118 1651498 : for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
3119 :
3120 1072454 : BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
3121 1072454 : CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
3122 :
3123 : // create a reference to the component itself
3124 1072454 : auto const &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
3125 :
3126 1072454 : if (this_component.Available) ++numAvail;
3127 : }
3128 579044 : if (numAvail > 0) {
3129 579042 : UniformLoad = std::abs(RemLoopDemand) / numAvail;
3130 : } else {
3131 2 : UniformLoad = 0.0;
3132 : }
3133 1651498 : for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
3134 :
3135 1072454 : BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
3136 1072454 : CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
3137 :
3138 : // create a reference to the component itself
3139 1072454 : auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
3140 :
3141 1072454 : if (!this_component.Available) continue;
3142 1072450 : if (this_component.MaxLoad > 0.0) {
3143 1072450 : ChangeInLoad = min(this_component.MaxLoad, UniformLoad);
3144 : } else {
3145 : // this is for some components like cooling towers don't have well defined MaxLoad
3146 0 : ChangeInLoad = std::abs(RemLoopDemand);
3147 : }
3148 :
3149 1072450 : AdjustChangeInLoadForLastStageUpperRangeLimit(state, LoopNum, CurSchemePtr, ListPtr, ChangeInLoad);
3150 :
3151 1072450 : AdjustChangeInLoadByEMSControls(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
3152 :
3153 1072450 : AdjustChangeInLoadByHowServed(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
3154 1072450 : ChangeInLoad = max(0.0, ChangeInLoad);
3155 1072450 : this_component.MyLoad = sign(ChangeInLoad, RemLoopDemand);
3156 1072450 : RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
3157 1072450 : if (std::abs(RemLoopDemand) < SmallLoad) RemLoopDemand = 0.0;
3158 : }
3159 :
3160 : // step 2: If RemLoopDemand is not zero, then distribute remainder sequentially.
3161 579044 : if (std::abs(RemLoopDemand) > SmallLoad) {
3162 345799 : for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
3163 :
3164 217520 : BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
3165 217520 : CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
3166 :
3167 : // create a reference to the component itself
3168 217520 : auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
3169 :
3170 217520 : if (!this_component.Available) continue;
3171 217516 : ChangeInLoad = min(this_component.MaxLoad - std::abs(this_component.MyLoad), std::abs(RemLoopDemand));
3172 217516 : ChangeInLoad = max(0.0, ChangeInLoad);
3173 217516 : this_component.MyLoad += sign(ChangeInLoad, RemLoopDemand);
3174 217516 : RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
3175 217516 : if (std::abs(RemLoopDemand) < SmallLoad) RemLoopDemand = 0.0;
3176 : }
3177 : }
3178 :
3179 579044 : break;
3180 :
3181 : // UNIFORMPLR LOAD DISTRIBUTION SCHEME
3182 0 : case DataPlant::LoadingScheme::UniformPLR:
3183 : // Get total plant capacity and remove last component from list if load is less
3184 : // than plant capacity at min PLR
3185 0 : PlantCapacity = 0.0;
3186 0 : PlantPLR = 0.0;
3187 0 : MinCompPLR = 0.0;
3188 0 : LargestMinCompPLR = 0.0;
3189 :
3190 : // Determine PlantCapacity and LargestMinCompPLR
3191 0 : for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
3192 :
3193 0 : BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
3194 0 : CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
3195 :
3196 : // create a reference to the component itself
3197 0 : auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
3198 :
3199 0 : if (!this_component.Available) continue;
3200 :
3201 0 : PlantCapacity += this_component.MaxLoad;
3202 :
3203 0 : if (this_component.MaxLoad < SmallLoad) {
3204 0 : ShowWarningMessage(state,
3205 0 : format("Plant component {} has zero available capacity. Check component controls.", this_component.Name));
3206 0 : MinCompPLR = 0.0;
3207 : } else {
3208 0 : MinCompPLR = this_component.MinLoad / this_component.MaxLoad;
3209 : }
3210 :
3211 : // Set LargestMinCompPLR to largest MinCompPLR
3212 0 : LargestMinCompPLR = max(LargestMinCompPLR, MinCompPLR);
3213 :
3214 : // Update the array
3215 0 : accrued_load_plr_values.push_back(LoadPLRPoint(PlantCapacity, LargestMinCompPLR));
3216 : }
3217 :
3218 : // work backwards from full capacity down to 1 unit on
3219 0 : for (int i = accrued_load_plr_values.size() - 1; i >= 0; --i) {
3220 :
3221 : // if i == 0 then we need to take that as the resulting value
3222 0 : if (i == 0) {
3223 0 : PlantCapacity = accrued_load_plr_values[i].plant_capacity_to_this_point;
3224 0 : LargestMinCompPLR = accrued_load_plr_values[i].largest_min_plr_to_this_point;
3225 0 : break;
3226 :
3227 : // if the capacity is greater than the demand, just store the latest values and continue
3228 0 : } else if (std::abs(RemLoopDemand) <
3229 0 : (accrued_load_plr_values[i].largest_min_plr_to_this_point * accrued_load_plr_values[i].plant_capacity_to_this_point)) {
3230 0 : PlantCapacity = accrued_load_plr_values[i].plant_capacity_to_this_point;
3231 0 : LargestMinCompPLR = accrued_load_plr_values[i].largest_min_plr_to_this_point;
3232 0 : continue;
3233 :
3234 : // if the capacity is less than the demand, accept the last values from the previous iteration and exit
3235 : } else {
3236 0 : break;
3237 : }
3238 : }
3239 :
3240 : // Determine PLR for uniform PLR loading of all equipment
3241 0 : if (PlantCapacity > 0.0) {
3242 0 : PlantPLR = min(1.0, std::abs(RemLoopDemand) / PlantCapacity);
3243 : } else {
3244 0 : ShowWarningError(state, format("Zero available plant capacity for Plant Loop = {}", state.dataPlnt->PlantLoop(LoopNum).Name));
3245 : }
3246 :
3247 : // Distribute load to each machine
3248 0 : for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
3249 :
3250 0 : CompLoad = 0.0;
3251 :
3252 0 : BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
3253 0 : CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
3254 :
3255 : // create a reference to the component itself
3256 0 : auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
3257 :
3258 0 : if (!this_component.Available) continue;
3259 :
3260 0 : CompLoad = PlantPLR * this_component.MaxLoad;
3261 :
3262 0 : if (this_component.MaxLoad > 0.0) {
3263 0 : ChangeInLoad = min(std::abs(RemLoopDemand), CompLoad);
3264 : } else {
3265 : // this is for some components like cooling towers don't have well defined MaxLoad
3266 0 : ChangeInLoad = std::abs(RemLoopDemand);
3267 : }
3268 :
3269 0 : AdjustChangeInLoadForLastStageUpperRangeLimit(state, LoopNum, CurSchemePtr, ListPtr, ChangeInLoad);
3270 :
3271 0 : AdjustChangeInLoadByEMSControls(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
3272 :
3273 0 : AdjustChangeInLoadByHowServed(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
3274 :
3275 0 : ChangeInLoad = max(0.0, ChangeInLoad);
3276 :
3277 0 : this_component.MyLoad = sign(ChangeInLoad, RemLoopDemand);
3278 :
3279 0 : RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
3280 :
3281 0 : if (std::abs(RemLoopDemand) < SmallLoad) RemLoopDemand = 0.0;
3282 : }
3283 :
3284 0 : break;
3285 :
3286 : // SEQUENTIALUNIFORMPLR LOAD DISTRIBUTION SCHEME
3287 0 : case DataPlant::LoadingScheme::SequentialUniformPLR:
3288 :
3289 0 : PlantCapacity = 0.0;
3290 0 : PlantPLR = 0.0;
3291 0 : MinCompPLR = 0.0;
3292 0 : LargestMinCompPLR = 0.0;
3293 :
3294 : // Determine PlantCapacity and LargestMinCompPLR
3295 0 : for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
3296 :
3297 0 : BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
3298 0 : CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
3299 :
3300 : // create a reference to the component itself
3301 0 : auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
3302 :
3303 0 : if (!this_component.Available) continue;
3304 :
3305 0 : PlantCapacity += this_component.MaxLoad;
3306 :
3307 0 : if (this_component.MaxLoad < SmallLoad) {
3308 0 : ShowWarningMessage(state,
3309 0 : format("Plant component {} has zero available capacity. Check component controls.", this_component.Name));
3310 0 : MinCompPLR = 0.0;
3311 : } else {
3312 0 : MinCompPLR = this_component.MinLoad / this_component.MaxLoad;
3313 : }
3314 :
3315 : // Set LargestMinCompPLR to largest MinCompPLR
3316 0 : if (MinCompPLR > LargestMinCompPLR) LargestMinCompPLR = MinCompPLR;
3317 :
3318 0 : if (std::abs(RemLoopDemand) <= PlantCapacity) {
3319 0 : break;
3320 : }
3321 : }
3322 :
3323 : // Determine PLR for uniform PLR loading of all equipment
3324 0 : if (PlantCapacity > 0.0) {
3325 0 : PlantPLR = min(1.0, std::abs(RemLoopDemand) / PlantCapacity);
3326 : } else {
3327 0 : ShowWarningError(state, format("Zero available plant capacity for Plant Loop = {}", state.dataPlnt->PlantLoop(LoopNum).Name));
3328 : }
3329 :
3330 : // Distribute load to each machine
3331 0 : for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
3332 :
3333 0 : CompLoad = 0.0;
3334 :
3335 0 : BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
3336 0 : CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
3337 :
3338 : // create a reference to the component itself
3339 0 : auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
3340 :
3341 0 : if (!this_component.Available) continue;
3342 :
3343 0 : CompLoad = PlantPLR * this_component.MaxLoad;
3344 :
3345 0 : if (this_component.MaxLoad > 0.0) {
3346 0 : ChangeInLoad = min(std::abs(RemLoopDemand), CompLoad);
3347 : } else {
3348 : // this is for some components like cooling towers don't have well defined MaxLoad
3349 0 : ChangeInLoad = std::abs(RemLoopDemand);
3350 : }
3351 :
3352 0 : AdjustChangeInLoadForLastStageUpperRangeLimit(state, LoopNum, CurSchemePtr, ListPtr, ChangeInLoad);
3353 :
3354 0 : AdjustChangeInLoadByEMSControls(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
3355 :
3356 0 : AdjustChangeInLoadByHowServed(state, {LoopNum, LoopSideNum, BranchNum, CompNum}, ChangeInLoad);
3357 :
3358 0 : ChangeInLoad = max(0.0, ChangeInLoad);
3359 :
3360 0 : this_component.MyLoad = sign(ChangeInLoad, RemLoopDemand);
3361 :
3362 0 : RemLoopDemand -= sign(ChangeInLoad, RemLoopDemand);
3363 :
3364 0 : if (std::abs(RemLoopDemand) < SmallLoad) RemLoopDemand = 0.0;
3365 : }
3366 0 : break;
3367 0 : default:
3368 0 : assert(false);
3369 : }
3370 :
3371 : } // load is small check
3372 :
3373 : // now update On flags according to result for MyLoad
3374 36861878 : for (CompIndex = 1; CompIndex <= NumCompsOnList; ++CompIndex) {
3375 :
3376 19165285 : BranchNum = this_equiplist.Comp(CompIndex).BranchNumPtr;
3377 19165285 : CompNum = this_equiplist.Comp(CompIndex).CompNumPtr;
3378 :
3379 : // create a reference to the component itself
3380 19165285 : auto &this_component = this_loopside.Branch(BranchNum).Comp(CompNum);
3381 :
3382 19165285 : if (std::abs(this_component.MyLoad) < SmallLoad) {
3383 876212 : this_component.ON = false;
3384 : } else {
3385 18289073 : this_component.ON = true;
3386 : }
3387 : }
3388 17696593 : }
3389 :
3390 18941742 : void AdjustChangeInLoadForLastStageUpperRangeLimit(EnergyPlusData &state,
3391 : int const LoopNum, // component topology
3392 : int const CurOpSchemePtr, // current active operation scheme
3393 : int const CurEquipListPtr, // current equipment list
3394 : Real64 &ChangeInLoad // positive magnitude of load change
3395 : )
3396 : {
3397 :
3398 : // SUBROUTINE INFORMATION:
3399 : // AUTHOR B. Griffith
3400 : // DATE WRITTEN May 2012
3401 : // MODIFIED na
3402 : // RE-ENGINEERED na
3403 :
3404 : // PURPOSE OF THIS SUBROUTINE:
3405 : // if this is the last stage for a load based operation, then limit load to upper range
3406 :
3407 : // METHODOLOGY EMPLOYED:
3408 : // <description>
3409 :
3410 : // REFERENCES:
3411 : // na
3412 :
3413 : // USE STATEMENTS:
3414 : // na
3415 :
3416 : // Locals
3417 : // SUBROUTINE ARGUMENT DEFINITIONS:
3418 :
3419 : // SUBROUTINE PARAMETER DEFINITIONS:
3420 : // na
3421 :
3422 : // INTERFACE BLOCK SPECIFICATIONS:
3423 : // na
3424 :
3425 : // DERIVED TYPE DEFINITIONS:
3426 : // na
3427 :
3428 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3429 : Real64 RangeHiLimit;
3430 :
3431 18941742 : if (state.dataPlnt->PlantLoop(LoopNum).OpScheme(CurOpSchemePtr).EquipListNumForLastStage == CurEquipListPtr) { // at final last stage
3432 :
3433 18359198 : RangeHiLimit = state.dataPlnt->PlantLoop(LoopNum).OpScheme(CurOpSchemePtr).EquipList(CurEquipListPtr).RangeUpperLimit;
3434 18359198 : ChangeInLoad = min(ChangeInLoad, RangeHiLimit);
3435 : }
3436 18941742 : }
3437 :
3438 18941742 : void AdjustChangeInLoadByHowServed(EnergyPlusData &state,
3439 : PlantLocation const &plantLoc, // component topology
3440 : Real64 &ChangeInLoad // positive magnitude of load change
3441 : )
3442 : {
3443 :
3444 : // SUBROUTINE INFORMATION:
3445 : // AUTHOR B. Griffith
3446 : // DATE WRITTEN Nov 2011
3447 : // MODIFIED March 2012, B. Griffith add controls for free cooling heat exchanger overrides of chillers
3448 : // RE-ENGINEERED na
3449 :
3450 : // PURPOSE OF THIS SUBROUTINE:
3451 : // central place to apply limits to machine load dispatch based on how the machine serves loads
3452 :
3453 : // METHODOLOGY EMPLOYED:
3454 : // Components are machines on plant equipment operation lists. Need to make adjustments to the
3455 : // load dispatch to account for limits and floating capacities.
3456 :
3457 : // SUBROUTINE PARAMETER DEFINITIONS:
3458 : static constexpr std::string_view RoutineName("PlantCondLoopOperation:DistributePlantLoad");
3459 :
3460 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3461 18941742 : Real64 CurMassFlowRate(0.0);
3462 18941742 : Real64 ToutLowLimit(0.0);
3463 18941742 : Real64 ToutHiLimit(0.0);
3464 18941742 : Real64 TinLowLimit(0.0);
3465 18941742 : Real64 Tinlet(0.0);
3466 18941742 : Real64 Tsensor(0.0);
3467 18941742 : Real64 CurSpecHeat(0.0);
3468 18941742 : Real64 QdotTmp(0.0);
3469 18941742 : int ControlNodeNum(0);
3470 :
3471 18941742 : auto &this_component = CompData::getPlantComponent(state, plantLoc);
3472 :
3473 : // start of bad band-aid, need a general and comprehensive approach for determining current capacity of all kinds of equipment
3474 : // Need to truncate the load down in case outlet temperature will hit a lower/upper limit
3475 :
3476 18941742 : switch (this_component.HowLoadServed) {
3477 :
3478 : // Chillers
3479 4867016 : case DataPlant::HowMet::ByNominalCapLowOutLimit: { // chillers with lower limit on outlet temperature
3480 :
3481 : //- Retrieve data from the plant loop data structure
3482 4867016 : CurMassFlowRate = state.dataLoopNodes->Node(this_component.NodeNumIn).MassFlowRate;
3483 4867016 : ToutLowLimit = this_component.MinOutletTemp;
3484 4867016 : Tinlet = state.dataLoopNodes->Node(this_component.NodeNumIn).Temp;
3485 4867016 : CurSpecHeat = GetSpecificHeatGlycol(state,
3486 4867016 : state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidName,
3487 : Tinlet,
3488 4867016 : state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidIndex,
3489 : RoutineName);
3490 4867016 : QdotTmp = CurMassFlowRate * CurSpecHeat * (Tinlet - ToutLowLimit);
3491 :
3492 : // !- Don't correct if Q is zero, as this could indicate a component which this hasn't been implemented or not yet turned on
3493 4867016 : if (CurMassFlowRate > 0.0) {
3494 4769342 : ChangeInLoad = min(ChangeInLoad, QdotTmp);
3495 : }
3496 :
3497 4867016 : break;
3498 : }
3499 45881 : case DataPlant::HowMet::ByNominalCapFreeCoolCntrl: {
3500 : // for chillers with free cooling shutdown (HeatExchanger:Hydronic currently)
3501 : // determine if free cooling controls shut off chiller
3502 45881 : TinLowLimit = this_component.FreeCoolCntrlMinCntrlTemp;
3503 45881 : switch (this_component.FreeCoolCntrlMode) {
3504 0 : case DataPlant::FreeCoolControlMode::WetBulb: {
3505 0 : Tsensor = state.dataEnvrn->OutWetBulbTemp;
3506 0 : break;
3507 : }
3508 0 : case DataPlant::FreeCoolControlMode::DryBulb: {
3509 0 : Tsensor = state.dataEnvrn->OutDryBulbTemp;
3510 0 : break;
3511 : }
3512 45881 : case DataPlant::FreeCoolControlMode::Loop: {
3513 45881 : ControlNodeNum = this_component.FreeCoolCntrlNodeNum;
3514 45881 : if (ControlNodeNum > 0) {
3515 45881 : Tsensor = state.dataLoopNodes->Node(ControlNodeNum).TempLastTimestep; // use lagged value for stability
3516 : } else {
3517 0 : Tsensor = 23.0;
3518 : }
3519 45881 : break;
3520 : }
3521 0 : default:
3522 0 : break;
3523 : }
3524 :
3525 45881 : if (Tsensor < TinLowLimit) { // turn off chiller to initiate free cooling
3526 1 : ChangeInLoad = 0.0;
3527 1 : this_component.Available = false;
3528 1 : this_component.FreeCoolCntrlShutDown = true;
3529 : } else {
3530 45880 : this_component.Available = true;
3531 45880 : this_component.FreeCoolCntrlShutDown = false;
3532 : }
3533 :
3534 45881 : break;
3535 : }
3536 0 : case DataPlant::HowMet::ByNominalCapLowOutLimitFreeCoolCntrl: {
3537 : // for chillers with free cooling shutdown (HeatExchanger:Hydronic currently)
3538 : // determine if free cooling controls shut off chiller
3539 0 : TinLowLimit = this_component.FreeCoolCntrlMinCntrlTemp;
3540 0 : switch (this_component.FreeCoolCntrlMode) {
3541 0 : case DataPlant::FreeCoolControlMode::WetBulb: {
3542 0 : Tsensor = state.dataEnvrn->OutWetBulbTemp;
3543 0 : break;
3544 : }
3545 0 : case DataPlant::FreeCoolControlMode::DryBulb: {
3546 0 : Tsensor = state.dataEnvrn->OutDryBulbTemp;
3547 0 : break;
3548 : }
3549 0 : case DataPlant::FreeCoolControlMode::Loop: {
3550 0 : ControlNodeNum = this_component.FreeCoolCntrlNodeNum;
3551 0 : if (ControlNodeNum > 0) {
3552 0 : Tsensor = state.dataLoopNodes->Node(ControlNodeNum).TempLastTimestep; // use lagged value for stability
3553 : } else {
3554 0 : Tsensor = 23.0;
3555 : }
3556 0 : break;
3557 : }
3558 0 : default:
3559 0 : break;
3560 : }
3561 :
3562 0 : if (Tsensor < TinLowLimit) { // turn off chiller to initiate free cooling
3563 0 : ChangeInLoad = 0.0;
3564 0 : this_component.Available = false;
3565 0 : this_component.FreeCoolCntrlShutDown = true;
3566 : } else {
3567 : //- Retrieve data from the plant loop data structure
3568 0 : this_component.Available = true;
3569 0 : this_component.FreeCoolCntrlShutDown = false;
3570 0 : CurMassFlowRate = state.dataLoopNodes->Node(this_component.NodeNumIn).MassFlowRate;
3571 0 : ToutLowLimit = this_component.MinOutletTemp;
3572 0 : Tinlet = state.dataLoopNodes->Node(this_component.NodeNumIn).Temp;
3573 0 : CurSpecHeat = GetSpecificHeatGlycol(state,
3574 0 : state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidName,
3575 : Tinlet,
3576 0 : state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidIndex,
3577 : RoutineName);
3578 0 : QdotTmp = CurMassFlowRate * CurSpecHeat * (Tinlet - ToutLowLimit);
3579 :
3580 : // !- Don't correct if Q is zero, as this could indicate a component which this hasn't been implemented or not yet turned
3581 : // on
3582 0 : if (CurMassFlowRate > 0.0) {
3583 0 : ChangeInLoad = min(ChangeInLoad, QdotTmp);
3584 : }
3585 : }
3586 :
3587 0 : break;
3588 : }
3589 4745540 : case DataPlant::HowMet::ByNominalCapHiOutLimit: { // boilers with upper limit on outlet temperature
3590 : //- Retrieve data from the plant loop data structure
3591 4745540 : CurMassFlowRate = state.dataLoopNodes->Node(this_component.NodeNumIn).MassFlowRate;
3592 4745540 : ToutHiLimit = this_component.MaxOutletTemp;
3593 4745540 : Tinlet = state.dataLoopNodes->Node(this_component.NodeNumIn).Temp;
3594 4745540 : CurSpecHeat = GetSpecificHeatGlycol(state,
3595 4745540 : state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidName,
3596 : Tinlet,
3597 4745540 : state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidIndex,
3598 : RoutineName);
3599 4745540 : QdotTmp = CurMassFlowRate * CurSpecHeat * (ToutHiLimit - Tinlet);
3600 :
3601 4745540 : if (CurMassFlowRate > 0.0) {
3602 4681709 : ChangeInLoad = min(ChangeInLoad, QdotTmp);
3603 : }
3604 :
3605 4745540 : break;
3606 : }
3607 4515564 : case DataPlant::HowMet::PassiveCap: { // need to estimate current capacity if more or less passive devices ??
3608 :
3609 4515564 : break;
3610 : }
3611 4767741 : default:
3612 4767741 : break;
3613 : }
3614 18941742 : }
3615 :
3616 1160704 : void FindCompSPLoad(EnergyPlusData &state,
3617 : PlantLocation const &plantLoc,
3618 : int const OpNum // index for Plant()%LoopSide()%Branch()%Comp()%OpScheme()
3619 : )
3620 : {
3621 :
3622 : // SUBROUTINE INFORMATION:
3623 : // AUTHOR Sankaranarayanan K P
3624 : // DATE WRITTEN Jan 2005
3625 : // MODIFIED na
3626 : // RE-ENGINEERED Dan Fisher July 2010
3627 :
3628 : // PURPOSE OF THIS SUBROUTINE:
3629 : // To calculate the load on a component controlled by
3630 : // Component SetPoint based scheme.
3631 :
3632 : // Using/Aliasing
3633 : using DataLoopNode::SensedNodeFlagValue;
3634 : using FluidProperties::GetDensityGlycol;
3635 :
3636 : // Locals
3637 : // SUBROUTINE ARGUMENT DEFINITIONS:
3638 :
3639 : // SUBROUTINE PARAMETER DEFINITIONS:
3640 : static constexpr std::string_view RoutineName("FindCompSPLoad");
3641 :
3642 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3643 : Real64 CompDemand;
3644 : Real64 DemandMdot;
3645 : Real64 ActualMdot;
3646 : Real64 TempIn;
3647 : Real64 CurSpecHeat;
3648 1160704 : Real64 TempSetPt(0.0);
3649 : Real64 CompMinLoad;
3650 : Real64 CompMaxLoad;
3651 : Real64 CompOptLoad;
3652 : int DemandNode;
3653 : int CompPtr;
3654 : int OpSchemePtr;
3655 : int ListPtr;
3656 : int SetPtNode;
3657 : int NumEquipLists;
3658 : Real64 rho;
3659 : Real64 CurrentDemandForCoolingOp;
3660 : Real64 CurrentDemandForHeatingOp;
3661 :
3662 1160704 : auto &this_component = CompData::getPlantComponent(state, plantLoc);
3663 :
3664 : // find the pointer to the 'PlantLoop()%OpScheme()'...data structure
3665 1160704 : NumEquipLists = this_component.OpScheme(OpNum).NumEquipLists;
3666 : if (NumEquipLists != 1) {
3667 : // CALL Severe error) there should be exactly one list associated with component setpoint scheme
3668 : }
3669 :
3670 1160704 : OpSchemePtr = this_component.OpScheme(OpNum).OpSchemePtr;
3671 1160704 : ListPtr = this_component.OpScheme(OpNum).EquipList(1).ListPtr;
3672 1160704 : CompPtr = this_component.OpScheme(OpNum).EquipList(1).CompPtr;
3673 :
3674 : // load local variables from the data structures
3675 1160704 : CompMinLoad = this_component.MinLoad;
3676 1160704 : CompMaxLoad = this_component.MaxLoad;
3677 1160704 : CompOptLoad = this_component.OptLoad;
3678 1160704 : DemandNode = state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).DemandNodeNum;
3679 1160704 : SetPtNode = state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).SetPointNodeNum;
3680 1160704 : TempIn = state.dataLoopNodes->Node(DemandNode).Temp;
3681 1160704 : rho = GetDensityGlycol(
3682 1160704 : state, state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidName, TempIn, state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidIndex, RoutineName);
3683 :
3684 1160704 : DemandMdot = state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).SetPointFlowRate * rho;
3685 : // DemandMDot is a constant design flow rate, next based on actual current flow rate for accurate current demand?
3686 1160704 : ActualMdot = state.dataLoopNodes->Node(DemandNode).MassFlowRate;
3687 1160704 : CurSpecHeat = GetSpecificHeatGlycol(
3688 1160704 : state, state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidName, TempIn, state.dataPlnt->PlantLoop(plantLoc.loopNum).FluidIndex, RoutineName);
3689 1160704 : if ((ActualMdot > 0.0) && (ActualMdot != DemandMdot)) {
3690 794506 : DemandMdot = ActualMdot;
3691 : }
3692 :
3693 1160704 : switch (state.dataPlnt->PlantLoop(plantLoc.loopNum).LoopDemandCalcScheme) {
3694 931488 : case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
3695 931488 : TempSetPt = state.dataLoopNodes->Node(SetPtNode).TempSetPoint;
3696 931488 : break;
3697 : }
3698 229216 : case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
3699 229216 : if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).CtrlType == CtrlType::CoolingOp) {
3700 114608 : TempSetPt = state.dataLoopNodes->Node(SetPtNode).TempSetPointHi;
3701 114608 : } else if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).CtrlType ==
3702 : CtrlType::HeatingOp) {
3703 114608 : TempSetPt = state.dataLoopNodes->Node(SetPtNode).TempSetPointLo;
3704 0 : } else if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).CtrlType == CtrlType::DualOp) {
3705 0 : CurrentDemandForCoolingOp = DemandMdot * CurSpecHeat * (state.dataLoopNodes->Node(SetPtNode).TempSetPointHi - TempIn);
3706 0 : CurrentDemandForHeatingOp = DemandMdot * CurSpecHeat * (state.dataLoopNodes->Node(SetPtNode).TempSetPointLo - TempIn);
3707 0 : if ((CurrentDemandForCoolingOp < 0.0) && (CurrentDemandForHeatingOp <= 0.0)) { // cooling
3708 0 : TempSetPt = state.dataLoopNodes->Node(SetPtNode).TempSetPointHi;
3709 0 : } else if ((CurrentDemandForCoolingOp >= 0.0) && (CurrentDemandForHeatingOp > 0.0)) { // heating
3710 0 : TempSetPt = state.dataLoopNodes->Node(SetPtNode).TempSetPointLo;
3711 : } else { // deadband
3712 0 : TempSetPt = TempIn;
3713 : }
3714 : } else {
3715 0 : assert(false);
3716 : }
3717 229216 : break;
3718 : }
3719 0 : default:
3720 0 : assert(false);
3721 : break;
3722 : }
3723 :
3724 1160704 : if (TempSetPt == SensedNodeFlagValue) {
3725 120 : this_component.ON = false;
3726 120 : this_component.MyLoad = 0.0;
3727 120 : this_component.EquipDemand = 0.0;
3728 : } else {
3729 :
3730 1160584 : CompDemand = (DemandMdot * CurSpecHeat * (TempSetPt - TempIn));
3731 :
3732 1160584 : if (std::abs(CompDemand) < LoopDemandTol) CompDemand = 0.0;
3733 1160584 : this_component.EquipDemand = CompDemand;
3734 :
3735 : // set MyLoad and runflag
3736 1160584 : if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).CtrlType == CtrlType::CoolingOp) {
3737 664376 : if (CompDemand < (-LoopDemandTol)) {
3738 461338 : this_component.ON = true;
3739 461338 : this_component.MyLoad = CompDemand;
3740 : } else {
3741 203038 : this_component.ON = false;
3742 203038 : this_component.MyLoad = 0.0;
3743 : }
3744 496208 : } else if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).CtrlType ==
3745 : CtrlType::HeatingOp) {
3746 120740 : if (CompDemand > LoopDemandTol) {
3747 1832 : this_component.ON = true;
3748 1832 : this_component.MyLoad = CompDemand;
3749 : } else {
3750 118908 : this_component.ON = false;
3751 118908 : this_component.MyLoad = 0.0;
3752 : }
3753 375468 : } else if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(OpSchemePtr).EquipList(ListPtr).Comp(CompPtr).CtrlType == CtrlType::DualOp) {
3754 375468 : if (CompDemand > LoopDemandTol || CompDemand < (-LoopDemandTol)) {
3755 234384 : this_component.ON = true;
3756 234384 : this_component.MyLoad = CompDemand;
3757 : } else {
3758 141084 : this_component.ON = false;
3759 141084 : this_component.MyLoad = 0.0;
3760 : }
3761 : }
3762 :
3763 : // Check bounds on MyLoad
3764 1160584 : if (std::abs(this_component.MyLoad) > CompMaxLoad) {
3765 457160 : this_component.MyLoad = sign(CompMaxLoad, this_component.MyLoad);
3766 : }
3767 : // PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchNum)%Comp(CompNum)%MyLoad = &
3768 : // MIN(PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchNum)%Comp(CompNum)%MyLoad,CompMaxLoad)
3769 :
3770 1160584 : if (std::abs(this_component.MyLoad) < CompMinLoad) {
3771 87432 : this_component.MyLoad = sign(CompMinLoad, this_component.MyLoad);
3772 : }
3773 : // PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchNum)%Comp(CompNum)%MyLoad = &
3774 : // MAX(PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchNum)%Comp(CompNum)%MyLoad,CompMinLoad)
3775 :
3776 : } // valid setpoint (TempSetPt /= SensedNodeFlagValue)
3777 1160704 : }
3778 :
3779 322816 : void DistributeUserDefinedPlantLoad(EnergyPlusData &state,
3780 : PlantLocation const &plantLoc,
3781 : int const CurCompLevelOpNum, // index for Plant()%LoopSide()%Branch()%Comp()%OpScheme()
3782 : int const CurSchemePtr,
3783 : Real64 const LoopDemand,
3784 : [[maybe_unused]] Real64 &RemLoopDemand)
3785 : {
3786 :
3787 : // SUBROUTINE INFORMATION:
3788 : // AUTHOR B. Griffith
3789 : // DATE WRITTEN August 2013
3790 : // MODIFIED na
3791 : // RE-ENGINEERED na
3792 :
3793 : // PURPOSE OF THIS SUBROUTINE:
3794 : // <description>
3795 :
3796 : // METHODOLOGY EMPLOYED:
3797 : // <description>
3798 :
3799 : // REFERENCES:
3800 : // na
3801 :
3802 : // Using/Aliasing
3803 : using EMSManager::ManageEMS;
3804 :
3805 : // Locals
3806 : // SUBROUTINE ARGUMENT DEFINITIONS:
3807 :
3808 : // SUBROUTINE PARAMETER DEFINITIONS:
3809 : // na
3810 :
3811 : // INTERFACE BLOCK SPECIFICATIONS:
3812 : // na
3813 :
3814 : // DERIVED TYPE DEFINITIONS:
3815 : // na
3816 :
3817 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3818 : int CompPtr;
3819 :
3820 322816 : auto &this_component = CompData::getPlantComponent(state, plantLoc);
3821 :
3822 : // ListPtr = PlantLoop(LoopNum)%LoopSide(LoopSideNum)%Branch(BranchNum)%Comp(CompNum)%OpScheme(CurCompLevelOpNum)%EquipList(1)%ListPtr
3823 322816 : CompPtr = this_component.OpScheme(CurCompLevelOpNum).EquipList(1).CompPtr;
3824 :
3825 : // fill internal variable
3826 322816 : state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).EquipList(1).Comp(CompPtr).EMSIntVarRemainingLoadValue = LoopDemand;
3827 :
3828 : // Call EMS program(s)
3829 322816 : if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).ErlSimProgramMngr > 0) {
3830 : bool anyEMSRan;
3831 161408 : ManageEMS(state,
3832 : EMSManager::EMSCallFrom::UserDefinedComponentModel,
3833 : anyEMSRan,
3834 161408 : state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).ErlSimProgramMngr);
3835 161408 : } else if (state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).simPluginLocation > -1) {
3836 161408 : state.dataPluginManager->pluginManager->runSingleUserDefinedPlugin(
3837 161408 : state, state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).simPluginLocation);
3838 : }
3839 :
3840 : // move actuated value to MyLoad
3841 :
3842 322816 : this_component.MyLoad =
3843 322816 : state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).EquipList(1).Comp(CompPtr).EMSActuatorDispatchedLoadValue;
3844 322816 : this_component.EquipDemand =
3845 322816 : state.dataPlnt->PlantLoop(plantLoc.loopNum).OpScheme(CurSchemePtr).EquipList(1).Comp(CompPtr).EMSActuatorDispatchedLoadValue;
3846 322816 : if (std::abs(this_component.MyLoad) > LoopDemandTol) {
3847 125424 : this_component.ON = true;
3848 :
3849 : } else {
3850 197392 : this_component.ON = false;
3851 : }
3852 322816 : }
3853 :
3854 : // End Load Calculation/Distribution Section of the Plant Loop Module
3855 : //******************************************************************************
3856 :
3857 : //********************************
3858 :
3859 399700 : Real64 FindRangeVariable(EnergyPlusData &state,
3860 : int const LoopNum, // PlantLoop data structure loop counter
3861 : int const CurSchemePtr, // set by PL()%LoopSide()%Branch()%Comp()%OpScheme()%OpSchemePtr
3862 : DataPlant::OpScheme CurSchemeType // identifier set in PlantData
3863 : )
3864 : {
3865 :
3866 : // SUBROUTINE INFORMATION:
3867 : // AUTHOR Sankaranarayanan K P
3868 : // DATE WRITTEN Jan 2004
3869 : // MODIFIED Chandan Sharma, August 2010
3870 : // RE-ENGINEERED na
3871 :
3872 : // Using/Aliasing
3873 : using namespace DataLoopNode;
3874 : // Return value
3875 399700 : Real64 FindRangeVariable(0.0);
3876 :
3877 : // Locals
3878 : // SUBROUTINE ARGUMENT DEFINITIONS:
3879 : // used to locate data in PL()%OpScheme(CurSchemePtr)
3880 : // SUBROUTINE PARAMETER DEFINITIONS:
3881 : // na
3882 :
3883 : // INTERFACE BLOCK SPECIFICATIONS
3884 : // na
3885 :
3886 : // DERIVED TYPE DEFINITIONS
3887 : // na
3888 :
3889 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3890 : int ReferenceNodeNum;
3891 : Real64 NodeTemperature;
3892 :
3893 399700 : switch (CurSchemeType) {
3894 14584 : case OpScheme::DryBulbTDB: { // drybulb temp based controls
3895 14584 : ReferenceNodeNum = state.dataPlnt->PlantLoop(LoopNum).OpScheme(CurSchemePtr).ReferenceNodeNumber;
3896 14584 : NodeTemperature = state.dataLoopNodes->Node(ReferenceNodeNum).Temp;
3897 14584 : FindRangeVariable = NodeTemperature - state.dataEnvrn->OutDryBulbTemp;
3898 14584 : break;
3899 : }
3900 370572 : case OpScheme::WetBulbTDB: { // wetbulb temp based controls
3901 370572 : ReferenceNodeNum = state.dataPlnt->PlantLoop(LoopNum).OpScheme(CurSchemePtr).ReferenceNodeNumber;
3902 370572 : NodeTemperature = state.dataLoopNodes->Node(ReferenceNodeNum).Temp;
3903 370572 : FindRangeVariable = NodeTemperature - state.dataEnvrn->OutWetBulbTemp;
3904 370572 : break;
3905 : }
3906 14544 : case OpScheme::DewPointTDB: { // dewpoint temp based controls
3907 14544 : ReferenceNodeNum = state.dataPlnt->PlantLoop(LoopNum).OpScheme(CurSchemePtr).ReferenceNodeNumber;
3908 14544 : NodeTemperature = state.dataLoopNodes->Node(ReferenceNodeNum).Temp;
3909 14544 : FindRangeVariable = NodeTemperature - state.dataEnvrn->OutDewPointTemp;
3910 14544 : break;
3911 : }
3912 0 : default: {
3913 0 : assert(false);
3914 : break;
3915 : }
3916 : } // OperationScheme
3917 :
3918 399700 : return FindRangeVariable;
3919 : }
3920 :
3921 : //********************************
3922 :
3923 : // Begin Plant Loop ON/OFF Utility Subroutines
3924 : //******************************************************************************
3925 :
3926 19180113 : void TurnOnPlantLoopPipes(EnergyPlusData &state, int const LoopNum, const LoopSideLocation LoopSideNum)
3927 : {
3928 : // SUBROUTINE INFORMATION:
3929 : // AUTHOR Dan Fisher
3930 : // DATE WRITTEN July 1998
3931 : // MODIFIED na
3932 : // RE-ENGINEERED na
3933 :
3934 : // PURPOSE OF THIS SUBROUTINE: This subroutine sets a logical flag
3935 : // for the loop circulation pump to TRUE.
3936 :
3937 : // METHODOLOGY EMPLOYED:
3938 : // na
3939 : // REFERENCES:
3940 : // na
3941 : // USE STATEMENTS:
3942 : // na
3943 :
3944 : // Locals
3945 : // SUBROUTINE ARGUMENT DEFINITIONS:
3946 :
3947 : // SUBROUTINE PARAMETER DEFINITIONS:
3948 : // na
3949 : // INTERFACE BLOCK SPECIFICATIONS
3950 : // na
3951 : // DERIVED TYPE DEFINITIONS
3952 : // na
3953 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3954 : int MachineOnLoopNum;
3955 : int Num;
3956 :
3957 98352680 : for (Num = 1; Num <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).TotalBranches; ++Num) {
3958 160583675 : for (MachineOnLoopNum = 1; MachineOnLoopNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).TotalComponents;
3959 : ++MachineOnLoopNum) {
3960 81411108 : switch (state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnLoopNum).Type) {
3961 37562619 : case DataPlant::PlantEquipmentType::Pipe:
3962 : case DataPlant::PlantEquipmentType::PipeInterior:
3963 : case DataPlant::PlantEquipmentType::PipeExterior:
3964 : case DataPlant::PlantEquipmentType::PipeUnderground: {
3965 37562619 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnLoopNum).ON = true;
3966 37562619 : break;
3967 : }
3968 43848489 : default:
3969 43848489 : break; // Don't do anything
3970 : }
3971 : }
3972 : }
3973 19180113 : }
3974 :
3975 16712 : void TurnOffLoopEquipment(EnergyPlusData &state, int const LoopNum)
3976 : {
3977 : // SUBROUTINE INFORMATION:
3978 : // AUTHOR D.E. Fisher
3979 : // DATE WRITTEN July 1998
3980 : // MODIFIED D.E. Fisher, Aug. 2010
3981 : // RE-ENGINEERED
3982 :
3983 : // PURPOSE OF THIS SUBROUTINE:
3984 : // METHODOLOGY EMPLOYED:
3985 : // na
3986 : // REFERENCES:
3987 : // na
3988 : // USE STATEMENTS:
3989 : // na
3990 :
3991 : // Locals
3992 : // SUBROUTINE ARGUMENT DEFINITIONS:
3993 :
3994 : // SUBROUTINE PARAMETER DEFINITIONS:
3995 : // na
3996 : // INTERFACE BLOCK SPECIFICATIONS
3997 : // na
3998 : // DERIVED TYPE DEFINITIONS
3999 : // na
4000 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4001 : int MachineOnBranch;
4002 : int Num;
4003 :
4004 50136 : for (DataPlant::LoopSideLocation LoopSideNum : LoopSideKeys) {
4005 167120 : for (Num = 1; Num <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).TotalBranches; ++Num) {
4006 267392 : for (MachineOnBranch = 1; MachineOnBranch <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).TotalComponents;
4007 : ++MachineOnBranch) {
4008 : // Sankar Non Integrated Economizer
4009 133696 : if (!DataPlant::PlantEquipmentTypeIsPump[static_cast<int>(
4010 133696 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnBranch).Type)]) {
4011 116984 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnBranch).ON = false;
4012 116984 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnBranch).MyLoad = 0.0;
4013 : }
4014 : }
4015 : }
4016 : }
4017 16712 : }
4018 :
4019 0 : void TurnOffLoopSideEquipment(EnergyPlusData &state, int const LoopNum, const LoopSideLocation LoopSideNum)
4020 : {
4021 : // SUBROUTINE INFORMATION:
4022 : // AUTHOR D.E. Fisher
4023 : // DATE WRITTEN July 1998
4024 : // MODIFIED D.E. Fisher, Aug. 2010
4025 : // RE-ENGINEERED
4026 :
4027 : // PURPOSE OF THIS SUBROUTINE:
4028 : // METHODOLOGY EMPLOYED:
4029 : // na
4030 : // REFERENCES:
4031 : // na
4032 : // USE STATEMENTS:
4033 : // na
4034 :
4035 : // Locals
4036 : // SUBROUTINE ARGUMENT DEFINITIONS:
4037 :
4038 : // SUBROUTINE PARAMETER DEFINITIONS:
4039 : // na
4040 : // INTERFACE BLOCK SPECIFICATIONS
4041 : // na
4042 : // DERIVED TYPE DEFINITIONS
4043 : // na
4044 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4045 : int MachineOnBranch;
4046 : int Num;
4047 :
4048 0 : for (Num = 1; Num <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).TotalBranches; ++Num) {
4049 0 : for (MachineOnBranch = 1; MachineOnBranch <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).TotalComponents;
4050 : ++MachineOnBranch) {
4051 : // Sankar Non Integrated Economizer
4052 0 : if (!DataPlant::PlantEquipmentTypeIsPump[static_cast<int>(
4053 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnBranch).Type)]) {
4054 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnBranch).ON = false;
4055 0 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(Num).Comp(MachineOnBranch).MyLoad = 0.0;
4056 : }
4057 : }
4058 : }
4059 0 : }
4060 :
4061 : // End Plant Loop ON/OFF Utility Subroutines
4062 : //******************************************************************************
4063 :
4064 : // Begin Plant EMS Control Routines
4065 : //******************************************************************************
4066 :
4067 73 : void SetupPlantEMSActuators(EnergyPlusData &state)
4068 : {
4069 :
4070 : // SUBROUTINE INFORMATION:
4071 : // AUTHOR D.E. Fisher
4072 : // DATE WRITTEN Feb 2007
4073 : // MODIFIED B. Griffith August 2009, D. Fisher, Aug. 2010
4074 : // RE-ENGINEERED na
4075 :
4076 : // PURPOSE OF THIS SUBROUTINE:
4077 : // This subroutine loads the plant EMS actuators
4078 :
4079 : // METHODOLOGY EMPLOYED:
4080 : // Call the setupAcuator routine
4081 :
4082 : // Locals
4083 : static constexpr std::string_view Units("[on/off]");
4084 :
4085 191 : for (int LoopNum = 1; LoopNum <= state.dataPlnt->TotNumLoops; ++LoopNum) {
4086 118 : std::string ActuatorName = "Plant Loop Overall";
4087 118 : std::string UniqueIDName = state.dataPlnt->PlantLoop(LoopNum).Name;
4088 118 : std::string ActuatorType = "On/Off Supervisory";
4089 118 : SetupEMSActuator(state,
4090 : ActuatorName,
4091 : UniqueIDName,
4092 : ActuatorType,
4093 : Units,
4094 118 : state.dataPlnt->PlantLoop(LoopNum).EMSCtrl,
4095 118 : state.dataPlnt->PlantLoop(LoopNum).EMSValue);
4096 :
4097 118 : ActuatorName = "Supply Side Half Loop";
4098 118 : UniqueIDName = state.dataPlnt->PlantLoop(LoopNum).Name;
4099 118 : ActuatorType = "On/Off Supervisory";
4100 118 : SetupEMSActuator(state,
4101 : ActuatorName,
4102 : UniqueIDName,
4103 : ActuatorType,
4104 : Units,
4105 118 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideLocation::Supply).EMSCtrl,
4106 118 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideLocation::Supply).EMSValue);
4107 :
4108 118 : ActuatorName = "Demand Side Half Loop";
4109 118 : UniqueIDName = state.dataPlnt->PlantLoop(LoopNum).Name;
4110 118 : ActuatorType = "On/Off Supervisory";
4111 118 : SetupEMSActuator(state,
4112 : ActuatorName,
4113 : UniqueIDName,
4114 : ActuatorType,
4115 : Units,
4116 118 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideLocation::Demand).EMSCtrl,
4117 118 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideLocation::Demand).EMSValue);
4118 :
4119 354 : for (DataPlant::LoopSideLocation LoopSideNum : LoopSideKeys) {
4120 2520 : for (int BranchNum = 1; BranchNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).TotalBranches; ++BranchNum) {
4121 2284 : if (LoopSideNum == LoopSideLocation::Supply) {
4122 488 : ActuatorName = "Supply Side Branch";
4123 488 : UniqueIDName = state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Name;
4124 488 : ActuatorType = "On/Off Supervisory";
4125 488 : SetupEMSActuator(state,
4126 : ActuatorName,
4127 : UniqueIDName,
4128 : ActuatorType,
4129 : Units,
4130 488 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).EMSCtrlOverrideOn,
4131 488 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).EMSCtrlOverrideValue);
4132 1796 : } else if (LoopSideNum == LoopSideLocation::Demand) {
4133 1796 : ActuatorName = "Demand Side Branch";
4134 1796 : UniqueIDName = state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Name;
4135 1796 : ActuatorType = "On/Off Supervisory";
4136 1796 : SetupEMSActuator(state,
4137 : ActuatorName,
4138 : UniqueIDName,
4139 : ActuatorType,
4140 : Units,
4141 1796 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).EMSCtrlOverrideOn,
4142 1796 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).EMSCtrlOverrideValue);
4143 : }
4144 4583 : for (int CompNum = 1; CompNum <= state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).TotalComponents;
4145 : ++CompNum) {
4146 4598 : ActuatorName = format("Plant Component {}",
4147 : PlantEquipTypeNames[static_cast<int>(
4148 4598 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Comp(CompNum).Type)]);
4149 2299 : UniqueIDName = state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Comp(CompNum).Name;
4150 2299 : ActuatorType = "On/Off Supervisory";
4151 2299 : SetupEMSActuator(state,
4152 : ActuatorName,
4153 : UniqueIDName,
4154 : ActuatorType,
4155 : "[fraction]",
4156 2299 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Comp(CompNum).EMSLoadOverrideOn,
4157 2299 : state.dataPlnt->PlantLoop(LoopNum).LoopSide(LoopSideNum).Branch(BranchNum).Comp(CompNum).EMSLoadOverrideValue);
4158 : }
4159 : }
4160 : }
4161 118 : }
4162 73 : }
4163 :
4164 38702348 : void ActivateEMSControls(EnergyPlusData &state, PlantLocation const &plantLoc, bool &LoopShutDownFlag)
4165 : {
4166 :
4167 : // SUBROUTINE INFORMATION:
4168 : // AUTHOR D.E. Fisher
4169 : // DATE WRITTEN Feb 2007
4170 : // MODIFIED
4171 : // RE-ENGINEERED na
4172 :
4173 : // PURPOSE OF THIS SUBROUTINE:
4174 : // This subroutine loads the plant EMS actuators
4175 :
4176 : // METHODOLOGY EMPLOYED: The EMS flags are evaluated in hierarchical order:
4177 : // LOOP flags override branch and component flags
4178 : // BRANCH flags override component flags
4179 : // If the loop flag (EMSCtrl) is true, then
4180 : // IF EMSValue <= 0, shut down the entire loop including the pumps
4181 : // IF EMSValue > 0, no action
4182 : // If the LoopSide flag (EMSCtrl) is true, then:
4183 : // IF EMSValue <=0, shut down all components on the LoopSide except the pumps
4184 : // IF EMSValue > 0, no action
4185 : // If a component flag (EMSCtrl) is true, then:
4186 : // EMSValue <=0, shut down the component
4187 : // EMSValue > 0, calc. component load: MyLoad=MIN(MaxCompLoad,MaxCompLoad*EMSValue)
4188 :
4189 : // REFERENCES:
4190 : // na
4191 :
4192 : // Using/Aliasing
4193 : using namespace DataLoopNode;
4194 :
4195 : // SUBROUTINE ARGUMENT DEFINITIONS
4196 :
4197 : // Locals
4198 : // SUBROUTINE PARAMETER DEFINITIONS
4199 : static constexpr std::string_view RoutineName("ActivateEMSControls");
4200 :
4201 : // SUBROUTINE VARIABLE DEFINITIONS
4202 : Real64 CurMassFlowRate;
4203 : Real64 ToutLowLimit;
4204 : Real64 Tinlet;
4205 : Real64 CurSpecHeat;
4206 : Real64 QTemporary;
4207 : // unused REAL(r64) :: ChangeInLoad
4208 :
4209 : // MODULE VARIABLE DECLARATIONS:
4210 :
4211 : // set up some nice references to avoid lookups
4212 38702348 : auto &this_loop = state.dataPlnt->PlantLoop(plantLoc.loopNum);
4213 38702348 : auto &this_loopside = this_loop.LoopSide(plantLoc.loopSideNum);
4214 38702348 : auto &this_comp = this_loopside.Branch(plantLoc.branchNum).Comp(plantLoc.compNum);
4215 :
4216 : // Loop Control
4217 38702348 : if (this_loop.EMSCtrl) {
4218 8356 : if (this_loop.EMSValue <= 0.0) {
4219 8356 : LoopShutDownFlag = true;
4220 8356 : TurnOffLoopEquipment(state, plantLoc.loopNum);
4221 153468 : return;
4222 : } else {
4223 0 : LoopShutDownFlag = false;
4224 : }
4225 : } else {
4226 38693992 : LoopShutDownFlag = false;
4227 : }
4228 :
4229 : // Half-loop control
4230 38693992 : if (this_loopside.EMSCtrl) {
4231 0 : if (this_loopside.EMSValue <= 0.0) {
4232 0 : TurnOffLoopSideEquipment(state, plantLoc.loopNum, plantLoc.loopSideNum);
4233 0 : return;
4234 : } else {
4235 : // do nothing: can't turn all LoopSide equip. ON with loop switch
4236 : }
4237 : }
4238 :
4239 38693992 : if (this_comp.EMSLoadOverrideOn) {
4240 : // EMSValue <= 0 turn component OFF
4241 145112 : if (this_comp.EMSLoadOverrideValue <= 0.0) {
4242 145112 : this_comp.ON = false;
4243 145112 : this_comp.Available = false;
4244 145112 : this_comp.MyLoad = 0.0;
4245 145112 : return;
4246 : } else {
4247 : // EMSValue > 0 Set Component Load and Turn component ON
4248 0 : this_comp.ON = true;
4249 0 : this_comp.Available = false;
4250 0 : this_comp.MyLoad = min(this_comp.MaxLoad, (this_comp.MaxLoad * this_comp.EMSLoadOverrideValue));
4251 :
4252 : // Check lower/upper temperature limit for chillers
4253 0 : switch (this_comp.Type) {
4254 :
4255 0 : case DataPlant::PlantEquipmentType::Chiller_ElectricEIR:
4256 : case DataPlant::PlantEquipmentType::Chiller_Electric:
4257 : case DataPlant::PlantEquipmentType::Chiller_ElectricReformEIR: {
4258 :
4259 : //- Retrieve data from the plant loop data structure
4260 0 : CurMassFlowRate = state.dataLoopNodes->Node(this_comp.NodeNumIn).MassFlowRate;
4261 0 : ToutLowLimit = this_comp.MinOutletTemp;
4262 0 : Tinlet = state.dataLoopNodes->Node(this_comp.NodeNumIn).Temp;
4263 0 : CurSpecHeat = GetSpecificHeatGlycol(state, this_loop.FluidName, Tinlet, this_loop.FluidIndex, RoutineName);
4264 0 : QTemporary = CurMassFlowRate * CurSpecHeat * (Tinlet - ToutLowLimit);
4265 :
4266 : //- Don't correct if Q is zero, as this could indicate a component which this hasn't been implemented
4267 0 : if (QTemporary > 0.0) {
4268 0 : if (std::abs(this_comp.MyLoad) > this_comp.MaxLoad) {
4269 0 : this_comp.MyLoad = sign(this_comp.MaxLoad, this_comp.MyLoad);
4270 : }
4271 0 : if (std::abs(this_comp.MyLoad) > QTemporary) {
4272 0 : this_comp.MyLoad = sign(QTemporary, this_comp.MyLoad);
4273 : }
4274 : }
4275 0 : break;
4276 : }
4277 0 : default:
4278 0 : break; // Nothing Changes for now, could add in case statements for boilers, which would use upper limit temp check
4279 : }
4280 0 : return;
4281 : } // EMSValue <=> 0
4282 : } // EMSFlag
4283 : }
4284 :
4285 18941742 : void AdjustChangeInLoadByEMSControls(EnergyPlusData &state,
4286 : PlantLocation const &plantLoc,
4287 : Real64 &ChangeInLoad // positive magnitude of load change
4288 : )
4289 : {
4290 :
4291 : // SUBROUTINE INFORMATION:
4292 : // AUTHOR B. Griffith
4293 : // DATE WRITTEN April 2012
4294 : // MODIFIED na
4295 : // RE-ENGINEERED na
4296 :
4297 : // PURPOSE OF THIS SUBROUTINE:
4298 : // modify load dispatch if EMS controls are in place for a specific component
4299 :
4300 : // METHODOLOGY EMPLOYED:
4301 : // Check if Loop Side is shutdown
4302 : // then check if branch is shutdown
4303 : // then check if component is overridden and use the value if it is.
4304 : // take ABS() of EMS value to ensure sign is correct.
4305 :
4306 : // REFERENCES:
4307 : // na
4308 :
4309 : // USE STATEMENTS:
4310 : // na
4311 :
4312 : // Locals
4313 : // SUBROUTINE ARGUMENT DEFINITIONS:
4314 :
4315 : // SUBROUTINE PARAMETER DEFINITIONS:
4316 : // na
4317 :
4318 : // INTERFACE BLOCK SPECIFICATIONS:
4319 : // na
4320 :
4321 : // DERIVED TYPE DEFINITIONS:
4322 : // na
4323 :
4324 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4325 :
4326 : // set up some nice references to avoid lookups
4327 18941742 : auto &this_loopside = state.dataPlnt->PlantLoop(plantLoc.loopNum).LoopSide(plantLoc.loopSideNum);
4328 18941742 : auto &this_branch = this_loopside.Branch(plantLoc.branchNum);
4329 18941742 : auto const &this_comp = this_branch.Comp(plantLoc.compNum);
4330 :
4331 18941742 : if ((this_loopside.EMSCtrl) && (this_loopside.EMSValue <= 0.0)) {
4332 0 : ChangeInLoad = 0.0;
4333 0 : return;
4334 : }
4335 :
4336 18941742 : if ((this_branch.EMSCtrlOverrideOn) && (this_branch.EMSCtrlOverrideValue <= 0.0)) {
4337 0 : ChangeInLoad = 0.0;
4338 0 : return;
4339 : }
4340 :
4341 18941742 : if (this_comp.EMSLoadOverrideOn) {
4342 52228 : if (this_comp.EMSLoadOverrideValue == 0.0) {
4343 672 : ChangeInLoad = 0.0;
4344 : }
4345 : }
4346 : }
4347 :
4348 : //*END PLANT EMS CONTROL ROUTINES!
4349 : //******************************************************************************
4350 :
4351 : } // namespace EnergyPlus::PlantCondLoopOperation
|