33// that can be found in the LICENSE file.
44
55#include " cnglob.h"
6+
67#include " ancrec.h"
78#include " rccn.h"
89
910#include " cnguts.h"
10- #include < cmath>
1111
12+ // ----------------------------------------------------------------------------
1213RC BATTERY::bt_CkF ()
1314{
1415 RC rc = RCOK;
1516 return rc;
1617} // BATTERY::bt_CkF
17-
18+ // ----------------------------------------------------------------------------
1819RC BATTERY::RunDup ( // copy input to run record; check and initialize
1920 const record* pSrc, // input record
2021 int options/* =0*/ )
2122{
22- RC rc = record::RunDup (pSrc, options);
23+ RC rc = record::RunDup ( pSrc, options);
2324 return rc;
2425} // BATTERY::RunDup
25-
26+ // ----------------------------------------------------------------------------
2627RC BATTERY::bt_Init ()
2728{
2829 RC rc = RCOK;
@@ -33,76 +34,94 @@ RC BATTERY::bt_Init()
3334 bt_loadSeen = 0.0 ;
3435 return rc;
3536} // BATTERY::bt_Init
36-
37- // MTR -> float
38- // Given a meter ( MTR) object, calculate all loads and return as power in kW
39- float BATTERY::bt_CalcAdjLoad (MTR m)
37+ // -----------------------------------------------------------------------------
38+ float BATTERY::bt_CalcAdjLoad ( // default load
39+ const MTR& m) const // source meter
40+ // returns sum of all end uses, kW
4041{
41- float btuh_to_kW (1.0 /3412.142 );
42- return (m.H .clg
43- + m.H .htg
44- + m.H .hp
45- + m.H .dhw
46- + m.H .dhwBU
47- + m.H .fanC
48- + m.H .fanH
49- + m.H .fanV
50- + m.H .fan
51- + m.H .aux
52- + m.H .proc
53- + m.H .lit
54- + m.H .rcp
55- + m.H .ext
56- + m.H .refr
57- + m.H .dish
58- + m.H .dry
59- + m.H .wash
60- + m.H .cook
61- + m.H .usr1
62- + m.H .usr2
63- + m.H .pv ) * btuh_to_kW;
64- }
65-
66- RC BATTERY::bt_DoHour ()
42+ return float ( m.H .mtr_NetBldgLoad () / 3412.142 );
43+ } // bt_CalcAdjLoad
44+ // -----------------------------------------------------------------------------
45+ RC BATTERY::bt_DoHour (
46+ int stage) // 0: pre-calc
47+ // 1: calcs
48+ // 2: after reports
6749{
50+ static const float kW_to_btuh = 3412 .142f ;
51+ static const float dt = 1 .f ; // timestep duration, hr
52+
6853 RC rc = RCOK;
69- float P_load_adj (0.0 ); // building + PV load, power [kW]
70- float P_bt_req (0.0 ); // battery requested discharge power [kW]
71- float P_bt_max_cap (0.0 ); // battery maximum (charge) power based on capacity [kW]
72- float P_bt_min_cap (0.0 ); // battery minimum (discharge) power based on capacity [kW]
73- float P_bt (0.0 ); // battery discharge power [kW]
74- float dE_bt_app (0.0 ); // battery apparent power change [kWh]
75- float dE_bt (0.0 ); // actual battery discharged energy [kWh]
76- float eff (1.0 ); // efficiency of the battery [fraction]
77- float dt (1.0 ); // hours in this timestep [hr]
78- float dsoe (0.0 ); // change in SOE
79- float kW_to_btuh (3412.142 );
80- float tolerance (bt_maxCap * 1e-6 ); // tolerance for capacity calculations [kW] -- used to prevent underflow issues
81- bt_loadSeen = 0.0 ;
82- if (bt_meter) {
83- P_load_adj = bt_CalcAdjLoad (MtrB.p [bt_meter]);
84- bt_loadSeen = P_load_adj;
54+
55+ if (stage == 0 )
56+ { // stage 0: after meter accum, before EVENDIVL expression eval
57+ // bt_loadSeen is thus available at EVENDIVL
58+ if (Top.tp_isBegMainSim && IsSet ( BATTERY_INITSOE))
59+ // Ensure battery is reinitialized
60+ // after warmup and/or autosizing
61+ // ONLY IF bt_initSOE was set by user
62+ rc = bt_Init ();
63+
64+ // building + PV net from meter if available
65+ bt_loadSeen = bt_meter ? bt_CalcAdjLoad ( MtrB.p [bt_meter]) : 0 .f ;
66+ }
67+ else if (stage == 1 )
68+ { // stage 1: after EVENDIVL expression eval
69+ // results have *p (EVPSTIVL) stage (available in reports)
70+
71+ float tolerance (bt_maxCap * 1e-6 ); // tolerance for capacity calculations [kW]
72+ // used to prevent underflow issues
73+
74+ // battery requested discharge power[ kW]
75+ float P_bt_req = bt_useUsrChg == C_NOYESCH_YES
76+ ? bt_chgReq // user-specified discharge request
77+ : -bt_loadSeen; // default control strategy
78+
79+ // battery maximum (charge) power based on capacity [kW]
80+ float P_bt_max_cap = (bt_maxCap * (1 .f - bt_soe)) / (dt * bt_chgEff);
81+ if (P_bt_max_cap < tolerance)
82+ P_bt_max_cap = 0 .f ;
83+
84+ // battery minimum (discharge) power based on capacity [kW]
85+ float P_bt_min_cap = -1.0 * (bt_maxCap * bt_soe * bt_dschgEff) / dt;
86+ if (P_bt_min_cap > (-tolerance))
87+ P_bt_min_cap = 0 .f ;
88+
89+ // battery discharge power [kW]
90+ float P_bt = bracket<float >( max ( P_bt_min_cap, -bt_maxDschgPwr), P_bt_req, min ( P_bt_max_cap, bt_maxChgPwr));
91+
92+ // battery apparent power change [kWh]
93+ float dE_bt_app = P_bt * dt;
94+
95+ // efficiency of battery
96+ float eff = dE_bt_app >= 0 .f ? bt_chgEff : (1 .f / bt_dschgEff);
97+
98+ // actual battery discharged energy [kWh]
99+ // update energy
100+ float dE_bt = dE_bt_app * eff;
101+ float energyPrior = bt_energy;
102+ bt_energy = bracket (0 .f , bt_energy + dE_bt, bt_maxCap);
103+ dE_bt = bt_energy - energyPrior; // force consistency in case bracket() changed bt_energy
104+
105+ // state of energy
106+ bt_soe = bt_energy / bt_maxCap;
107+
108+ // soeBegIvl is used to provide probe access to SOE for the beginning of the next interval
109+ // during expression evaluation
110+ bt_soeBegIvl = bt_soe;
111+
112+ // we divide by 2 because one full discharge and one full charge = one cycle
113+ bt_cycles += fabs ( dE_bt / bt_maxCap) / 2 .f ;
114+ if (bt_meter)
115+ MtrB.p [bt_meter].H .mtr_Accum (bt_endUse, P_bt * kW_to_btuh );
116+ }
117+ else
118+ { // stage == 2 (after reports): copy current hour results to xxxlh
119+ // re availability for probing in e.g. next hour control expressions
120+ bt_soelh = bt_soe;
121+ bt_energylh = bt_energy;
122+ bt_cycleslh = bt_cycles;
85123 }
86- P_bt_req = (bt_useUsrChg == C_NOYESCH_NO) ? -1.0 * P_load_adj : bt_chgReq;
87- P_bt_max_cap = (bt_maxCap * (1.0 - bt_soe)) / (dt * bt_chgEff);
88- if (P_bt_max_cap < tolerance)
89- P_bt_max_cap = 0.0 ;
90- P_bt_min_cap = -1.0 * (bt_maxCap * bt_soe * bt_dschgEff) / dt;
91- if (P_bt_min_cap > (-1.0 * tolerance))
92- P_bt_min_cap = 0.0 ;
93- P_bt = bracket<float >(max (P_bt_min_cap, -1.0 * bt_maxDschgPwr), P_bt_req, min (P_bt_max_cap, bt_maxChgPwr));
94- dE_bt_app = P_bt * dt;
95- eff = (dE_bt_app >= 0.0 ) ? bt_chgEff : (1.0 / bt_dschgEff);
96- dE_bt = dE_bt_app * eff;
97- bt_energy = bt_energy + dE_bt;
98- dsoe = dE_bt / bt_maxCap;
99- bt_soe = bt_soe + dsoe;
100- // soeBegIvl is used to provide probe access to SOE for the beginning of the next interval
101- // during expression evaluation
102- bt_soeBegIvl = bt_soe;
103- // we devide by two because one full discharge and one full charge = one cycle
104- bt_cycles = bt_cycles + (std::abs (dsoe) / 2.0 );
105- if (bt_meter)
106- MtrB.p [bt_meter].H .mtr_Accum (bt_endUse, P_bt * kW_to_btuh );
107124 return rc;
108- } // BATTERY::bt_DoHour()
125+ } // BATTERY::bt_DoHour
126+
127+ // battery.cpp end
0 commit comments