Skip to content

Reorganize component name and type#216

Merged
genevievestarke merged 43 commits intoNatLabRockies:developfrom
paulf81:feature/clean_up_type
Mar 4, 2026
Merged

Reorganize component name and type#216
genevievestarke merged 43 commits intoNatLabRockies:developfrom
paulf81:feature/clean_up_type

Conversation

@paulf81
Copy link
Copy Markdown
Collaborator

@paulf81 paulf81 commented Feb 26, 2026

This pull request is meant to address Issue #207. The main points are to:

  1. Clarify the usage and purpose of component_name and component_type
  2. Facilitate allowing multiple instances of the same type of component
  3. Maintain backward compatibility

This PR accomplished this via:

  1. Changing component_name to be a unique identifier that can be any string. It's backwards-compatible since it is still defined as the YAML top level key and the names for example in the examples like wind_farm still work since there is only one thing called wind_farm in those examples
  2. Keeping component_type to represent the specific class use to define the unit, however making that more explicit by automatically defining the type in the ComponentBase using the __name__ method
  3. Adding a component_category that captures what the component_name used to represent. These are class attributes defined at least in each base class and then optionally in subclasses

Then also the following organization steps are taken:

  • All components and base classes updated around this new pattern
  • Components now require a component_name to be passed in. This is a smallish change handled mainly by HybridPlant but all tests of the components themselves need this added.
  • HybridPlant updated to use these more explicit variables
  • utilities.py simplified since many of the types/classes are kept within HybridPlant
  • A few additional tests added for the new features
  • Documentation updated

@paulf81 paulf81 marked this pull request as ready for review February 26, 2026 22:44
@paulf81 paulf81 self-assigned this Feb 26, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 addresses Issue #207 by formalizing the distinction between component_name (user-chosen unique YAML key), component_type (class selector), and a new component_category (broad grouping used for generator/battery behavior). It updates HybridPlant and input loading to support multiple instances of the same component type while preserving existing single-instance YAML conventions.

Changes:

  • Introduces component_category on component classes and auto-derives component_type from the concrete Python class name in ComponentBase.
  • Updates HybridPlant and load_hercules_input to discover components by presence of a component_type field, enabling multi-instance components.
  • Updates tests and documentation to pass component_name into component constructors and to document the new naming/type/category model.

Reviewed changes

Copilot reviewed 35 out of 35 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/wind_farm_scada_power_test.py Updates WindFarmSCADAPower tests to pass component_name into constructor.
tests/wind_farm_precom_floris_test.py Updates WindFarm tests to pass component_name into constructor.
tests/wind_farm_dynamic_floris_test.py Updates WindFarm dynamic-mode tests for new constructor signature.
tests/wind_farm_direct_test.py Updates WindFarm direct-mode tests for new constructor signature.
tests/utilities_test.py Aligns expected loader error message for invalid component_type.
tests/thermal_component_base_test.py Updates ThermalComponentBase tests for new constructor signature.
tests/solar_pysam_pvwatts_test.py Updates SolarPySAMPVWatts tests for new constructor signature.
tests/regression_tests/solar_pysam_pvwatts_regression_test.py Updates regression test to pass component_name.
tests/regression_tests/electrolyzer_plant_regression_test.py Updates regression test to pass component_name.
tests/regression_tests/battery_regression_test.py Updates regression tests to pass component_name.
tests/open_cycle_gas_turbine_test.py Updates OpenCycleGasTurbine tests for new constructor signature.
tests/hybrid_plant_test.py Adds tests for component_category, auto-set component_type, and multi-instance batteries.
tests/electrolyzer_plant_test.py Updates ElectrolyzerPlant tests for new constructor signature.
tests/battery_simple_test.py Updates battery tests for new constructor signature.
hercules/utilities.py Simplifies component validation and discovers components by component_type; adds a global valid-type list.
hercules/plant_components/wind_farm_scada_power.py Adds component_category and requires component_name argument.
hercules/plant_components/wind_farm.py Adds component_category and requires component_name argument; uses name param early for config read.
hercules/plant_components/thermal_component_base.py Switches from fixed name/type to component_category + component_name param.
hercules/plant_components/solar_pysam_pvwatts.py Requires component_name and relies on base to set component_type.
hercules/plant_components/solar_pysam_base.py Adds component_category and replaces hard-coded h_dict keys with self.component_name in metadata.
hercules/plant_components/open_cycle_gas_turbine.py Requires component_name and removes fixed name/type class attributes.
hercules/plant_components/electrolyzer_plant.py Adds component_category and requires component_name argument.
hercules/plant_components/component_base.py Enforces component_category on subclasses and auto-derives component_type.
hercules/plant_components/battery_simple.py Adds component_category and requires component_name argument (no hard-coded name/type).
hercules/plant_components/battery_lithium_ion.py Adds component_category and requires component_name argument (no hard-coded name/type).
hercules/hybrid_plant.py Adds a component registry; discovers components by component_type; generator classification via component_category; battery sign logic via category.
docs/solar_pv.md Updates YAML instructions to reflect component_name vs component_type and links to new doc.
docs/open_cycle_gas_turbine.md Documents YAML usage with user-chosen component_name and component_type.
docs/hybrid_plant.md Updates component discovery explanation and adds type/category/generator classification table.
docs/hercules_input.md Updates input structure docs to allow arbitrary component section keys with component_type.
docs/h_dict.md Updates h_dict docs to reflect auto-discovery and adds OCGT section.
docs/electrolyzer.md Updates YAML instructions to reflect component_name vs component_type.
docs/component_types.md Adds new reference doc defining component_name, component_type, and component_category.
docs/battery.md Clarifies YAML component_name convention for batteries in docs.
docs/_toc.yml Adds component_types page to documentation TOC.

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

Comment on lines 64 to +67
self.wake_method = wake_method

# Store the type of this component (for backward compatibility)
component_type = h_dict[self.component_name].get("component_type", "WindFarm")
self.component_type = component_type

# Call the base class init
super().__init__(h_dict, self.component_name)
# Call the base class init (sets self.component_name and self.component_type)
super().__init__(h_dict, component_name)
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

WindFarm now accepts an explicit component_name for multi-instance support, but get_initial_conditions_and_meta_data() still writes to h_dict["wind_farm"] (hard-coded key). That will break/clobber metadata when the instance name is not exactly "wind_farm". Please switch those updates to use h_dict[self.component_name] instead of the literal key (and similarly for the optional starttime_utc field).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@paulf81 is this and the similar one below now resolved?

Comment on lines 23 to +25
"""
# Store the name of this component
self.component_name = "wind_farm"

self.component_type = "WindFarmSCADAPower"

# Call the base class init
super().__init__(h_dict, self.component_name)
# Call the base class init (sets self.component_name and self.component_type)
super().__init__(h_dict, component_name)
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

WindFarmSCADAPower now supports a user-chosen component_name, but get_initial_conditions_and_meta_data() still writes to h_dict["wind_farm"] (hard-coded key). This breaks multi-instance support (e.g., "wind_farm_2") and can overwrite another component’s metadata. Update those assignments to use h_dict[self.component_name] consistently.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch!

Comment thread hercules/utilities.py Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 36 changed files in this pull request and generated no new comments.


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

@misi9170
Copy link
Copy Markdown
Collaborator

I'll need to check whether this affects Hycon. At this stage, supervisory controllers in Hycon can only accept a single of each type of component (e.g. a single wind farm). Updating that will be a bit more complicated, but for now I'll just plan to see what (if any) updates I'll need to make in Hycon for this update.

@paulf81
Copy link
Copy Markdown
Collaborator Author

paulf81 commented Feb 27, 2026

I'll need to check whether this affects Hycon. At this stage, supervisory controllers in Hycon can only accept a single of each type of component (e.g. a single wind farm). Updating that will be a bit more complicated, but for now I'll just plan to see what (if any) updates I'll need to make in Hycon for this update.

Thanks @misi9170, maybe it's hopeful to point out these changes didn't necessitate any changes to the examples since "wind_farm" is still for example an acceptable name

@misi9170
Copy link
Copy Markdown
Collaborator

@paulf81 , thanks, and you're right, looks like Hycon is indeed unaffected :)

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 36 changed files in this pull request and generated 4 comments.


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

Comment thread hercules/utilities.py Outdated
Comment thread hercules/plant_components/battery_simple.py Outdated
Comment thread hercules/plant_components/battery_lithium_ion.py Outdated
Comment thread hercules/plant_components/component_base.py
Copy link
Copy Markdown
Collaborator

@misi9170 misi9170 left a comment

Choose a reason for hiding this comment

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

Overall this looks good to me. I've made a couple of documentation suggestions for you to conisder @paulf81 , and I will take a look at why github is treating the two battery files as having completely changed and see if I can fix that.

Comment thread docs/adding_components.md Outdated
Comment thread hercules/utilities.py
Comment thread hercules/plant_components/battery_lithium_ion.py
Comment thread hercules/hybrid_plant.py
if cls is None:
raise ValueError(
f"Unknown component_type '{component_type}' for component '{component_name}'. "
f"Available types: {sorted(COMPONENT_REGISTRY)}"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Perhaps here we could also say something like: if you are adding a new component, please update the COMPONENT_REGISTRY. But maybe that's too much information for someone that, 9 times out of 10, just has a typo in their input file.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I guess this error only gets raised if users don't use load_hercules_input() to create the initial h_dict. That's enough of an edge case that we probably don't need to update this error.

@misi9170
Copy link
Copy Markdown
Collaborator

misi9170 commented Mar 2, 2026

@paulf81 I think I've now fixed the battery file diffs. Can you just take a quick look over them and make sure I didn't miss any changes needed (tests all pass, and were helpful because there were some differences I'd missed!).

I'm still not sure what happened there, so there's a chance it happens again. Hopefully not.

@paulf81
Copy link
Copy Markdown
Collaborator Author

paulf81 commented Mar 2, 2026

@paulf81 I think I've now fixed the battery file diffs. Can you just take a quick look over them and make sure I didn't miss any changes needed (tests all pass, and were helpful because there were some differences I'd missed!).

I'm still not sure what happened there, so there's a chance it happens again. Hopefully not.

It looks good to me @misi9170 ! Checked the two battery files and they matched my expectations

Comment thread docs/component_types.md Outdated
paulf81 and others added 2 commits March 2, 2026 13:45
@genevievestarke genevievestarke linked an issue Mar 3, 2026 that may be closed by this pull request
Comment thread docs/adding_components.md Outdated
- [hybrid_plant.md](hybrid_plant.md) — Available Components table
- [component_types.md](component_types.md) — Complete Component Type Reference table

## Testing
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is personal preference, but I usually put testing in with developing the model. Thoughts on moving it up?

Comment thread docs/adding_components.md
pytest tests/my_component_test.py -v
```

## Summary Checklist
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is a great summary!!

@genevievestarke genevievestarke merged commit 2cb1ef7 into NatLabRockies:develop Mar 4, 2026
3 checks passed
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.

Clean up component name and component type definitions

4 participants