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 UserDefinedComponents_hh_INCLUDED
49 : #define UserDefinedComponents_hh_INCLUDED
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array1D.hh>
53 :
54 : // EnergyPlus Headers
55 : #include <EnergyPlus/Data/BaseData.hh>
56 : #include <EnergyPlus/DataGlobals.hh>
57 : #include <EnergyPlus/EnergyPlus.hh>
58 : #include <EnergyPlus/Plant/DataPlant.hh>
59 : #include <EnergyPlus/Plant/Enums.hh>
60 : #include <EnergyPlus/PlantComponent.hh>
61 :
62 : namespace EnergyPlus {
63 :
64 : // Forward declarations
65 : struct EnergyPlusData;
66 :
67 : namespace UserDefinedComponents {
68 :
69 : struct PlantConnectionStruct
70 : {
71 : // Members
72 : int ErlInitProgramMngr; // points to an EMS:ProgramManager to run for setup and sizing
73 : int ErlSimProgramMngr; // points to an EMS:ProgramManager to run only when this connection is called
74 : int simPluginLocation; // If Python Plugins are used to simulate this, this defines the location in the plugin structure
75 : int initPluginLocation; // If Python Plugins are used to init this, this defines the location in the plugin structure
76 : int simCallbackIndex = -1; // If API Callbacks are used to simulate this, this defines the index in the user-defined callbacks vector
77 : int initCallbackIndex = -1; // If API Callbacks are used to init this, this defines the index in the user-defined callbacks vector
78 : PlantLocation plantLoc;
79 : int InletNodeNum; // plant loop inlet node index
80 : int OutletNodeNum; // plant loop outlet node index
81 : DataPlant::LoopFlowStatus FlowPriority; // how component affects overall loop flow determination
82 : DataPlant::HowMet HowLoadServed; // nature of component wrt to plant loop's loads
83 : Real64 LowOutTempLimit; // low limit for outlet temp if MEETSLOADWITHNOMINALCAPACITYLOWOUTLIMIT
84 : Real64 HiOutTempLimit; // hi limit for outlet temp if MEETSLOADWITHNOMINALCAPACITYHIOUTLIMIT
85 : Real64 MassFlowRateRequest; // request filled by actuator, might not be satisfied if plant constrained [kg/s]
86 : Real64 MassFlowRateMin; // filled by actuator, reports minimum (hardware) flow rate for component [kg/s]
87 : Real64 MassFlowRateMax; // filled by actuator, reports maximum (hardware) flow rate for component [kg/s]
88 : Real64 DesignVolumeFlowRate; // filled by actuator,
89 : Real64 MyLoad; // fills internal variable for user's model to know current load request of supply equip [W]
90 : Real64 MinLoad; // filled by actuator, reports back size for load dispatch routines [W]
91 : Real64 MaxLoad; // filled by actuator, reports back size for load dispatch [W]
92 : Real64 OptLoad; // filled by actuator, reports back size for load dispatch [W]
93 : Real64 InletRho; // fills internal variable, current density for fluid type and inlet temperature [kg/m3]
94 : Real64 InletCp; // fills internal Variable, current specific heat for fluid type and inlet temperature [J/kg-C]
95 : Real64 InletTemp; // fills internal variable, current inlet fluid temperature [C]
96 : Real64 InletMassFlowRate; // fills internal variable, current inlet mass flow rate [kg/s]
97 : Real64 OutletTemp; // filled by actuator, component outlet temperature [C]
98 :
99 : // Default Constructor
100 20 : PlantConnectionStruct()
101 40 : : ErlInitProgramMngr(0), ErlSimProgramMngr(0), simPluginLocation(-1), initPluginLocation(-1), plantLoc{}, InletNodeNum(0),
102 20 : OutletNodeNum(0), FlowPriority(DataPlant::LoopFlowStatus::Invalid), HowLoadServed(DataPlant::HowMet::Invalid), LowOutTempLimit(0.0),
103 20 : HiOutTempLimit(0.0), MassFlowRateRequest(0.0), MassFlowRateMin(0.0), MassFlowRateMax(0.0), DesignVolumeFlowRate(0.0), MyLoad(0.0),
104 20 : MinLoad(0.0), MaxLoad(0.0), OptLoad(0.0), InletRho(0.0), InletCp(0.0), InletTemp(0.0), InletMassFlowRate(0.0), OutletTemp(0.0)
105 : {
106 20 : }
107 : };
108 :
109 : struct AirConnectionStruct
110 : {
111 : // Members
112 : int InletNodeNum; // air inlet node index
113 : int OutletNodeNum; // air outlet node index
114 : Real64 InletRho; // fills internal variable, current inlet air density [kg/m3]
115 : Real64 InletCp; // fills internal variable, current inlet air specific heat [J/kg-c]
116 : Real64 InletTemp; // fills internal variable, current inlet air temperature [C]
117 : Real64 InletHumRat; // fills internal variable, current inlet air humidity ratio [kg/kg]
118 : Real64 InletMassFlowRate; // fills internal variable, current inlet air mass flow rate [kg/s]
119 : Real64 OutletTemp; // filled by actuator, component outlet temperature [C]
120 : Real64 OutletHumRat; // filled by actuator, component outlet humidity ratio [kg/kg]
121 : Real64 OutletMassFlowRate; // filled by actuator, component outlet mass flow rate [kg/s]
122 :
123 : // Default Constructor
124 50 : AirConnectionStruct()
125 50 : : InletNodeNum(0), OutletNodeNum(0), InletRho(0.0), InletCp(0.0), InletTemp(0.0), InletHumRat(0.0), InletMassFlowRate(0.0),
126 50 : OutletTemp(0.0), OutletHumRat(0.0), OutletMassFlowRate(0.0)
127 : {
128 50 : }
129 : };
130 :
131 : struct WaterUseTankConnectionStruct // data for interacting with water use storage system
132 : {
133 : // Members
134 : bool SuppliedByWaterSystem;
135 : int SupplyTankID; // index "pointer" to WaterStorage structure
136 : int SupplyTankDemandARRID; // index "pointer" to demand array inside WaterStorage structure
137 : Real64 SupplyVdotRequest;
138 : bool CollectsToWaterSystem;
139 : int CollectionTankID; // index "pointer" to Storage TAnk array WaterStorage
140 : int CollectionTankSupplyARRID; // index pointe to supply Vdot array in WaterStorage
141 : Real64 CollectedVdot;
142 :
143 : // Default Constructor
144 32 : WaterUseTankConnectionStruct()
145 32 : : SuppliedByWaterSystem(false), SupplyTankID(0), SupplyTankDemandARRID(0), SupplyVdotRequest(0.0), CollectsToWaterSystem(false),
146 32 : CollectionTankID(0), CollectionTankSupplyARRID(0), CollectedVdot(0.0)
147 : {
148 32 : }
149 : };
150 :
151 : struct ZoneInternalGainsStruct
152 : {
153 : // Members
154 : bool DeviceHasInternalGains;
155 : int ZoneNum;
156 : Real64 ConvectionGainRate;
157 : Real64 ReturnAirConvectionGainRate;
158 : Real64 ThermalRadiationGainRate;
159 : Real64 LatentGainRate;
160 : Real64 ReturnAirLatentGainRate;
161 : Real64 CarbonDioxideGainRate;
162 : Real64 GenericContamGainRate;
163 :
164 : // Default Constructor
165 32 : ZoneInternalGainsStruct()
166 32 : : DeviceHasInternalGains(false), ZoneNum(0), ConvectionGainRate(0.0), ReturnAirConvectionGainRate(0.0), ThermalRadiationGainRate(0.0),
167 32 : LatentGainRate(0.0), ReturnAirLatentGainRate(0.0), CarbonDioxideGainRate(0.0), GenericContamGainRate(0.0)
168 : {
169 32 : }
170 : };
171 :
172 : struct UserPlantComponentStruct : PlantComponent
173 : {
174 : // Members
175 : std::string Name; // user identifier
176 : int ErlSimProgramMngr; // EMS:ProgramManager to always run when this model is called
177 : int simPluginLocation; // If Python Plugins are used to simulate this, this defines the location in the plugin structure
178 : int simCallbackIndex = -1;
179 : int NumPlantConnections; // count of how many plant loop connections there are
180 : Array1D<PlantConnectionStruct> Loop; // collect data for each plant loop connection
181 : AirConnectionStruct Air;
182 : WaterUseTankConnectionStruct Water;
183 : ZoneInternalGainsStruct Zone;
184 : bool myOneTimeFlag;
185 :
186 : // Default Constructor
187 4 : UserPlantComponentStruct() : ErlSimProgramMngr(0), simPluginLocation(-1), NumPlantConnections(0), myOneTimeFlag(true)
188 : {
189 4 : }
190 :
191 : static PlantComponent *factory(EnergyPlusData &state, std::string const &objectName);
192 :
193 : void onInitLoopEquip([[maybe_unused]] EnergyPlusData &state, const PlantLocation &calledFromLocation) override;
194 :
195 : void getDesignCapacities(
196 : EnergyPlusData &state, const PlantLocation &calledFromLocation, Real64 &MaxLoad, Real64 &MinLoad, Real64 &OptLoad) override;
197 :
198 : void
199 : simulate(EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, bool RunFlag) override;
200 :
201 : void initialize(EnergyPlusData &state, int LoopNum, Real64 MyLoad);
202 :
203 : void report(EnergyPlusData &state, int LoopNum);
204 :
205 : void oneTimeInit(EnergyPlusData &state) override;
206 : };
207 :
208 : struct UserCoilComponentStruct
209 : {
210 : // Members
211 : std::string Name; // user identifier
212 : int ErlSimProgramMngr; // EMS:ProgramManager to always run when this model is called
213 : int ErlInitProgramMngr; // EMS:ProgramManager to run when this model is initialized and setup
214 : int initPluginLocation; // If Python Plugins are used to init this, this defines the location in the plugin structure
215 : int simPluginLocation; // If Python Plugins are used to simulate this, this defines the location in the plugin structure
216 : int initCallbackIndex = -1; // If API callbacks are used to init this, this defines the location in the vector
217 : int simCallbackIndex = -1; // If API callbacks are used to simulate this, this defines the location in the vector
218 : int NumAirConnections; // count of how many air connections there are
219 : bool PlantIsConnected;
220 : Array1D<AirConnectionStruct> Air;
221 : PlantConnectionStruct Loop;
222 : WaterUseTankConnectionStruct Water;
223 : ZoneInternalGainsStruct Zone;
224 : bool myOneTimeFlag;
225 :
226 : // Default Constructor
227 8 : UserCoilComponentStruct()
228 16 : : ErlSimProgramMngr(0), ErlInitProgramMngr(0), initPluginLocation(-1), simPluginLocation(-1), NumAirConnections(0),
229 8 : PlantIsConnected(false), myOneTimeFlag(true)
230 : {
231 8 : }
232 :
233 : void initialize(EnergyPlusData &state);
234 :
235 : void report(EnergyPlusData &state);
236 : };
237 :
238 : struct UserZoneHVACForcedAirComponentStruct
239 : {
240 : // Members
241 : std::string Name; // user identifier
242 : int ErlSimProgramMngr; // EMS:ProgramManager to always run when this model is called
243 : int ErlInitProgramMngr; // EMS:ProgramManager to run when this model is initialized and setup
244 : int initPluginLocation; // If Python Plugins are used to init this, this defines the location in the plugin structure
245 : int simPluginLocation; // If Python Plugins are used to simulate this, this defines the location in the plugin structure
246 : int initCallbackIndex = -1; // If API callbacks are used to init this, this defines the location in the vector
247 : int simCallbackIndex = -1; // If API callbacks are used to simulate this, this defines the location in the vector
248 : AirConnectionStruct ZoneAir;
249 : AirConnectionStruct SourceAir;
250 : int NumPlantConnections; // count of how many plant loop (demand) connections there are
251 : Array1D<PlantConnectionStruct> Loop; // collect data for each plant loop connection
252 : WaterUseTankConnectionStruct Water;
253 : ZoneInternalGainsStruct Zone; // for skin losses
254 : Real64 RemainingOutputToHeatingSP; // sensible load remaining for device, to heating setpoint [W]
255 : Real64 RemainingOutputToCoolingSP; // sensible load remaining for device, negative means cooling [W]
256 : Real64 RemainingOutputReqToHumidSP; // latent load remaining for device, to humidification setpoint [kg/s]
257 : Real64 RemainingOutputReqToDehumidSP; // latent load remaining for device, Negative means dehumidify [kg/s]
258 : bool myOneTimeFlag;
259 :
260 : // Default Constructor
261 8 : UserZoneHVACForcedAirComponentStruct()
262 24 : : ErlSimProgramMngr(0), ErlInitProgramMngr(0), initPluginLocation(-1), simPluginLocation(-1), NumPlantConnections(0),
263 8 : RemainingOutputToHeatingSP(0.0), RemainingOutputToCoolingSP(0.0), RemainingOutputReqToHumidSP(0.0), RemainingOutputReqToDehumidSP(0.0),
264 8 : myOneTimeFlag(true)
265 : {
266 8 : }
267 :
268 : void initialize(EnergyPlusData &state, int ZoneNum);
269 :
270 : void report(EnergyPlusData &state);
271 : };
272 :
273 : struct UserAirTerminalComponentStruct
274 : {
275 : // Members
276 : std::string Name; // user identifier
277 : int ActualCtrlZoneNum;
278 : int ADUNum; // index of corresponding air distribution unit
279 : int ErlSimProgramMngr; // EMS:ProgramManager to always run when this model is called
280 : int ErlInitProgramMngr; // EMS:ProgramManager to run when this model is initialized and setup
281 : int initPluginLocation; // If Python Plugins are used to init this, this defines the location in the plugin structure
282 : int simPluginLocation; // If Python Plugins are used to simulate this, this defines the location in the plugin structure
283 : int initCallbackIndex = -1; // If API callbacks are used to init this, this defines the location in the vector
284 : int simCallbackIndex = -1; // If API callbacks are used to simulate this, this defines the location in the vector
285 : AirConnectionStruct AirLoop;
286 : AirConnectionStruct SourceAir;
287 : int NumPlantConnections; // count of how many plant loop (demand) connections there are
288 : Array1D<PlantConnectionStruct> Loop; // collect data for each plant loop connection
289 : WaterUseTankConnectionStruct Water;
290 : ZoneInternalGainsStruct Zone; // for skin losses
291 : Real64 RemainingOutputToHeatingSP; // sensible load remaining for device, to heating setpoint [W]
292 : Real64 RemainingOutputToCoolingSP; // sensible load remaining for device, negative means cooling [W]
293 : Real64 RemainingOutputReqToHumidSP; // latent load remaining for device, to humidification setpoint [kg/s]
294 : Real64 RemainingOutputReqToDehumidSP; // latent load remaining for device, Negative means dehumidify [kg/s]
295 : bool myOneTimeFlag;
296 :
297 : // Default Constructor
298 12 : UserAirTerminalComponentStruct()
299 24 : : ActualCtrlZoneNum(0), ADUNum(0), ErlSimProgramMngr(0), ErlInitProgramMngr(0), initPluginLocation(-1), simPluginLocation(-1),
300 24 : NumPlantConnections(0), RemainingOutputToHeatingSP(0.0), RemainingOutputToCoolingSP(0.0), RemainingOutputReqToHumidSP(0.0),
301 12 : RemainingOutputReqToDehumidSP(0.0), myOneTimeFlag(true)
302 : {
303 12 : }
304 :
305 : void initialize(EnergyPlusData &state, int ZoneNum);
306 :
307 : void report(EnergyPlusData &state);
308 : };
309 :
310 : void SimCoilUserDefined(EnergyPlusData &state,
311 : std::string_view EquipName, // user name for component
312 : int &CompIndex,
313 : int AirLoopNum,
314 : bool &HeatingActive,
315 : bool &CoolingActive);
316 :
317 : void SimZoneAirUserDefined(EnergyPlusData &state,
318 : std::string_view CompName, // name of the packaged terminal heat pump
319 : int ZoneNum, // number of zone being served
320 : Real64 &SensibleOutputProvided, // sensible capacity delivered to zone
321 : Real64 &LatentOutputProvided, // Latent add/removal (kg/s), dehumid = negative
322 : int &CompIndex // index to zone hvac unit
323 : );
324 :
325 : void SimAirTerminalUserDefined(
326 : EnergyPlusData &state, std::string_view CompName, bool FirstHVACIteration, int ZoneNum, int ZoneNodeNum, int &CompIndex);
327 :
328 : void GetUserDefinedPlantComponents(EnergyPlusData &state);
329 :
330 : void GetUserDefinedComponents(EnergyPlusData &state);
331 :
332 : void GetUserDefinedCoilIndex(
333 : EnergyPlusData &state, std::string const &CoilName, int &CoilIndex, bool &ErrorsFound, std::string const &CurrentModuleObject);
334 :
335 : void GetUserDefinedCoilAirInletNode(
336 : EnergyPlusData &state, std::string const &CoilName, int &CoilAirInletNode, bool &ErrorsFound, std::string const &CurrentModuleObject);
337 :
338 : void GetUserDefinedCoilAirOutletNode(
339 : EnergyPlusData &state, std::string const &CoilName, int &CoilAirOutletNode, bool &ErrorsFound, std::string const &CurrentModuleObject);
340 :
341 : } // namespace UserDefinedComponents
342 :
343 : struct UserDefinedComponentsData : BaseGlobalStruct
344 : {
345 :
346 : int NumUserPlantComps = 0;
347 : int NumUserCoils = 0;
348 : int NumUserZoneAir = 0;
349 : int NumUserAirTerminals = 0;
350 :
351 : bool GetInput = true;
352 : bool GetPlantCompInput = true;
353 :
354 : Array1D_bool CheckUserPlantCompName;
355 : Array1D_bool CheckUserCoilName;
356 : Array1D_bool CheckUserZoneAirName;
357 : Array1D_bool CheckUserAirTerminal;
358 :
359 : // Object Data
360 : EPVector<UserDefinedComponents::UserPlantComponentStruct> UserPlantComp;
361 : EPVector<UserDefinedComponents::UserCoilComponentStruct> UserCoil;
362 : EPVector<UserDefinedComponents::UserZoneHVACForcedAirComponentStruct> UserZoneAirHVAC;
363 : EPVector<UserDefinedComponents::UserAirTerminalComponentStruct> UserAirTerminal;
364 :
365 : bool lDummy_EMSActuatedPlantComp = false;
366 : bool lDummy_GetUserDefComp = false;
367 :
368 796 : void init_state([[maybe_unused]] EnergyPlusData &state) override
369 : {
370 796 : }
371 :
372 0 : void clear_state() override
373 : {
374 0 : this->GetInput = true;
375 0 : this->GetPlantCompInput = true;
376 0 : this->NumUserPlantComps = 0;
377 0 : this->NumUserCoils = 0;
378 0 : this->NumUserZoneAir = 0;
379 0 : this->NumUserAirTerminals = 0;
380 0 : this->CheckUserPlantCompName.deallocate();
381 0 : this->CheckUserCoilName.deallocate();
382 0 : this->CheckUserZoneAirName.deallocate();
383 0 : this->CheckUserAirTerminal.deallocate();
384 0 : this->UserPlantComp.deallocate();
385 0 : this->UserCoil.deallocate();
386 0 : this->UserZoneAirHVAC.deallocate();
387 0 : this->UserAirTerminal.deallocate();
388 0 : this->lDummy_EMSActuatedPlantComp = false;
389 0 : this->lDummy_GetUserDefComp = false;
390 0 : }
391 :
392 : // Default Constructor
393 796 : UserDefinedComponentsData() = default;
394 : };
395 : } // namespace EnergyPlus
396 :
397 : #endif
|