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 : #ifndef HVACControllers_hh_INCLUDED
49 : #define HVACControllers_hh_INCLUDED
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array1D.hh>
53 : #include <ObjexxFCL/Optional.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/Data/BaseData.hh>
57 : #include <EnergyPlus/DataAirSystems.hh>
58 : #include <EnergyPlus/DataGlobals.hh>
59 : #include <EnergyPlus/DataHVACControllers.hh>
60 : #include <EnergyPlus/DataRootFinder.hh>
61 : #include <EnergyPlus/EnergyPlus.hh>
62 : #include <EnergyPlus/SetPointManager.hh>
63 :
64 : namespace EnergyPlus {
65 :
66 : // Forward declarations
67 : struct EnergyPlusData;
68 :
69 : namespace HVACControllers {
70 :
71 : // Using/Aliasing
72 : using DataAirSystems::DefinePrimaryAirSystem;
73 : using DataHVACControllers::ControllerAction;
74 : using DataHVACControllers::ControllerMode;
75 : using DataHVACControllers::ControllerSimple_Type;
76 : using DataHVACControllers::iFirstMode;
77 : using DataHVACControllers::iLastMode;
78 : using DataRootFinder::RootFinderDataType;
79 :
80 : // Parameters for controls used here
81 : enum class CtrlVarType
82 : {
83 : Invalid = -1,
84 : NoControlVariable,
85 : Temperature,
86 : HumidityRatio,
87 : TemperatureAndHumidityRatio,
88 : Flow,
89 : Num
90 : };
91 :
92 : struct SolutionTrackerType
93 : {
94 : bool DefinedFlag = true; // Flag set to TRUE when tracker is up-to-date. FALSE otherwise.
95 : Real64 ActuatedValue = 0.0; // Actuated value
96 : ControllerMode Mode = ControllerMode::None; // Operational model of controller
97 : };
98 :
99 : struct ControllerPropsType
100 : {
101 : // Members
102 : std::string ControllerName; // Name of the Controller
103 : std::string ControllerType; // Type of Controller
104 : int ControllerType_Num;
105 : CtrlVarType ControlVar; // The type of control variable being sensed
106 : CtrlVarType ActuatorVar; // The variable that the controller will act on ie. flow
107 : ControllerAction Action; // Controller Action - Reverse or Normal
108 : // Controller must be initialized to set MinActuated and MaxActuated
109 : bool InitFirstPass;
110 : // --------------------
111 : // Internal data used for optimal restart across successive calls to SimAirLoop()
112 : // --------------------
113 : int NumCalcCalls; // Number of Calc() calls since last call to Reset()
114 : ControllerMode Mode; // Operational model of controller at current iteration
115 : // Flag indicating whether the current controller simulation was performed from a cold start
116 : // or following a speculative warm restart. Set in the ResetController() routine.
117 : // Used in the CheckController() routine.
118 : bool DoWarmRestartFlag;
119 : // Flag used to decide whether or not it is allowed to reuse the intermediate solution from
120 : // solving the previous controller on the air loop (COLD_START mode only) as the initial guess for
121 : // the current controller.
122 : bool ReuseIntermediateSolutionFlag;
123 : // Flag used to decide whether or not it is possible to reuse the solution from
124 : // the last call to SimAirLoop() as a possible candidate.
125 : bool ReusePreviousSolutionFlag;
126 : // Array of solution trackers. Saved at last call to SimAirLoop() in ManageControllers(iControllerOpEnd)
127 : // The first tracker is used to track the solution when FirstHVACIteration is TRUE.
128 : // The second tracker is used to track the solution at FirstHVACIteration is FALSE.
129 : Array1D<SolutionTrackerType> SolutionTrackers;
130 : // --------------------
131 : // Operational limits at min/max avail values for actuated variable and the corresponding sensed values
132 : // --------------------
133 : Real64 MaxAvailActuated; // kg/s, The maximum actuated variable currently available.
134 : // Reset by simulation at each HVAC iteration
135 : Real64 MaxAvailSensed; // Sensed value at maximum available actuated variable
136 : Real64 MinAvailActuated; // kg/s, The minimum actuated variable currently available.
137 : // Reset by simulation at each HVAC iteration
138 : Real64 MinAvailSensed; // Sensed value at maximum available actuated variable
139 : // --------------------
140 : // User input min/max values for actuated variable
141 : // --------------------
142 : Real64 MaxVolFlowActuated; // m3/s, From User input the Max amount for the actuated variable
143 : Real64 MinVolFlowActuated; // m3/s, From User input the Min amount for the actuated variable
144 : Real64 MaxActuated; // kg/s, From User input the Max amount for the actuated variable
145 : Real64 MinActuated; // kg/s, From User input the Min amount for the actuated variable
146 : // --------------------
147 : // Actuated variable
148 : // --------------------
149 : int ActuatedNode; // The node that is acted upon by the controller
150 : Real64 ActuatedValue; // Value of actuated variable before change by the controller
151 : Real64 NextActuatedValue; // The new control actuated value
152 : PlantLocation ActuatedNodePlantLoc; // Location for actuated node
153 : DataPlant::PlantEquipmentType WaterCoilType = DataPlant::PlantEquipmentType::Invalid;
154 : // --------------------
155 : // Sensed variable
156 : // --------------------
157 : int SensedNode; // The sensed node number from the grid
158 : bool IsSetPointDefinedFlag; // If TRUE indicates that the setpoint has been defined and can
159 : // be used to compute DeltaSensed
160 : Real64 SetPointValue; // Desired setpoint; set in the SetPoint Manager or computed in Init() routine
161 : Real64 SensedValue; // The sensed control variable of any type
162 : Real64 DeltaSensed; // Difference of sensed to setpoint value for calculating proportional gain
163 : Real64 Offset; // This is the tolerance or droop from the error
164 : HVAC::CtrlVarType HumRatCntrlType; // iCtrlVarType_HumRat=4,iCtrlVarType_MaxHumRat=5,iCtrlVarType_MinHumRat=6
165 : // --------------------
166 : // Other controller inputs, not yet used
167 : // --------------------
168 : std::string LimitType; // Limit type as in HIGH or LOW
169 : Real64 Range; // The range or hysteresis of the control limit
170 : Real64 Limit; // The Limit value for a Limit Controller
171 : // --------------------
172 : // Trace mechanism
173 : // --------------------
174 : SharedFileHandle TraceFile;
175 : bool FirstTraceFlag; // To detect first individual write operation to individual controller trace file
176 : int BadActionErrCount; // Counts number of incorrect action errors
177 : int BadActionErrIndex; // index to recurring error structure for bad action error
178 : // Fault model for water coil supply air temperature sensor offset
179 : bool FaultyCoilSATFlag; // True if the coil has SAT sensor fault
180 : int FaultyCoilSATIndex; // Index of the fault object corresponding to the coil
181 : Real64 FaultyCoilSATOffset; // Coil SAT sensor offset
182 : bool BypassControllerCalc; // set true for OA sys water coils
183 : int AirLoopControllerIndex; // index to controller on specific air loop
184 :
185 : bool HumRatCtrlOverride; // true if TemperatureAndHumidityRatio control switches to humidity ratio control
186 :
187 : // Default Constructor
188 296 : ControllerPropsType()
189 592 : : ControllerType_Num(ControllerSimple_Type), ControlVar(CtrlVarType::NoControlVariable), ActuatorVar(CtrlVarType::NoControlVariable),
190 296 : Action(ControllerAction::NoAction), InitFirstPass(true), NumCalcCalls(0), Mode(ControllerMode::None), DoWarmRestartFlag(false),
191 296 : ReuseIntermediateSolutionFlag(false), ReusePreviousSolutionFlag(false), SolutionTrackers(2), MaxAvailActuated(0.0), MaxAvailSensed(0.0),
192 296 : MinAvailActuated(0.0), MinAvailSensed(0.0), MaxVolFlowActuated(0.0), MinVolFlowActuated(0.0), MaxActuated(0.0), MinActuated(0.0),
193 296 : ActuatedNode(0), ActuatedValue(0.0), NextActuatedValue(0.0), ActuatedNodePlantLoc{}, SensedNode(0), IsSetPointDefinedFlag(false),
194 592 : SetPointValue(0.0), SensedValue(0.0), DeltaSensed(0.0), Offset(0.0), HumRatCntrlType(HVAC::CtrlVarType::Invalid), Range(0.0),
195 592 : Limit(0.0), FirstTraceFlag(true), BadActionErrCount(0), BadActionErrIndex(0), FaultyCoilSATFlag(false), FaultyCoilSATIndex(0),
196 592 : FaultyCoilSATOffset(0.0), BypassControllerCalc(false), AirLoopControllerIndex(0), HumRatCtrlOverride(false)
197 : {
198 296 : }
199 : };
200 :
201 : struct ControllerStatsType
202 : {
203 : // Members
204 : Array1D_int NumCalls; // Number of times this controller operated in each mode
205 : Array1D_int TotIterations; // Total number of iterations required to solve this controller
206 : Array1D_int MaxIterations; // Maximum number of iterations required to solve this controller
207 :
208 : // Default Constructor
209 0 : ControllerStatsType()
210 0 : : NumCalls({iFirstMode, iLastMode}, 0), TotIterations({iFirstMode, iLastMode}, 0), MaxIterations({iFirstMode, iLastMode}, 0)
211 : {
212 0 : }
213 : };
214 :
215 : struct AirLoopStatsType
216 : {
217 : // Shared_ptr because we need to put this into an Array1D which is not friendly with move-only types
218 : SharedFileHandle TraceFile;
219 : // Used only if > 0. Same size as NumPrimaryAirSys
220 : bool FirstTraceFlag = true; // To detect first trace to air loop trace file
221 : int NumCalls = 0; // Number of times air loop is simulated (number of calls to SimAirLoop)
222 : int NumFailedWarmRestarts = 0; // Number of times speculative warm restart was attempted and failed
223 : int NumSuccessfulWarmRestarts = 0; // Number of times speculative warm restart was attempted and succeeded
224 : int TotSimAirLoopComponents = 0; // Total number of times the SimAirLoopComponents() routine has been invoked
225 : int MaxSimAirLoopComponents = 0; // Maximum number of times the SimAirLoopComponents() routine has been invoked
226 : int TotIterations = 0; // Total number of iterations required to solve the controllers on this air loop
227 : int MaxIterations = 0; // Maximum number of iterations required to solve the controllers on this air loop
228 : Array1D<ControllerStatsType> ControllerStats; // Array of statistics for each controller on this air loop
229 : };
230 :
231 : void ManageControllers(EnergyPlusData &state,
232 : std::string const &ControllerName,
233 : int &ControllerIndex,
234 : bool FirstHVACIteration,
235 : int AirLoopNum, // unused1208
236 : DataHVACControllers::ControllerOperation Operation,
237 : bool &IsConvergedFlag,
238 : bool &IsUpToDateFlag,
239 : bool const BypassOAController,
240 : ObjexxFCL::Optional_bool AllowWarmRestartFlag = _);
241 :
242 : void GetControllerInput(EnergyPlusData &state);
243 :
244 : void ResetController(EnergyPlusData &state, int ControlNum, bool DoWarmRestartFlag, bool &IsConvergedFlag);
245 :
246 : void InitController(EnergyPlusData &state, int ControlNum, bool &IsConvergedFlag);
247 :
248 : void SizeController(EnergyPlusData &state, int ControlNum);
249 :
250 : void CalcSimpleController(EnergyPlusData &state,
251 : int ControlNum,
252 : bool FirstHVACIteration,
253 : bool &IsConvergedFlag,
254 : bool &IsUpToDateFlag,
255 : std::string const &ControllerName // used when errors occur
256 : );
257 :
258 : void FindRootSimpleController(EnergyPlusData &state,
259 : int ControlNum,
260 : bool FirstHVACIteration,
261 : bool &IsConvergedFlag,
262 : bool &IsUpToDateFlag,
263 : std::string const &ControllerName // used when errors occur
264 : );
265 :
266 : void CheckSimpleController(EnergyPlusData &state, int ControlNum, bool &IsConvergedFlag);
267 :
268 : bool CheckMinActiveController(EnergyPlusData &state, int ControlNum);
269 :
270 : bool CheckMaxActiveController(EnergyPlusData &state, int ControlNum);
271 :
272 : void CheckTempAndHumRatCtrl(EnergyPlusData &state, int ControlNum, bool &IsConvergedFlag);
273 :
274 : void SaveSimpleController(EnergyPlusData &state, int ControlNum, bool FirstHVACIteration, bool IsConvergedFlag);
275 :
276 : void UpdateController(EnergyPlusData &state, int ControlNum);
277 :
278 : void ExitCalcController(
279 : EnergyPlusData &state, int ControlNum, Real64 NextActuatedValue, ControllerMode Mode, bool &IsConvergedFlag, bool &IsUpToDateFlag);
280 :
281 : void TrackAirLoopControllers(EnergyPlusData &state,
282 : int AirLoopNum,
283 : DataHVACControllers::ControllerWarmRestart WarmRestartStatus,
284 : int AirLoopIterMax,
285 : int AirLoopIterTot,
286 : int AirLoopNumCalls);
287 :
288 : void TrackAirLoopController(EnergyPlusData &state,
289 : int AirLoopNum, // Air loop index
290 : int AirLoopControlNum // Controller index on this air loop
291 : );
292 :
293 : void DumpAirLoopStatistics(EnergyPlusData &state);
294 :
295 : void WriteAirLoopStatistics(EnergyPlusData &state,
296 : InputOutputFile &statisticsFile,
297 : DefinePrimaryAirSystem const &ThisPrimaryAirSystem,
298 : AirLoopStatsType const &ThisAirLoopStats);
299 :
300 : void SetupAirLoopControllersTracer(EnergyPlusData &state, int AirLoopNum);
301 :
302 : void TraceAirLoopControllers(
303 : EnergyPlusData &state, bool FirstHVACIteration, int AirLoopNum, int AirLoopPass, bool AirLoopConverged, int AirLoopNumCalls);
304 :
305 : void TraceIterationStamp(
306 : EnergyPlusData &state, InputOutputFile &TraceFile, bool FirstHVACIteration, int AirLoopPass, bool AirLoopConverged, int AirLoopNumCalls);
307 :
308 : void TraceAirLoopController(EnergyPlusData &state, InputOutputFile &TraceFile, int ControlNum);
309 :
310 : void SetupIndividualControllerTracer(EnergyPlusData &state, int ControlNum);
311 :
312 : void TraceIndividualController(EnergyPlusData &state,
313 : int ControlNum,
314 : bool FirstHVACIteration,
315 : int AirLoopPass,
316 : DataHVACControllers::ControllerOperation Operation, // Operation to execute
317 : bool IsConvergedFlag);
318 :
319 : Real64 GetCurrentHVACTime(const EnergyPlusData &state);
320 :
321 : Real64 GetPreviousHVACTime(const EnergyPlusData &state);
322 :
323 : std::string CreateHVACTimeString(const EnergyPlusData &state);
324 :
325 : std::string CreateHVACStepFullString(const EnergyPlusData &state);
326 :
327 : std::string MakeHVACTimeIntervalString(const EnergyPlusData &state);
328 :
329 : void CheckControllerListOrder(EnergyPlusData &state);
330 :
331 : void CheckCoilWaterInletNode(EnergyPlusData &state,
332 : int WaterInletNodeNum, // input actuator node number
333 : bool &NodeNotFound // true if matching actuator node not found, false if found
334 : );
335 :
336 : void GetControllerNameAndIndex(EnergyPlusData &state,
337 : int WaterInletNodeNum, // input actuator node number
338 : std::string &ControllerName, // controller name used by water coil
339 : int &ControllerIndex, // controller index used by water coil
340 : bool &ErrorsFound // true if matching actuator node not found
341 : );
342 :
343 : void GetControllerActuatorNodeNum(EnergyPlusData &state,
344 : std::string const &ControllerName, // name of coil controller
345 : int &WaterInletNodeNum, // input actuator node number
346 : bool &NodeNotFound // true if matching actuator node not found, false if found
347 : );
348 :
349 : int GetControllerIndex(EnergyPlusData &state,
350 : std::string const &ControllerName // name of coil controller
351 : );
352 :
353 : } // namespace HVACControllers
354 :
355 : struct HVACControllersData : BaseGlobalStruct
356 : {
357 : int NumControllers = 0; // The number of controllers found in the Input
358 : int NumAirLoopStats = 0; // Same size as NumPrimaryAirSys if controllers
359 : Array1D_bool CheckEquipName;
360 : bool GetControllerInputFlag = true;
361 : bool InitControllerOneTimeFlag = true;
362 : bool InitControllerSetPointCheckFlag = true;
363 : Array1D<HVACControllers::ControllerPropsType> ControllerProps;
364 : Array1D<HVACControllers::RootFinderDataType> RootFinders;
365 : Array1D<HVACControllers::AirLoopStatsType> AirLoopStats; // Statistics array to analyze computational profile for
366 : Array1D_bool MyEnvrnFlag;
367 : Array1D_bool MySizeFlag;
368 : Array1D_bool MyPlantIndexsFlag;
369 :
370 796 : void init_state([[maybe_unused]] EnergyPlusData &state) override
371 : {
372 796 : }
373 :
374 0 : void clear_state() override
375 : {
376 0 : new (this) HVACControllersData();
377 0 : }
378 : };
379 :
380 : } // namespace EnergyPlus
381 :
382 : #endif
|