Skip to content

Feature Branch for MPPOC Data Centers#106

Draft
dzalkind wants to merge 16 commits into
NatLabRockies:developfrom
dzalkind:feature/mppoc_dcs
Draft

Feature Branch for MPPOC Data Centers#106
dzalkind wants to merge 16 commits into
NatLabRockies:developfrom
dzalkind:feature/mppoc_dcs

Conversation

@dzalkind

@dzalkind dzalkind commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Working branch for team to push updates for working together on multi-level control.

We can use this as a shared working/discussion space.

In general, most things should be pushed to mppoc_data_center_sim, but some things make more sense in hycon long term:

  • Generic controllers for individual plant components
  • Any updates needed to Hycon to enable simulations (e.g. modifications to the HerculesInterface)

@misi9170 misi9170 marked this pull request as draft June 12, 2026 17:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds new controller utilities and expands Hercules v2 integration to better support MPPOC-style simulations (notably thermal plant handling, filtering utilities, and supervisory controller features).

Changes:

  • Added a reusable LowPassFilter utility (with new tests) and introduced SciPy as a dependency.
  • Extended HerculesInterface to recognize ThermalPlant, add battery roundtrip_efficiency, and apply a default setpoint for uncontrolled components.
  • Enhanced HybridSupervisoryControllerGeneric with minimum-power constraints and storage charging availability propagation; added a new ThermalPlantController.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tests/controller_utilities_test.py Adds unit tests for the new low-pass filter utility.
pyproject.toml Adds SciPy dependency required by signal conditioning utilities.
hycon/interfaces/hercules_interface.py Extends Hercules v2 component support (thermal plant params, battery efficiency, default controls).
hycon/controllers/thermal_plant_controller.py Introduces a new controller for thermal plant power setpoints.
hycon/controllers/signal_conditioning.py Introduces LowPassFilter implemented via SciPy.
hycon/controllers/hybrid_supervisory_controller.py Adds minimum-power handling and storage charging availability propagation.
hycon/controllers/controller_base.py Makes controller parameter checking tolerant of None.
hycon/controllers/__init__.py Exposes the new ThermalPlantController at the package level.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +79 to +87
self.plant_parameters[c] = {
"type": "thermal",
"component_category": "generator",
"P_min": h_dict[c]["min_stable_load_fraction"] * h_dict[c]["rated_capacity"],
"P_max": h_dict[c]["rated_capacity"],
"ramp_rate": h_dict[c]["ramp_rate_fraction"]
* h_dict[c]["rated_capacity"]
/ 60.0,
}
Comment on lines +194 to +196
else:
# Set a safe default power_setpoint for components without controllers
h_dict[c].setdefault("power_setpoint", 0.0)
Comment on lines +49 to +53
def set_controller_parameters(
self,
component_controllers=[],
curtailment_order=None,
minimum_power=None,
Comment on lines +104 to +117
# Check valid minimum_power
if minimum_power is None:
# Default is reverse order of component_controllers
self.minimum_power = np.zeros_like(component_controllers)
elif len(minimum_power) != len(component_controllers):
raise ValueError("minimum_power must be the same length as component_controllers.")
elif not all([isinstance(c, (float, int)) and c >= 0 for c in minimum_power]):
raise ValueError(
"All entries in minimum_power must be non-negative floats or integers corresponding"
" to indices of component_controllers."
)
else:
self.minimum_power = minimum_power

Comment on lines 182 to +186
for cidx in self.curtailment_order[::-1]:
cc = self.component_controllers[cidx]

if cc.plant_parameters[cc.cname]["component_category"] == "generator":
power_reference_component = power_reference_with_storage - power_export_total
power_reference_component = max(
Comment on lines +46 to +47
def compute_controls(self, measurements_dict):
return {self.cname: {"power_setpoint": measurements_dict[self.cname]["power_reference"]}}
Comment on lines +24 to +29
# Check DC gain of the filter is 1, raise warning if not
if a[-1] != b[-1]:
print(
"Warning: DC gain of the low-pass filter is not 1. "
"This will lead to a steady-state scaling of the reference trajectory."
)
@dzalkind

Copy link
Copy Markdown
Collaborator Author

I accidentally triggered Copilot. We can disregard for now or delete to remove the noise. My bad.

@misi9170

misi9170 commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

@jfrederik-nrel @dzalkind I've added some utilities for signal conditioning in hycon/controllers/signal_conditioning.py. At first, I formulated them as controllers that inherited from ControllerBase, but in the end I think it's better to leave them as simple classes that we can just use within different controllers as needed.

Currently included are:

  • Generic low-pass SISO filter (which should be specified using continuous-time numerator and denominator polynomials for the transfer function)
  • Rate limiter
  • Saturation

You can see how they are each set up and called in tests/controller_utilities_tests.py.

@jfrederik-nrel , I think I'll now see if I can refactor the BatteryController to use these utilities, as a demonstration of how they might be used (but hopefully not actually change the response of BatteryController :) )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants