Skip to content

Standardize naming conventions #223

@elenya-grant

Description

@elenya-grant

Standardized naming conventions

Have a standardized and documented naming convention for model inputs and outputs given that a lot of logic relies on strings. This would include naming outputs in a specific way that indicate whether the output is a timeseries profile, an aggregated value, or a lifetime estimated value. Also would include naming conventions for not just the primary flow variables, but also the secondary inputs/outputs that may not be 'primary'. For example, the electrolyzer model has a primary timeseries input of an electricity profile and primary timeseries output of hydrogen. The electrolyzer consumes electricity (although may not consume all the electricity input) and consumes water. The consumption of water is not output from the model and not included in any financial calculations. The electrolyzer model could output results for the plant lifetime but does not at the moment.

Also - have a more standardized/automated method of understanding what technologies are connected to what commodities.

Proposed solution

General nomenclature:

  • commodity: commodities are produced or stored. A converter produces some commodity, a storage component stores some commodity
  • feedstock: feedstock(s) is/are consumed by a technology. A converter may be input one of many feedstock(s) to produce its commodity. This could also refer to ancillary equipment needs. A storage component may have a feedstock if it requires some input other than the storage commodity to operate.
  • resource: resource(s) is/are used by a technology. Such as a natural resource, refers to things that would be in plant_config['site'].

Standardized naming convention

Standardized model inputs/outputs could look like introducing a base class for different technology types (converters, storage, transporters, etc). At the very least, this should include documentation. Below is a draft of some possible naming conventions:

Converter Performance Models (commodity to commodity)

  • inputs:
    • possible design variables:

      • {technology}_capacity OR n_{technology_modules}
      • size_for_demand ?
    • timeseries:

      • {feedstock_a}_in OR {feedstock_a}_in_profile
      • {feedstock_b}_in OR {feedstock_b}_in_profile
      • {commodity}_demand perhaps? OR {commodity}_demand_profile
    • annual:

    • lifetime: ?

  • outputs:
    • timeseries (arrays of length n_timesteps):
      • {commodity}_out: timeseries of commodity production
      • {feedstock_a}_consumption_profile: timeseries of primary feedstock consumed
      • {feedstock_b}_consumption_profile: if used, timeseries of secondary feedstock consumed (only required for hourly prices for secondary feedstock)
    • totals (scalars):
      • max_{commodity}_production_possible: maximum amount of commodity that could be produced over the simulation if the converter was running at its rated capacity for the entire simulation. Should be representative of the converter's rated capacity.
      • total_{commodity}_produced: sum of {commodity}_out
      • capacity_factor: equal to total_{commodity}_produced/max_{commodity}_production_possible. Should be a value between 0 and 1.
      • total_{primary_feedstock}_consumed: sum of {primary_feedstock}_consumption_profile
      • total_{secondary_feedstock}_consumed: sum of {secondary_feedstock}_consumption_profile
    • lifetime (array of length plant_life):
      • annual_{commodity_out}_produced_per_year: can default to [total_{commodity}_produced*(8760*3600)/(n_timesteps*dt)]*plant_life if simulation is not completed for a whole year or [total_{commodity}_produced]*plant_life if simulation is equal to one year.
      • annual_{primary_feedstock}_consumed_per_year (if relevant)
      • annual_{secondary_feedstock}_consumed_per_year (if relevant)
      • time_until_replacement: can default to plant_life. Wouldn't be included in financials unless replacement_cost_percent is included in tech-specific finance parameters under capex.

storage

  • inputs:
    • possible design variables:
      • {technology}_charge_rate AND {technology}_{capacity}
    • timeseries:
      • {commodity}_in: available input to use for charging
      • {commodity}_demand: reference signal
    • annual:
    • lifetime:
  • outputs:
    • timeseries:
      • {commodity}_out
      • {commodity}_excess
      • {commodity}_missed_load
      • {technology}_SOC
      • {technology}_discharged
      • {technology}_charged
    • annual:
    • lifetime:

Standardized method of connecting technologies and commodities or dealing with models with tech-specific finance models

Add the following dictionaries to supported_models.py:

commodity_to_model_kwargs = {
    "hydrogen": ["electrolyzer", "geoh2", "h2_storage", "wombat", "hydrogen_tank"],
    "steel": ["steel"],
    "methanol": ["methanol", "smr"],
    "ammonia": ["ammonia"],
    "nitrogen": ["air_separator", "asu"],
    "co2": ["doc", "direct_ocean_capture"],
    "electricity": ["wind", "solar", "pv", "river", "hydro", "hopp"],
    "water": ["desal", "desalination"],
}

commodity_to_common_units = {
    "hydrogen": "kg",
    "steel": "t",  # metric ton
    "ammonia": "",
    "nitrogen": "kg",
    "co2": "kg",
    "electricity": "kW*h",
    "water": "kg",
}

independent_financial_models = [
    "steel_cost",
    "stimulated_geoh2_financial",
    "natural_geoh2_financial",
    "methanol_plant_financial",
]

Including some new utility/tool functions like this:

from h2integrate.core.supported_models import commodity_to_model_kwargs


def make_model_kwarg_to_commodity():
    model_kwargs_to_commodity = {}
    for commodity, tech_kwargs in commodity_to_model_kwargs.items():
        model_kwargs_to_commodity.update({tech_kw: commodity for tech_kw in tech_kwargs})
    return model_kwargs_to_commodity


def get_commodities_for_tech_keywords(finance_group_tech_config: dict):
    model_kwargs_to_commodity = make_model_kwarg_to_commodity()
    commodity_types = []
    for tech_name in finance_group_tech_config.keys():
        commodity = [v for k, v in model_kwargs_to_commodity.items() if tech_name.lower() in k]
           
        if len(commodity) > 0:
            commodity_types.append(commodity[0])
        else:
            msg = (
                f"Technology {tech_name} name has unrecognized commodity type."
                "Please check `commodity_to_model_kwargs` in "
                "h2integrate/core/supported_models.py to find valid technology keywords."
            )
            raise ValueError(msg)
    unique_commodity_types = list(set(commodity_types))
    return unique_commodity_types

Then adjusting the logic within h2integrate/core/h2integrate_model.py to not rely on technology names in tech_config (ex: tech_config.keys()) but to instead look at the strings used for the models (ex: tech_config['electrolyzer']['cost_model']['model']). For example, in create_financial_model():

for group_id, tech_configs in financial_groups.items():
     commodity_types = get_commodities_for_tech_keywords(tech_configs)

could replace

for group_id, tech_configs in financial_groups.items():
     if "steel" in tech_configs:
          commodity_types.append("steel")
     if "electrolyzer" in tech_configs:
          commodity_types.append("hydrogen")
     ...

We could also replace some hard-coded logic about either individual finance models or coupled cost/finance models like this:

    if any(c in commodity_types for c in ("steel", "methanol")):
        continue

    # GeoH2 provides own financials
    if "geoh2" in tech_configs:
        continue

to be this:

# Check for individual financial model
coupled_cost_finance = any(
    tech_info.get("cost_model", {}).get("model", False) in independent_financial_models
    for tech, tech_info in tech_configs.items()
)
individual_finance = any(
    tech_info.get("financial_model", {}).get("model", False)
    in independent_financial_models
    for tech, tech_info in tech_configs.items()
)
if coupled_cost_finance or individual_finance:
    continue

Alternatives considered

Additional context

This was partially discussed/addressed in PR #198.
Related to Issue #231

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions