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