How to prevent grid charging when using TrackChargeDischargeSchedules in ElectricLoadCenter:Distribution?

Hi there,

I know it is a bit off-topic for this forum. However, maybe somebody can shed light to the challenge.

I have implemented a large-scale photovoltaic (PV) system with battery storage and defined specific schedules for charging and discharging. A relevant portion of the IDF file is provided below.

Thank you very much for your time and assistance. From the documentation and prior discussions, I understand that enabling scheduled battery charging and discharging requires using TrackChargeDischargeSchedules as the Storage Operation Scheme in the ElectricLoadCenter:Distribution object.

However, the issue I am encountering is that TrackChargeDischargeSchedules appears to allow the battery to charge using electricity from the grid, which is not my objective.

In my case, the battery capacity is relatively large. On sunny days, the battery can be fully charged during the scheduled period using PV generation alone. However, I would like to avoid any charging from the grid. If PV production is insufficient (e.g., on cloudy days), I prefer the battery to remain partially charged rather than drawing electricity from the grid.

I would greatly appreciate any guidance on how to configure the system so that the battery follows the specified charging and discharging schedules while being charged exclusively from on-site renewable generation (e.g., PV), without importing electricity from the grid.

Schedule:Compact, ALWAYS_ON, !- Name On/Off, !- Schedule Type Limits Name Through: 12/31, !- Field 1 For: AllDays, !- Field 2 Until: 24:00,1; !- Field 3

ElectricLoadCenter:Storage:Converter, Converter 1, !- Name ALWAYS_ON, !- Availability Schedule Name SimpleFixed, !- Power Conversion Efficiency Method 0.95, !- Simple Fixed Efficiency , !- Design Maximum Continuous Input Power {W} , !- Efficiency Function of Power Curve Name 20, !- Ancillary Power Consumed In Standby {W} , !- Zone Name 0.25; !- Radiative Fraction

ElectricLoadCenter:Storage:LiIonNMCBattery, NMC_Battery, !- Name ALWAYS_ON, !- Availability Schedule Name , !- Zone Name 0.0, !- Radiative Fraction KandlerSmith, !- Lifetime Model 13, !- Number of Cells in Series 80, !- Number of Strings in Parallel 0.7, !- Initial Fractional State of Charge , !- DC to DC Charging Efficiency 80, !- Battery Mass {kg} 10, !- Battery Surface Area {m2} 0.95, !- Maximum Storage State of Charge Fraction 0.20; !- Minimum Storage State of Charge Fraction

ElectricLoadCenter:Inverter:LookUpTable, Electric Load Center Inverter Simple 1, !- Name ALWAYS_ON, !- Availability Schedule Name , !- Zone Name 0.25, !- Radiative Fraction 14000, !- Rated Maximum Continuous Output Power {W} 200.0, !- Night Tare Loss Power {W} 368, !- Nominal Voltage Input {V} 0.839, !- Efficiency at 10% Power and Nominal Voltage 0.897, !- Efficiency at 20% Power and Nominal Voltage 0.916, !- Efficiency at 30% Power and Nominal Voltage 0.931, !- Efficiency at 50% Power and Nominal Voltage 0.934, !- Efficiency at 75% Power and Nominal Voltage 0.930; !- Efficiency at 100% Power and Nominal Voltage

ScheduleTypeLimits, Fraction, !- Name 0.0, !- Lower Limit Value 1.0, !- Upper Limit Value CONTINUOUS; !- Numeric Type

Schedule:Compact, Charge Schedule, !- Name Fraction, !- Schedule Type Limits Name Through: 12/31, !- Field 1 For: AllDays, !- Field 2 Until: 10:00,0.0, !- Field 3 Until: 14:00,1.0, !- Field 5 Until: 24:00,0.0; !- Field 5

Schedule:Compact, Discharge Schedule, !- Name Fraction, !- Schedule Type Limits Name Through: 12/31, !- Field 1 For: AllDays, !- Field 2 Until: 17:00,0.0, !- Field 3 Until: 24:00,1.0; !- Field 5

ElectricLoadCenter:Distribution, Model Load Center Distribution 1, !- Name Electric Load Center Distribution 1 Generators, !- Generator List Name Baseload, !- Generator Operation Scheme Type 0, !- Generator Demand Limit Scheme Purchased Electric Demand Limit {W} , !- Generator Track Schedule Name Scheme Schedule Name , !- Generator Track Meter Scheme Meter Name DirectCurrentWithInverterDCStorage, !- Electrical Buss Type Electric Load Center Inverter Simple 1, !- Inverter Name NMC_Battery, !- Electrical Storage Object Name , !- Transformer Object Name TrackChargeDischargeSchedules, !- Storage Operation Scheme , !- Storage Control Track Meter Name Converter 1, !- Storage Converter Object Name 0.96, !- Maximum Storage State of Charge Fraction 0.04, !- Minimum Storage State of Charge Fraction 5000, !- Design Storage Control Charge Power {W} Charge Schedule, !- Storage Charge Power Fraction Schedule Name 5000, !- Design Storage Control Discharge Power {W} Discharge Schedule, !- Storage Discharge Power Fraction Schedule Name , !- Storage Control Utility Demand Target {W} ; !- Storage Control Utility Demand Target Fraction Schedule Name

Sincerely,
Behnam Mohseni Gharyehsafa
Ireland

Hi @behnammmohseni!
I haven’t read the relevant part of the docs in ages but chatgpt is saying something about needing external logic via ems/pyems:

from chat:
With TrackChargeDischargeSchedules, you generally cannot prevent grid charging by configuration alone. In that scheme, EnergyPlus treats the charge schedule as a requested charging power:

Design Storage Control Charge Power Ă— Storage Charge Power Fraction Schedule

and if on-site generation is less than that charging request, EnergyPlus draws the shortfall from the main panel / grid.

So under TrackChargeDischargeSchedules, the behavior is essentially:

if Pgen > Pcharge, excess generation can go to storage

if Pgen < Pcharge, EnergyPlus sets Pdraw = Pcharge - Pgen and charges from the grid.

That means the clean ways to avoid grid charging are:

Use a different storage operation scheme
TrackFacilityElectricDemandStoreExcessOnSite does not draw from the main panel to charge storage (Pdraw = 0). It only stores excess on-site generation. TrackMeterDemandStoreExcessOnSite behaves similarly but tracks a chosen meter instead of whole-facility demand.

Keep TrackChargeDischargeSchedules, but force the charge schedule to zero whenever grid charging would occur
In practice this means the charge-fraction schedule must be generated by some external logic, such as:

EMS

Python Plugin

preprocessing/postprocessing workflow
so charging is enabled only when you know surplus on-site generation is available. The built-in schedule itself is just a fraction from 0 to 1; it does not check whether the charging energy comes from PV or the grid.

A couple of related notes:

Maximum Storage State of Charge Fraction only caps charging at a SOC limit; it does not stop grid charging by itself.

For DC storage with grid-supplied charging under TrackChargeDischargeSchedules or FacilityDemandLeveling, EnergyPlus requires a storage converter object, which is another hint that grid charging is an intended feature of this scheme.

So the practical answer is:

If you want “charge only from excess on-site generation,” use TrackFacilityElectricDemandStoreExcessOnSite or TrackMeterDemandStoreExcessOnSite.

If you must use TrackChargeDischargeSchedules, the only workaround is to control the charging schedule externally so it is zero unless surplus generation exists.

hopefully that is helpful!
best
-trevor

1 Like

chats been pretty good about documentation reference and compilation but don’t ask it to write too much *.idf ems or otherwise for ya :joy:

1 Like

Thank you very much @TrevorFedyna for your reply and time.

I tried the TrackFacilityElectricDemandStoreExcessOnSite but I noticed this is not the schedule that satisfies my objectives, since it does not work well with the schedules for charging/discharging. For example, during a specific time period (when electricity prices are low or demand is low), I want all the renewable generation to be stored in the storage.

I noticed when you set Design Maximum Continuous Input Power {W}, Ancillary Power Consumed In Standby {W}, and Radiative Fraction to zero for ElectricLoadCenter:Storage:Converter, the connection for getting electricity from the grid to be stored in the batteries will be zero and blocked.

With the below setup, my desired operation of interaction between battery, PV, and schedules is working:

ElectricLoadCenter:Storage:Converter,
Converter 1, !- Name
ALWAYS_ON, !- Availability Schedule Name (Use your existing schedule)
SimpleFixed, !- Power Conversion Efficiency Method
0.95, !- Simple Fixed Efficiency
0.0, !- Design Maximum Continuous Input Power {W}
, !- Efficiency Function of Power Curve Name
0.0, !- Ancillary Power Consumed In Standby {W}
, !- Zone Name
0.0; !- Radiative Fraction

Frankly speaking, the EMS is not for me, since the logic is not understandable to me, for the projects I have, like control and specific designs, I just set the IDF and use local EnergyPlus Python handler (since the pyenergyplus python EnergyPlus library is limited) to ignite the IDF during runtimes.

Thank you very much for your time and assistance.

Sincerely,
Behnam

1 Like