Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : #ifndef ElectricPowerServiceManager_hh_INCLUDED
49 : #define ElectricPowerServiceManager_hh_INCLUDED
50 :
51 : // C++ Headers
52 : #include <memory>
53 : #include <string>
54 : #include <vector>
55 :
56 : // EnergyPlus Headers
57 : #include <EnergyPlus/Data/BaseData.hh>
58 : #include <EnergyPlus/DataGlobalConstants.hh>
59 : #include <EnergyPlus/DataHeatBalance.hh>
60 : #include <EnergyPlus/EMSManager.hh>
61 : #include <EnergyPlus/EnergyPlus.hh>
62 : #include <EnergyPlus/OutputProcessor.hh>
63 : #include <EnergyPlus/PVWatts.hh>
64 : #include <EnergyPlus/Plant/Enums.hh>
65 : #include <EnergyPlus/Plant/PlantLocation.hh>
66 :
67 : // SSC Headers
68 : #include <../third_party/ssc/shared/lib_battery.h>
69 :
70 : namespace EnergyPlus {
71 :
72 : enum class GeneratorType
73 : {
74 : Invalid = -1,
75 : ICEngine,
76 : CombTurbine,
77 : PV,
78 : FuelCell,
79 : MicroCHP,
80 : Microturbine,
81 : WindTurbine,
82 : PVWatts,
83 : Num
84 : };
85 :
86 : constexpr std::array<std::string_view, (int)GeneratorType::Num> generatorTypeNames = {"Generator:InternalCombustionEngine",
87 : "Generator:CombustionTurbine",
88 : "Generator:Photovoltaic",
89 : "Generator:FuelCell",
90 : "Generator:MicroCHP",
91 : "Generator:MicroTurbine",
92 : "Generator:WindTurbine",
93 : "Generator:PVWatts"};
94 :
95 : constexpr std::array<std::string_view, (int)GeneratorType::Num> generatorTypeNamesUC = {"GENERATOR:INTERNALCOMBUSTIONENGINE",
96 : "GENERATOR:COMBUSTIONTURBINE",
97 : "GENERATOR:PHOTOVOLTAIC",
98 : "GENERATOR:FUELCELL",
99 : "GENERATOR:MICROCHP",
100 : "GENERATOR:MICROTURBINE",
101 : "GENERATOR:WINDTURBINE",
102 : "GENERATOR:PVWATTS"};
103 :
104 : enum class ThermalLossDestination
105 : {
106 : Invalid = -1,
107 : ZoneGains, // device thermal losses are added to a zone as internal gains
108 : LostToOutside, // device thermal losses have no destination
109 : Num
110 : };
111 :
112 : void initializeElectricPowerServiceZoneGains(const EnergyPlusData &state);
113 :
114 : class DCtoACInverter
115 : // This class is for modelling a power conversion device that takes DC power in and produces AC power out.
116 : // This class combines three separate input objects that have different methods of determining efficiency.
117 : {
118 :
119 : public: // Methods
120 : enum class InverterModelType
121 : {
122 : Invalid = -1,
123 : CECLookUpTableModel,
124 : CurveFuncOfPower,
125 : SimpleConstantEff,
126 : PVWatts,
127 : Num
128 : };
129 :
130 : // Constructor
131 : DCtoACInverter(EnergyPlusData &state, std::string const &objectName);
132 :
133 : void simulate(EnergyPlusData &state, Real64 const powerIntoInverter);
134 :
135 : void reinitAtBeginEnvironment();
136 :
137 : void reinitZoneGainsAtBeginEnvironment();
138 :
139 : void setPVWattsDCCapacity(EnergyPlusData &state, Real64 const dcCapacity);
140 :
141 : Real64 pvWattsDCCapacity();
142 :
143 : Real64 pvWattsInverterEfficiency();
144 :
145 : Real64 pvWattsDCtoACSizeRatio();
146 :
147 : Real64 getLossRateForOutputPower(EnergyPlusData &state, Real64 const powerOutOfInverter);
148 :
149 : Real64 aCPowerOut() const;
150 :
151 : InverterModelType modelType() const;
152 :
153 : std::string const &name() const;
154 :
155 : private: // Methods
156 : void calcEfficiency(EnergyPlusData &state);
157 :
158 : private: // data
159 : std::string name_; // user identifier
160 : Real64 aCPowerOut_;
161 : Real64 aCEnergyOut_;
162 : Real64 efficiency_;
163 : Real64 dCPowerIn_;
164 : Real64 dCEnergyIn_;
165 : Real64 conversionLossPower_;
166 : Real64 conversionLossEnergy_;
167 : Real64 conversionLossEnergyDecrement_;
168 : Real64 thermLossRate_;
169 : Real64 thermLossEnergy_;
170 : Real64 qdotConvZone_;
171 : Real64 qdotRadZone_;
172 : Real64 ancillACuseRate_;
173 : Real64 ancillACuseEnergy_;
174 : InverterModelType modelType_; // type of inverter model used
175 : Sched::Schedule *availSched_ = nullptr; // number for availability schedule.
176 : ThermalLossDestination heatLossesDestination_;
177 : int zoneNum_; // destination zone for heat losses from inverter.
178 : Real64 zoneRadFract_; // radiative fraction for thermal losses to zone
179 : Real64 nominalVoltage_; // CEC lookup table model
180 : std::vector<Real64> nomVoltEfficiencyARR_; // eff at 10, 20, 30, 50, 75, & 100% CEC lookup table model
181 : Curve::Curve *effCurve_ = nullptr; // curve for eff as func of power
182 : Real64 ratedPower_; // rated, max continuous power output level for inverter
183 : Real64 minPower_;
184 : Real64 maxPower_;
185 : Real64 minEfficiency_;
186 : Real64 maxEfficiency_;
187 : Real64 standbyPower_;
188 : Real64 pvWattsDCtoACSizeRatio_;
189 : Real64 pvWattsInverterEfficiency_;
190 :
191 : }; // DCtoACInverter
192 :
193 : class ACtoDCConverter
194 : // This class is for modelling a power conversion device that takes AC power in and produces DC power out.
195 :
196 : {
197 :
198 : public: // Methods
199 : // Constructor
200 : ACtoDCConverter(EnergyPlusData &state, std::string const &objectName);
201 :
202 : void simulate(EnergyPlusData &state, Real64 const powerOutFromConverter);
203 :
204 : void reinitAtBeginEnvironment();
205 :
206 : void reinitZoneGainsAtBeginEnvironment();
207 :
208 : Real64 aCPowerIn() const;
209 :
210 : Real64 getLossRateForInputPower(EnergyPlusData &state, Real64 const powerIntoConverter); // AC power going into inverter
211 :
212 : std::string const &name() const;
213 :
214 : private: // methods
215 : void calcEfficiency(EnergyPlusData &state);
216 :
217 : private: // data
218 : enum class ConverterModelType
219 : {
220 : Invalid = -1,
221 : CurveFuncOfPower,
222 : SimpleConstantEff,
223 : Num
224 : };
225 :
226 : static constexpr std::array<std::string_view, (int)ConverterModelType::Num> converterModelTypeNames = {"FunctionOfPower", "SimpleFixed"};
227 : static constexpr std::array<std::string_view, (int)ConverterModelType::Num> converterModelTypeNamesUC = {"FUNCTIONOFPOWER", "SIMPLEFIXED"};
228 :
229 : std::string name_; // user identifier
230 : Real64 efficiency_;
231 : Real64 aCPowerIn_;
232 : Real64 aCEnergyIn_;
233 : Real64 dCPowerOut_;
234 : Real64 dCEnergyOut_;
235 : Real64 conversionLossPower_;
236 : Real64 conversionLossEnergy_;
237 : Real64 conversionLossEnergyDecrement_;
238 : Real64 thermLossRate_;
239 : Real64 thermLossEnergy_;
240 : Real64 qdotConvZone_;
241 : Real64 qdotRadZone_;
242 : Real64 ancillACuseRate_;
243 : Real64 ancillACuseEnergy_;
244 : Sched::Schedule *availSched_ = nullptr; // number for availability schedule.
245 : ConverterModelType modelType_; // type of inverter model used
246 : Curve::Curve *effCurve_ = nullptr; // performance curve or table index
247 : ThermalLossDestination heatLossesDestination_;
248 : int zoneNum_; // destination zone for heat losses from inverter.
249 : Real64 zoneRadFract_; // radiative fraction for thermal losses to zone
250 : Real64 standbyPower_;
251 : Real64 maxPower_;
252 : };
253 :
254 : class ElectricStorage
255 : // This class is for modeling a device for storing electric power over time.
256 : // This class combines two separate input objects that have different models.
257 : {
258 :
259 : public: // methods
260 : // Constructor
261 : ElectricStorage(EnergyPlusData &state, std::string const &objectName);
262 :
263 : void timeCheckAndUpdate(EnergyPlusData &state);
264 :
265 : void simulate(EnergyPlusData &state,
266 : Real64 &powerCharge,
267 : Real64 &powerDischarge,
268 : bool &charging,
269 : bool &discharging,
270 : Real64 const controlSOCMaxFracLimit,
271 : Real64 const controlSOCMinFracLimit);
272 :
273 : // void calcAndReportSimpleBucketModel();
274 :
275 : // void calcAndReportKineticBatteryModel();
276 :
277 : void reinitAtBeginEnvironment();
278 :
279 : void reinitZoneGainsAtBeginEnvironment();
280 :
281 : void reinitAtEndWarmup();
282 :
283 : Real64 drawnPower() const;
284 :
285 : Real64 storedPower() const;
286 :
287 : Real64 drawnEnergy() const;
288 :
289 : Real64 storedEnergy() const;
290 :
291 : Real64 stateOfChargeFraction() const;
292 :
293 : Real64 batteryTemperature() const;
294 :
295 : bool determineCurrentForBatteryDischarge(EnergyPlusData &state,
296 : Real64 &curI0,
297 : Real64 &curT0,
298 : Real64 &curVolt,
299 : Real64 const Pw,
300 : Real64 const q0,
301 : Curve::Curve *curve,
302 : Real64 const k,
303 : Real64 const c,
304 : Real64 const qmax,
305 : Real64 const E0c,
306 : Real64 const InternalR);
307 :
308 : std::string const &name() const;
309 :
310 : private: // methods
311 : void simulateSimpleBucketModel( // request charge discharge and
312 : EnergyPlusData &state,
313 : Real64 &powerCharge,
314 : Real64 &powerDischarge,
315 : bool &charging,
316 : bool &discharging,
317 : Real64 const controlSOCMaxFracLimit,
318 : Real64 const controlSOCMinFracLimit);
319 :
320 : void simulateKineticBatteryModel(EnergyPlusData &state,
321 : Real64 &powerCharge,
322 : Real64 &powerDischarge,
323 : bool &charging,
324 : bool &discharging,
325 : Real64 const controlSOCMaxFracLimit,
326 : Real64 const controlSOCMinFracLimit);
327 :
328 : void simulateLiIonNmcBatteryModel(EnergyPlusData &state,
329 : Real64 &powerCharge,
330 : Real64 &powerDischarge,
331 : bool &charging,
332 : bool &discharging,
333 : Real64 const controlSOCMaxFracLimit,
334 : Real64 const controlSOCMinFracLimit);
335 :
336 : void rainflow(int const numbin, // numbin = constant value
337 : Real64 const input, // input = input value from other object (battery model)
338 : std::vector<Real64> &B1, // stores values of points, calculated here - stored for next timestep
339 : std::vector<Real64> &X, // stores values of two data point difference, calculated here - stored for next timestep
340 : int &count, // calculated here - stored for next timestep in main loop
341 : std::vector<Real64> &Nmb, // calculated here - stored for next timestep in main loop
342 : std::vector<Real64> &OneNmb // calculated here - stored for next timestep in main loop
343 : // int const dim // end dimension of array
344 : );
345 :
346 : void shift(std::vector<Real64> &A, int const m, int const n, std::vector<Real64> &B
347 : // int const dim // end dimension of arrays
348 : );
349 :
350 : private: // data
351 : enum class StorageModelType
352 : {
353 : Invalid = -1,
354 : SimpleBucketStorage,
355 : KIBaMBattery,
356 : LiIonNmcBattery,
357 : Num
358 : };
359 :
360 : std::string name_; // name of this electrical storage module
361 : Real64 storedPower_; // [W]
362 : Real64 storedEnergy_; // [J]
363 : Real64 drawnPower_; // [W]
364 : Real64 drawnEnergy_; // [J]
365 : Real64 decrementedEnergyStored_; // [J] this is the negative of StoredEnergy
366 : int maxRainflowArrayBounds_;
367 : bool myWarmUpFlag_;
368 : StorageModelType storageModelMode_; // type of model parameter, SimpleBucketStorage
369 : Sched::Schedule *availSched_ = nullptr; // availability schedule index.
370 : ThermalLossDestination heatLossesDestination_; // mode for where thermal losses go
371 : int zoneNum_; // destination zone for heat losses from inverter.
372 : Real64 zoneRadFract_; // radiative fraction for thermal losses to zone
373 : Real64 startingEnergyStored_; // [J] joules inside at beginning of environment period
374 : Real64 energeticEfficCharge_; // [ ] efficiency of charging
375 : Real64 energeticEfficDischarge_; // [ ] efficiency of discharging
376 : Real64 maxPowerDraw_; // [W] max rate of discharge
377 : Real64 maxPowerStore_; // [W] max rate of charge
378 : Real64 maxEnergyCapacity_; // [J] max storage capacity
379 : int parallelNum_; // [ ] number of battery modules in parallel
380 : int seriesNum_; // [ ] number of battery modules in series
381 : int numBattery_; // total number of batteries all together
382 : Curve::Curve *chargeCurve_ = nullptr; // [ ] voltage change curve for charging
383 : Curve::Curve *dischargeCurve_ = nullptr; // [ ] voltage change curve for discharging
384 : int cycleBinNum_; // [ ] number of cycle bins
385 : Real64 startingSOC_; // [ ] initial fractional state of charge
386 : Real64 maxAhCapacity_; // [Ah]maximum capacity
387 : Real64 availableFrac_; // [ ] maximum fraction of available charge capacity
388 : Real64 chargeConversionRate_; // [1/h]change rate from bound charge energy to available charge
389 : Real64 chargedOCV_; // [V] fully charged open circuit voltage
390 : Real64 dischargedOCV_; // [V] fully discharged open circuit voltage
391 : Real64 internalR_; // [ohm]internal electric resistance
392 : Real64 maxDischargeI_; // [A] maximum discharging current
393 : Real64 cutoffV_; // [V] cut-off voltage
394 : Real64 maxChargeRate_; // [1/h] charge rate limit
395 : bool lifeCalculation_; // [ ] battery life calculation: Yes or No
396 : Curve::Curve *lifeCurve_ = nullptr; // [ ] battery life curve
397 : Real64 liIon_dcToDcChargingEff_; // [ ] DC to DC Charging Efficiency (Li-ion NMC model)
398 : Real64 liIon_mass_; // [kg] mass of battery (Li-ion NMC model)
399 : Real64 liIon_surfaceArea_; // [m2] battery surface area (Li-ion NMC model)
400 : Real64 liIon_Cp_; // [J/kg-K] battery specific heat capacity (Li-ion NMC model)
401 : Real64 liIon_heatTransferCoef_; // [W/m2-K] Heat Transfer Coefficient Between Battery and Ambient (Li-ion NMC model)
402 : Real64 liIon_Vfull_; // [V] Fully charged cell voltage (Li-ion NMC model)
403 : Real64 liIon_Vexp_; // [V] Cell Voltage at End of Exponential Zone (Li-ion NMC model)
404 : Real64 liIon_Vnom_; // [V] Cell voltage at end of nominal zone (Li-ion NMC model)
405 : Real64 liIon_Vnom_default_; // [V] Default nominal cell voltage (Li-ion NMC model)
406 : Real64 liIon_Qfull_; // [A-h] Fully charged cell capacity (Li-ion NMC model)
407 : Real64 liIon_Qexp_; // [A-h] Cell capacity at end of exponential zone (Li-ion NMC model)
408 : Real64 liIon_Qnom_; // [A-h] Cell capacity at end of nominal zone (Li-ion NMC model)
409 : Real64 liIon_C_rate_; // [ ] Rate at which voltage vs capacity curve input (Li-ion NMC model)
410 : // calculated and from elsewhere vars
411 : Real64 thisTimeStepStateOfCharge_; // [J]
412 : Real64 lastTimeStepStateOfCharge_; // [J]
413 : Real64 pelNeedFromStorage_; // [W]
414 : Real64 pelFromStorage_; // [W]
415 : Real64 pelIntoStorage_; // [W]
416 : Real64 qdotConvZone_; // [W]
417 : Real64 qdotRadZone_; // [W]
418 : Real64 timeElapsed_; // [h]
419 : Real64 thisTimeStepAvailable_; // [Ah] available charge at the current timestep
420 : Real64 thisTimeStepBound_; // [Ah] bound charge at the current timestep
421 : Real64 lastTimeStepAvailable_; // [Ah] available charge at the previous timestep
422 : Real64 lastTimeStepBound_; // [Ah] bound charge at the previous timestep
423 : Real64 lastTwoTimeStepAvailable_; // [Ah] available charge at the previous two timesteps
424 : Real64 lastTwoTimeStepBound_; // [Ah] bound charge at the previous two timesteps
425 : // Li-ion NMC battery objects from SAM Simulation Core lib_battery
426 : std::unique_ptr<battery_t> ssc_battery_;
427 : std::unique_ptr<battery_state> ssc_lastBatteryState_;
428 : Real64 ssc_lastBatteryTimeStep_ = 0.0;
429 : std::unique_ptr<battery_state> ssc_initBatteryState_;
430 : Real64 ssc_initBatteryTimeStep_ = 0.0;
431 : // battery life calculation variables
432 : int count0_;
433 : std::vector<Real64> b10_;
434 : std::vector<Real64> x0_;
435 : std::vector<Real64> nmb0_;
436 : std::vector<Real64> oneNmb0_;
437 : // report
438 : Real64 electEnergyinStorage_; // [J] state of charge
439 : Real64 thermLossRate_; // [W]
440 : Real64 thermLossEnergy_; // [J]
441 : int storageMode_; // [ ] mode of operation 0 for idle, 1 for discharging, 2 for charging
442 : Real64 absoluteSOC_; // [Ah] total state of charge
443 : Real64 fractionSOC_; // [ ] fractional state of charge
444 : Real64 batteryCurrent_; // [A] total current
445 : Real64 batteryVoltage_; // [V] total voltage
446 : Real64 batteryDamage_; // [ ] fractional battery damage
447 : Real64 batteryTemperature_; // [C] battery temperature (only used in Li-ion batteries)
448 :
449 : }; // ElectricStorage
450 :
451 : class ElectricTransformer
452 : // This class is for modeling a power conversion device that changes from one voltage to another, or serves as an isolation transformer
453 : {
454 :
455 : public: // methods
456 : // Constructor
457 : ElectricTransformer(EnergyPlusData &state, std::string const &objectName);
458 :
459 : Real64 getLossRateForOutputPower(EnergyPlusData &state, Real64 const powerOutOfTransformer);
460 :
461 : Real64 getLossRateForInputPower(EnergyPlusData &state, Real64 const powerIntoTransformer);
462 :
463 : void manageTransformers(EnergyPlusData &state, Real64 const surplusPowerOutFromLoadCenters);
464 :
465 : void setupMeterIndices(EnergyPlusData &state);
466 :
467 : void reinitAtBeginEnvironment();
468 :
469 : void reinitZoneGainsAtBeginEnvironment();
470 :
471 : std::string const &name() const;
472 :
473 : private: // data
474 : enum class TransformerUse
475 : {
476 : Invalid = -1,
477 : PowerInFromGrid, // condition power from grid going into building buss
478 : PowerOutFromBldgToGrid, // condition power from building buss going out to grid
479 : PowerBetweenLoadCenterAndBldg, // condition power from a load center going into building buss, or from building buss into load center for
480 : // draws
481 : Num
482 : };
483 :
484 : static constexpr std::array<std::string_view, (int)TransformerUse::Num> transformerUseNames = {
485 : "PowerInFromGrid", "PowerOutToGrid", "LoadCenterPowerConditioning"};
486 : static constexpr std::array<std::string_view, (int)TransformerUse::Num> transformerUseNamesUC = {
487 : "POWERINFROMGRID", "POWEROUTTOGRID", "LOADCENTERPOWERCONDITIONING"};
488 :
489 : enum class TransformerPerformanceInput
490 : {
491 : Invalid = -1,
492 : LossesMethod,
493 : EfficiencyMethod,
494 : Num
495 : };
496 :
497 : static constexpr std::array<std::string_view, (int)TransformerPerformanceInput::Num> transformerPerformanceInputNames = {"RatedLosses",
498 : "NominalEfficiency"};
499 : static constexpr std::array<std::string_view, (int)TransformerPerformanceInput::Num> transformerPerformanceInputNamesUC = {"RATEDLOSSES",
500 : "NOMINALEFFICIENCY"};
501 :
502 : std::string name_; // user identifier
503 : bool myOneTimeFlag_;
504 : Sched::Schedule *availSched_ = nullptr; // availability schedule
505 : TransformerUse usageMode_; // mode for transformer usage
506 : ThermalLossDestination heatLossesDestination_; // mode for where thermal losses go
507 : int zoneNum_; // destination zone for heat losses from inverter.
508 : Real64 zoneRadFrac_; // radiative fraction for thermal losses to zone
509 : Real64 ratedCapacity_; // rated capacity [VA]
510 : // int phase_; // phase
511 : Real64 factorTempCoeff_; // thermal coefficient of resistance for winding material
512 : Real64 tempRise_; // full load temperature rise [C]
513 : Real64 eddyFrac_; // fraction of eddy current losses []
514 : TransformerPerformanceInput performanceInputMode_; // performance input method
515 : Real64 ratedEfficiency_; // nameplate efficiency []
516 : Real64 ratedPUL_; // per unit load for nameplate efficiency []
517 : Real64 ratedTemp_; // reference temperature for nameplate efficiency [C]
518 : Real64 maxPUL_; // per unit load for maximum efficiency []
519 : bool considerLosses_; // if true, consider transformer lossses in metering
520 : std::vector<std::string> wiredMeterNames_; // names of the meters wired to transformer
521 : std::vector<int> wiredMeterPtrs_; // array of "pointers" to meters wired to transformer
522 : std::vector<bool> specialMeter_; // indicates whether a meter needs special consideration
523 : // Electricity:Facility and Electricity:HVAC are two special
524 : // meters because tranformer loss is part of them
525 : // calculated and from elsewhere vars
526 : Real64 ratedNL_; // rated no load losses, user input or calculated [W]
527 : Real64 ratedLL_; // rated load losses, user input or calculated [W]
528 : int overloadErrorIndex_; // used for warning message when transformer is overloaded
529 : // results and reporting
530 : Real64 efficiency_; // transformer efficiency
531 : Real64 powerIn_; // [W]
532 : Real64 energyIn_; // [J]
533 : Real64 powerOut_; // [W]
534 : Real64 energyOut_; // [J]
535 : Real64 noLoadLossRate_; // [W]
536 : Real64 noLoadLossEnergy_; // [J]
537 : Real64 loadLossRate_; // [W]
538 : Real64 loadLossEnergy_; // [J]
539 : Real64 totalLossRate_; // [W]
540 : // Real64 totalLossEnergy_; // [J]
541 : Real64 thermalLossRate_; // [W]
542 : Real64 thermalLossEnergy_; // [J]
543 : Real64 elecUseMeteredUtilityLosses_; // [J] Energy consumption for a utility transformer (power in)
544 : // Positive values
545 : Real64 powerConversionMeteredLosses_; // [J] Energy consumption for a (cogeneration )transformer (power out from building to grid)
546 : // Negative values
547 : Real64 qdotConvZone_; // [W]
548 : Real64 qdotRadZone_; // [W]
549 : }; // ElectricTransformer
550 :
551 : class GeneratorController
552 : // this class is used as part of the supervisory control and calling of electric power generators. Each instances is for one generator
553 : {
554 :
555 : public: // Method
556 : // Constructor
557 : GeneratorController(EnergyPlusData &state,
558 : std::string const &objectName,
559 : std::string const &objectType,
560 : Real64 ratedElecPowerOutput,
561 : std::string const &availSchedName,
562 : Real64 thermalToElectRatio);
563 :
564 : void simGeneratorGetPowerOutput(EnergyPlusData &state,
565 : bool const runFlag, // true if generator is on
566 : Real64 const myElecLoadRequest, // target electric power production request
567 : bool const FirstHVACIteration, //
568 : Real64 &electricPowerOutput, // Actual generator electric power output
569 : Real64 &thermalPowerOutput // Actual generator thermal power output
570 : );
571 :
572 : void reinitAtBeginEnvironment();
573 :
574 : public: // data // might make this class a friend of ElectPowerLoadCenter?
575 : std::string name; // user identifier
576 : GeneratorType generatorType; // Numeric designator for generator CompType (TypeOf), in DataGlobalConstants
577 : DataPlant::PlantEquipmentType compPlantType{DataPlant::PlantEquipmentType::Invalid}; // numeric designator for plant component, in DataPlant
578 : std::string compPlantName; // name of plant component if heat recovery
579 : int generatorIndex; // index in generator model data struct
580 : Real64 maxPowerOut; // Maximum Power Output (W)
581 : Sched::Schedule *availSched = nullptr; // pointer to operation schedule
582 : Real64 powerRequestThisTimestep; // Current Demand on Equipment (W)
583 : bool onThisTimestep; // Indicator whether Generator on
584 : Real64 eMSPowerRequest; // EMS actuator for current demand on equipment (W)
585 : bool eMSRequestOn; // EMS actuating On if true.
586 : bool plantInfoFound;
587 : PlantLocation cogenLocation;
588 : Real64 nominalThermElectRatio; // Cogen: nominal ratio of thermal to elect production
589 : // results of component models for load center reporting
590 : Real64 dCElectricityProd; // Current DC Electric Produced from Equipment (J)
591 : Real64 dCElectProdRate; // Current DC Electric Production Rate from Equipment (W)
592 : Real64 electricityProd; // Current AC Electric Produced from Equipment (J)
593 : Real64 electProdRate; // Current AC Electric Production Rate from Equipment (W)
594 : Real64 thermalProd; // Current Thermal energy Produced from Equipment (J)
595 : Real64 thermProdRate; // Current Thermal energy Production Rate from Equipment (W)
596 :
597 : std::unique_ptr<PVWatts::PVWattsGenerator> pvwattsGenerator; // PVWattsGenerator object pointer
598 :
599 : private:
600 : int errCountNegElectProd_; // error count for reccuring error when generators produce negative electric power
601 :
602 : }; // class GeneratorController
603 :
604 : class ElectPowerLoadCenter
605 : // This class if for modeling a load center which can be thought of as a kind of subpanel that connects power equipment to a main panel
606 : // multiple subpanels can be connected to the main panel and each ElectPowerLoadCenter object is a subpanel
607 : // Each load center will contain other power conversion devices and/or generator(s).
608 : {
609 :
610 : public: // Methods
611 : // Constructor
612 : ElectPowerLoadCenter(EnergyPlusData &state, int const objectNum);
613 :
614 : void manageElecLoadCenter(EnergyPlusData &state, bool const firstHVACIteration, Real64 &remainingPowerDemand);
615 :
616 : void setupLoadCenterMeterIndices(EnergyPlusData &state);
617 :
618 : void reinitAtBeginEnvironment();
619 :
620 : void reinitZoneGainsAtBeginEnvironment();
621 :
622 : std::string const &generatorListName() const;
623 :
624 : void updateLoadCenterGeneratorRecords(EnergyPlusData &state);
625 :
626 : private: // Methods
627 : void dispatchGenerators(EnergyPlusData &state, bool const firstHVACIteration, Real64 &remainingPowerDemand);
628 :
629 : void dispatchStorage(EnergyPlusData &state, Real64 const remainingPowerDemand);
630 :
631 : Real64 calcLoadCenterThermalLoad(EnergyPlusData &state); // returns heat rate called for from cogenerator(watts)
632 :
633 : public: // data public for unit test
634 : enum class ElectricBussType
635 : {
636 : Invalid = -1,
637 : ACBuss,
638 : DCBussInverter,
639 : ACBussStorage,
640 : DCBussInverterDCStorage,
641 : DCBussInverterACStorage,
642 : Num
643 : };
644 :
645 : static constexpr std::array<std::string_view, (int)ElectricBussType::Num> electricBussTypeNames = {"AlternatingCurrent",
646 : "DirectCurrentWithInverter",
647 : "AlternatingCurrentWithStorage",
648 : "DirectCurrentWithInverterDCStorage",
649 : "DirectCurrentWithInverterACStorage"};
650 : static constexpr std::array<std::string_view, (int)ElectricBussType::Num> electricBussTypeNamesUC = {"ALTERNATINGCURRENT",
651 : "DIRECTCURRENTWITHINVERTER",
652 : "ALTERNATINGCURRENTWITHSTORAGE",
653 : "DIRECTCURRENTWITHINVERTERDCSTORAGE",
654 : "DIRECTCURRENTWITHINVERTERACSTORAGE"};
655 :
656 : std::unique_ptr<ElectricStorage> storageObj;
657 : std::unique_ptr<ACtoDCConverter> converterObj;
658 : std::unique_ptr<ElectricTransformer> transformerObj;
659 : int numGenerators; // Number of Generators
660 : std::vector<std::unique_ptr<GeneratorController>> elecGenCntrlObj; // generator controller objects
661 : ElectricBussType bussType; // is this load center powered by AC or DC generators
662 : Real64 thermalProd; // Current thermal energy Produced from generators in load center (J)
663 : Real64 thermalProdRate; // Current thermal energy production rate from generators in load center (W)
664 : bool inverterPresent;
665 : std::string inverterName; // hold name for verificaton and error messages
666 : std::unique_ptr<DCtoACInverter> inverterObj;
667 : Real64 subpanelFeedInRequest;
668 : // subpanel terms, interact with main panel
669 : Real64 subpanelFeedInRate; // Current AC electric power fed into main panel by load center, adjusted by inverter if any (W)
670 : Real64 subpanelDrawRate; // Current AC electric power draw from main panel into load center (W)
671 : // storage operation terms,
672 : Real64 genElectricProd; // Current electric produced by generators in the load center, DC or AC (J)
673 : Real64 genElectProdRate; // Current electric power produced by generators in the load center, DC or AC (W)
674 : Real64 storOpCVGenRate; // power from generators (and maybe inverter) going into storage operation control volume, DC or AC ( W )
675 : Real64 storOpCVDrawRate; // power drawn from main panel into storage operation control volume after any converter, DC or AC ( W )
676 : Real64 storOpCVFeedInRate; // power fed toward main panel from storage operation control volume before any inverter, DC or AC ( W )
677 : Real64 storOpCVChargeRate; // power fed into storage device from storage operation control volume, before any storage losses, DC or AC ( W )
678 : Real64 storOpCVDischargeRate; // power drawn from storage device into storage operation control volume, after any storage losses, DC or AC ( W )
679 : bool storOpIsCharging; // true if storage operation scheme is trying to charge
680 : bool storOpIsDischarging; // true if storage operation scheme is trying to discharge
681 :
682 : private: // data
683 : enum class GeneratorOpScheme : int
684 : {
685 : Invalid = -1,
686 : BaseLoad,
687 : DemandLimit,
688 : TrackElectrical,
689 : TrackSchedule,
690 : TrackMeter,
691 : ThermalFollow,
692 : ThermalFollowLimitElectrical,
693 : Num
694 : };
695 :
696 : static constexpr std::array<std::string_view, (int)GeneratorOpScheme::Num> generatorOpSchemeNames = {
697 : "Baseload", "DemandLimit", "TrackElectrical", "TrackSchedule", "TrackMeter", "FollowThermal", "FollowThermalLimitElectrical"};
698 : static constexpr std::array<std::string_view, (int)GeneratorOpScheme::Num> generatorOpSchemeNamesUC = {
699 : "BASELOAD", "DEMANDLIMIT", "TRACKELECTRICAL", "TRACKSCHEDULE", "TRACKMETER", "FOLLOWTHERMAL", "FOLLOWTHERMALLIMITELECTRICAL"};
700 :
701 : enum class StorageOpScheme : int
702 : {
703 : Invalid = -1,
704 : FacilityDemandStoreExcessOnSite, // legacy control behavior
705 : MeterDemandStoreExcessOnSite,
706 : ChargeDischargeSchedules,
707 : FacilityDemandLeveling,
708 : Num
709 : };
710 :
711 : static constexpr std::array<std::string_view, (int)StorageOpScheme::Num> storageOpSchemeNames = {"TrackFacilityElectricDemandStoreExcessOnSite",
712 : "TrackMeterDemandStoreExcessOnSite",
713 : "TrackChargeDischargeSchedules",
714 : "FacilityDemandLeveling"};
715 : static constexpr std::array<std::string_view, (int)StorageOpScheme::Num> storageOpSchemeNamesUC = {"TRACKFACILITYELECTRICDEMANDSTOREEXCESSONSITE",
716 : "TRACKMETERDEMANDSTOREEXCESSONSITE",
717 : "TRACKCHARGEDISCHARGESCHEDULES",
718 : "FACILITYDEMANDLEVELING"};
719 :
720 : std::string name_; // user identifier
721 : std::string generatorListName_; // List name of available generators
722 : GeneratorOpScheme genOperationScheme_; // Name of Operation Scheme
723 : std::string demandMeterName_; // Name of Demand Energy Meter for "on demand" operation
724 : int demandMeterPtr_; // "pointer" to Meter for electrical Demand to meet
725 : std::string generationMeterName_; // Name of Generated Energy Meter for "on demand" operation
726 : bool generatorsPresent_; // true if any generators
727 : bool myCoGenSetupFlag_;
728 : Real64 demandLimit_; // Demand Limit in Watts(W) which the generator will operate above
729 : Sched::Schedule *trackSched_ = nullptr; // schedule for electrical demand to meet.
730 : bool storagePresent_;
731 : std::string storageName_; // hold name for verificaton and error messages
732 : bool transformerPresent_; // should only be transformers for on-site load center, not facility service
733 : std::string transformerName_; // hold name for verificaton and error messages
734 : Real64 totalPowerRequest_; // Total electric power request from the load center (W)
735 : Real64 totalThermalPowerRequest_; // Total thermal power request from the load center (W)
736 : StorageOpScheme storageScheme_; // what options are available for charging storage.
737 : std::string trackSorageOpMeterName_; // user name for a specific meter
738 : int trackStorageOpMeterIndex_; // points to meter being
739 : bool converterPresent_;
740 : std::string converterName_;
741 : Real64 maxStorageSOCFraction_; // Fraction of storage capacity used as upper limit for controlling charging (don't overcharge the batteries)
742 : Real64 minStorageSOCFraction_; // Fraction of storage capacity used as lower limit for controlling discharging (dont drain the batteries too far)
743 : Real64 designStorageChargePower_; // rate of electric power drawn from grid to go into storage
744 : bool designStorageChargePowerWasSet_; // true if a value was input
745 : Real64 designStorageDischargePower_; // rate of electric power exported to grid by being drawn from storage
746 : bool designStorageDischargePowerWasSet_; // true if value was input
747 : Sched::Schedule *storageChargeModSched_ = nullptr; // index of fraction schedule for controlling charge rate over time
748 : Sched::Schedule *storageDischargeModSched_ = nullptr; // index of fraction schedule for controlling discharge rate over time.
749 : Real64 facilityDemandTarget_; // target utility demand level in Watts
750 : Sched::Schedule *facilityDemandTargetModSched_ = nullptr; // index of fracton schedule for controlling target demand over time.
751 : bool eMSOverridePelFromStorage_; // if true, EMS calling for override
752 : Real64 eMSValuePelFromStorage_; // value EMS is directing to use, power from storage [W]
753 : bool eMSOverridePelIntoStorage_; // if true, EMS calling for override
754 : Real64 eMSValuePelIntoStorage_; // value EMS is directing to use, power into storage [W]
755 :
756 : }; // class ElectPowerLoadCenter
757 :
758 : class ElectricPowerServiceManager //
759 : // This class if the top level object for modeling complex electric power service. It contains transformers and/or
760 : // load center(s).
761 : {
762 :
763 : public: // Creation
764 : // Default Constructor
765 144 : ElectricPowerServiceManager()
766 288 : : newEnvironmentInternalGainsFlag(true), numElecStorageDevices(0), getInputFlag_(true), newEnvironmentFlag_(true), numLoadCenters_(0),
767 144 : numTransformers_(0), setupMeterIndexFlag_(true), elecFacilityMeterIndex_(-1), elecProducedCoGenMeterIndex_(-1),
768 144 : elecProducedPVMeterIndex_(-1), elecProducedWTMeterIndex_(-1), elecProducedStorageMeterIndex_(-1),
769 288 : elecProducedPowerConversionMeterIndex_(-1), name_("Whole Building"), facilityPowerInTransformerPresent_(false), numPowerOutTransformers_(0),
770 144 : wholeBldgRemainingLoad_(0.0), electricityProd_(0.0), electProdRate_(0.0), electricityPurch_(0.0), electPurchRate_(0.0),
771 144 : electSurplusRate_(0.0), electricitySurplus_(0.0), electricityNetRate_(0.0), electricityNet_(0.0), totalBldgElecDemand_(0.0),
772 144 : totalHVACElecDemand_(0.0), totalElectricDemand_(0.0), elecProducedPVRate_(0.0), elecProducedWTRate_(0.0), elecProducedStorageRate_(0.0),
773 288 : elecProducedPowerConversionRate_(0.0), elecProducedCoGenRate_(0.0), pvTotalCapacity_(0.0), windTotalCapacity_(0.0)
774 : {
775 144 : }
776 :
777 : public: // Methods
778 : void manageElectricPowerService(EnergyPlusData &state,
779 : bool const FirstHVACIteration,
780 : bool &SimElecCircuits, // simulation convergence flag
781 : bool const UpdateMetersOnly // if true then don't resimulate generators, just update meters.
782 : );
783 :
784 : void reinitZoneGainsAtBeginEnvironment();
785 :
786 : void verifyCustomMetersElecPowerMgr(EnergyPlusData &state);
787 :
788 : private: // Methods
789 : void getPowerManagerInput(EnergyPlusData &state);
790 :
791 : void setupMeterIndices(EnergyPlusData &state);
792 :
793 : void reinitAtBeginEnvironment();
794 :
795 : void updateWholeBuildingRecords(EnergyPlusData &state);
796 :
797 : void reportPVandWindCapacity(EnergyPlusData &state);
798 :
799 : void sumUpNumberOfStorageDevices();
800 :
801 : void checkLoadCenters(EnergyPlusData &state);
802 :
803 : public: // data
804 : bool newEnvironmentInternalGainsFlag;
805 : int numElecStorageDevices;
806 : std::vector<std::unique_ptr<ElectPowerLoadCenter>> elecLoadCenterObjs;
807 :
808 : private: // data
809 : bool getInputFlag_; // control if object needs to get input and call factory methods
810 : bool newEnvironmentFlag_; // control if object needs to reinit at beginning of a new environment period
811 : int numLoadCenters_;
812 : int numTransformers_;
813 : bool setupMeterIndexFlag_; // control if object needs to make calls to GetMeterIndex
814 : int elecFacilityMeterIndex_;
815 : int elecProducedCoGenMeterIndex_;
816 : int elecProducedPVMeterIndex_;
817 : int elecProducedWTMeterIndex_;
818 : int elecProducedStorageMeterIndex_;
819 : int elecProducedPowerConversionMeterIndex_;
820 : std::string name_;
821 : bool facilityPowerInTransformerPresent_;
822 : std::string facilityPowerInTransformerName_; // hold name for verificaton and error messages
823 : std::unique_ptr<ElectricTransformer> facilityPowerInTransformerObj_;
824 : int numPowerOutTransformers_;
825 : std::string powerOutTransformerName_;
826 : std::unique_ptr<ElectricTransformer> powerOutTransformerObj_;
827 : Real64 wholeBldgRemainingLoad_;
828 : Real64 electricityProd_; // Current Electric Produced from Equipment (J)
829 : Real64 electProdRate_; // Current Electric Production Rate from Equipment (W)
830 : Real64 electricityPurch_; // Current Purchased Electric (J)
831 : Real64 electPurchRate_; // Current Electric Purhcased Rate (W)
832 : Real64 electSurplusRate_; // Current excess power (W)
833 : Real64 electricitySurplus_; // Current excess energy (J)
834 : Real64 electricityNetRate_; // Net elect rate, + is Purchased, - is Surplus (W)
835 : Real64 electricityNet_; // Net energy, + is Purchased, - is Surplus (J)
836 : Real64 totalBldgElecDemand_; // Current Total Building Electric Demand (W)
837 : Real64 totalHVACElecDemand_; // Current Total HVAC Electric Demand (W)
838 : Real64 totalElectricDemand_; // Current Total Electric Demand (W)
839 : Real64 elecProducedPVRate_; // Current Rate of PV Produced from the Arrays (W)
840 : Real64 elecProducedWTRate_; // Current Rate of Wind Turbine Produced (W)
841 : Real64 elecProducedStorageRate_; // Current Rate of power to(-)/from(+) storage
842 : Real64 elecProducedPowerConversionRate_; // Current rate of power loss from power conversion, negative (W)
843 : Real64 elecProducedCoGenRate_; // Current Rate of Cogeneration generators produced ( W )
844 : Real64 pvTotalCapacity_; // for LEED report, total installed PV capacity
845 : Real64 windTotalCapacity_; // for LEED report, total installed wind capacity
846 :
847 : }; // class ElectricPowerServiceManager
848 :
849 : void createFacilityElectricPowerServiceObject(const EnergyPlusData &state);
850 :
851 : Real64 checkUserEfficiencyInput(EnergyPlusData &state, Real64 userInputValue, bool isCharging, std::string const &deviceName, bool &errorsFound);
852 :
853 : void checkChargeDischargeVoltageCurves(
854 : EnergyPlusData &state, std::string_view nameBatt, Real64 const E0c, Real64 const E0d, Curve::Curve *chargeCurve, Curve::Curve *dischargeCurve);
855 :
856 : struct ElectPwrSvcMgrData : BaseGlobalStruct
857 : {
858 :
859 : std::unique_ptr<ElectricPowerServiceManager> facilityElectricServiceObj;
860 :
861 2126 : void init_constant_state([[maybe_unused]] EnergyPlusData &state) override
862 : {
863 2126 : }
864 :
865 1152 : void init_state([[maybe_unused]] EnergyPlusData &state) override
866 : {
867 1152 : }
868 :
869 2100 : void clear_state() override
870 : {
871 2100 : this->facilityElectricServiceObj.release();
872 2100 : }
873 : };
874 :
875 : } // namespace EnergyPlus
876 : #endif // ElectricPowerServiceManager_hh_INCLUDED
|