Starting structure for OM refactor - #92
Conversation
…olyzer into om_refactor/structure
…rolyzer into om_refactor/structure
johnjasa
left a comment
There was a problem hiding this comment.
Some initial thoughts and comments from me! I'm liking what I'm seeing, especially with the care you've put to introducing base classes and then having smart inheritance. The similarities between the structure you've chosen here and H2I is fun to see, as well as the differences since we're tackling slightly different problems.
Nothing blocking, though I am treating this PR as part of a larger refactor effort so I'm not being picky about docstrings, etc. Glad you're able to push through some great progress here!
| def initialize(self): | ||
| super().initialize() | ||
| # self.options.declare("mode", types=str, default="normal") | ||
|
|
||
| def setup(self): | ||
| # self.n = 2 # number of electrons transferred in reaction | ||
|
|
||
| self.config = PEMCellConfig.from_dict(self.options["tech_config"]["cell_parameters"]) | ||
|
|
||
| super().setup() | ||
|
|
||
| # self.add_input("H2_demand", val=0.0, shape_by_conn=True, units="g/s") | ||
| # self.add_output("I_demand", val=0.0, copy_shape="H2_demand", units="A") | ||
| # self.add_output("J_demand", val=0.0, copy_shape="H2_demand", units="A/(cm**2)") |
There was a problem hiding this comment.
remove commented code? or is useful for later?
There was a problem hiding this comment.
this is removed in the follow-on PR I think?
There was a problem hiding this comment.
maybe rename to cell_baseclass.py? not necessary
There was a problem hiding this comment.
I'm guessing you're going to be fleshing this out more later on, but I still think it'd be worthwhile to have a docstring or two in here explaining the very basics of the simple dynamics class, what it does, potential applications for it
| outputs[o_name] = inputs[in_name] / inputs["n_stacks"] | ||
|
|
||
|
|
||
| class ScaleUp(om.ExplicitComponent): |
There was a problem hiding this comment.
These two classes are named very broadly; is this on purpose? Will these be used in multiple different contexts, or could we name them more clearly to say at what level they'd be used, e.g. "stack to cluster" or whatever it is?
There was a problem hiding this comment.
removed the building blocks file
|
|
||
|
|
||
| class ScaleUp(om.ExplicitComponent): | ||
| """Scale things down""" |
| class Draft(om.ExplicitComponent): | ||
| def initialize(self): | ||
| self.options.declare("tech_config", types=dict, default={}) | ||
|
|
||
| def setup(self): | ||
| pass | ||
|
|
||
| def compute(self, inputs, outputs): | ||
| pass |
There was a problem hiding this comment.
sorry I meant to delete the entire building_blocks.py file!
| A_cell: float = field(validator=(validators.gt(0.0))) | ||
|
|
||
|
|
||
| class CurrentBoundsBase(om.ExplicitComponent): |
There was a problem hiding this comment.
Tell me about this component; its name/docstring/filename doesn't make it immediately clear to me what it's doing or where it's used
There was a problem hiding this comment.
It supplies the min/max current bounds to the dynamics component (and would likely send these to the controller). It also calculates a bunch of current reference points from min to max for the curve-fitting.
| # Step 1: Create controller cluster connector components | ||
| pre_translator = self.create_controller_cluster_connector() | ||
| # Translator has scale down + power to current conversion | ||
| translator = self.create_controller_translator() | ||
| # Step 2: Create the simulate block of a cluster | ||
| simulator = self.create_cluster_simulation_block() | ||
|
|
||
| cluster_group.add_subsystem( | ||
| "converter", pre_translator, promotes=["A_cell", "I_min", "I_max"] | ||
| ) | ||
| cluster_group.add_subsystem("translator", translator, promotes=["n_stacks", "n_cells"]) | ||
| cluster_group.add_subsystem("simulation", simulator, promotes=["I_min", "I_max", "A_cell"]) |
There was a problem hiding this comment.
I'm not necessarily sold on the translator and converter terms. Is there something where we could call it static_design or pre_simulation or something else? It could be more clear what those names mean
There was a problem hiding this comment.
I'm not sold on them either. I did have it the "converter" called the "pre-translator" at one point. I don't think I'm sold on the static_design name. I did make an issue about the naming in general and started brainstorming some new names for the classes here #100
| cell_scale_down = self.create_scale_down_component( | ||
| scale_comp="cells", n_comps=self.config["stack"]["n_cells"] | ||
| ) | ||
| stack_scale_down = self.create_scale_down_component( | ||
| scale_comp="stacks", n_comps=self.config["cluster"]["n_stacks"] | ||
| ) | ||
|
|
||
| translator.add_subsystem( | ||
| "cluster_to_stack", | ||
| stack_scale_down, | ||
| promotes_inputs=["n_stacks"], | ||
| ) | ||
| translator.add_subsystem( | ||
| "stack_to_cell", | ||
| cell_scale_down, | ||
| promotes_inputs=["n_cells"], | ||
| ) |
There was a problem hiding this comment.
Right on, I see how the scale components are used now, please mostly disregard my prior comment. I do still think when you get to documenting the components it'd be useful to include a few examples of where they'd be used in the docstring so folks understand where you'd be scaling up or down
Starting structure for OM refactor
This PR requires PR #90 to be merged in!
This PR introduces a different structure of the functionality within the electrolyzer repo to accommodate an Open-MDAO structure. This is in a somewhat intermediate state so that future development has smaller PRs and can have more rigorous testing and a focus on individual component development. This PR really focuses on the structure for the "cluster" and the connection from a cluster to a controller. The "controller" right now is just an
IndepVarCompbecause the structure is only set-up to handle one cluster at the moment. The cluster is comprised of 3 main subgroups:converter: perhaps this should be renamed to "pre_translator". This defines the current operational bounds and also is used to get curve coefficients for the power-to-current conversion.translator: this is used to take a cluster input power signal and convert it to the cell-level current inputsimulation: this takes the cell-level current input and simulates cell degradation, includes dynamic operating constraints, and simulates the cell performance.Plans for follow-on PRs:
Files to Remove (were helper/drafts):
electrolyzer/translators/power_translator_baseclass.pyelectrolyzer/core/simulate_structure.pyelectrolyzer/core/pre_processing_structure_v2.pyRelated issue, if one exists
Impacted areas of the software
Additional supporting information
Test results, if applicable