Example usage - simple battery model#2
Conversation
…en(pyomo_var) in get_energy_charges.
There was a problem hiding this comment.
Pull Request Overview
This PR adds support for handling fixed charges in the charge DataFrame, provides an example tariff CSV, and introduces a simple Pyomo-based battery model example.
- Updated
get_charge_dfto optionally distribute or drop fixed charges. - Added an example tariff (
tariff.csv) demonstrating typical time-of-use blocks. - Introduced
examples/battery_model.py, a runnable Pyomo battery storage model example.
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| examples/battery_model.py | New example class for time-discretized Pyomo battery model |
| electric_emission_cost/data/tariff.csv | Sample tariff data including fixed and time-of-use charges |
| electric_emission_cost/costs.py | Enhanced get_charge_df to handle fixed charges and updated step count logic in cost calculation |
Comments suppressed due to low confidence (4)
examples/battery_model.py:112
- [nitpick] Consider renaming
power_Candpower_Dtopower_chandpower_dis(or lowercase snake_case) for consistency with other variable names.
model.power_C = Var(model.t, bounds=(0, self.powercapacity), initialize=0, doc="Charging power")
electric_emission_cost/data/tariff.csv:2
- The tab (
\t) between the two URLs may break CSV parsing; consider quoting the entireNotesfield or splitting into separate columns.
electric,customer,,,,,,,,,,,666.65,666.65,$/month,https://www.pnm.com/...pdf/…\thttps://www.pnm.com/rates2
electric_emission_cost/costs.py:339
- The variable
datetimeshadows thedatetimemodule alias (dt); rename this DataFrame to e.g.datetime_dffor clarity.
datetime = pd.DataFrame(
electric_emission_cost/costs.py:304
- New
keep_fixed_chargesbehavior should have unit tests covering both branches (True/False) and verifying charge distribution or removal.
def get_charge_df(start_dt, end_dt, rate_data, resolution="15m", keep_fixed_charges=False):
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. Thanks for integrating Codecov - We've got you covered ☂️ |
remove unnecessary imports and adding docs. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
fletchapin
left a comment
There was a problem hiding this comment.
A couple of minor questions or changes, but overall looks good!
|
|
||
| def get_charge_df(start_dt, end_dt, rate_data, resolution="15m"): | ||
| def get_charge_df( | ||
| start_dt, end_dt, rate_data, resolution="15m", keep_fixed_charges=False |
There was a problem hiding this comment.
I think the default behavior should be to keep the fixed charges (i.e., keep_fixed_charges =True not False) but otherwise this seems like a good feature. Is there a reason to go through the effort of dividing the fixed charge over the length of the array? Maybe it could be useful and I've just never computed them in that way
There was a problem hiding this comment.
That makes sense! I figured it was either that or assign it to time step 0 and make the rest of the time steps 0 value. Either way, we need an array of length T to build the data frame.
| if model is None: | ||
| n_steps = consumption_data.shape[0] | ||
| else: # Pyomo does not support shape attribute | ||
| n_steps = len(consumption_data.extract_values()) |
There was a problem hiding this comment.
Did extract_values() throw an error or do you just think it is unnecessary?
| This class models the behavior of a battery system operating on the site of an industrial power consumer. | ||
| It uses time-discretized simulation to optimize battery usage based on input parameters and baseline load data. | ||
|
|
||
| Parameters: |
There was a problem hiding this comment.
nit: I usually add format the docstring like this to ensure they format correctly with Sphinx:
Parameters
-----------
params (dict): A dictionary of model parameters. Expected keys include:
- 'start_date' (str): The start date of the simulation in ISO format (e.g., 'YYYY-MM-DDTHH:MM:SS').
- 'end_date' (str): The end date of the simulation in ISO format.
- 'timestep' (float): The time step for the simulation in hours.
(Additional keys may be required depending on the specific model configuration.)
baseload (array-like): The baseline load profile for the site, provided as a time series.
baseload_repeat (bool, optional): If True, the baseline load profile is repeated to match the simulation period.
Defaults to False.
* Update costs.py * update index_set * fix lint * lint #2 * Update costs.py * test fixes * black * remove gurobi and use scip * Update setup.py * Update setup.py * change scip install * update costs * remove gurbi dept * update test runs * Update test_and_lint.yml * Update test_and_lint.yml * Update test_and_lint.yml * Update test_and_lint.yml * Update test_and_lint.yml * black * Update test_and_lint.yml * Update test_and_lint.yml * Update utils.py * Added overwrite flag with warning to create_pyomo_model_index_ref * Autoreformatted with black * fixed util/emission tests * missed check * lint * dumb lint * Update costs.py * names/bug * blk * add explicti indexed * blk * Updated model.t to model.dummy_t to check for edge cases implicitly relying on old model.t * Switching docstrings to NumPy format (from Google) * fix tests * Update utils.py * Resolvd flake8 errors --------- Co-authored-by: Fletcher Chapin <fletchapin@gmail.com>
Changes
electric_emission_cost/costs.py: updatedget_charge_dffunction to handle fixed charges.electric_emission_cost/data/tariff.csv: included example tariffexamples/battery_model.py: include simple system model of an electric battery that is applied to a sinusoidal industrial load. The class is built in pyomo. Future versions should include a cvxpy example.examples/example_pyomo_jupyter.ipynb: includes a Jupyter notebook that details the steps in obtaining charge arrays from the tariff and adding them to the pyomo battery model.