From b6de7705386c11c12cc854dc5eaa17d959e6a324 Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Mon, 27 Apr 2026 12:41:58 -0700 Subject: [PATCH 01/40] add unintegrated, working EIA API data querier --- h2integrate/resource/ng_price.py | 169 +++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 h2integrate/resource/ng_price.py diff --git a/h2integrate/resource/ng_price.py b/h2integrate/resource/ng_price.py new file mode 100644 index 000000000..a3210e0b8 --- /dev/null +++ b/h2integrate/resource/ng_price.py @@ -0,0 +1,169 @@ +import json +from pathlib import Path +from datetime import datetime + +import attrs +import pandas as pd +import requests +from attrs import field, define + +from h2integrate.core.utilities import BaseConfig +from h2integrate.core.file_utils import get_path + + +STATES = states = [ + "AL", + "AK", + "AZ", + "AR", + "CA", + "CO", + "CT", + "DC", + "DE", + "FL", + "GA", + "HI", + "ID", + "IL", + "IN", + "IA", + "KS", + "KY", + "LA", + "ME", + "MD", + "MA", + "MI", + "MN", + "MS", + "MO", + "MT", + "NE", + "NV", + "NH", + "NJ", + "NM", + "NY", + "NC", + "ND", + "OH", + "OK", + "OR", + "PA", + "RI", + "SC", + "SD", + "TN", + "TX", + "UT", + "VT", + "VA", + "WA", + "WV", + "WI", + "WY", +] +CURRENT_YEAR = datetime.now().year + + +def get_eia_api_key(filename: Path) -> str: + """Retrieves the EIA API key from a file, and returns the key following "EIA_API_KEY:". + + Args: + filename (Path): Full file path and name of where the EIA API key is located. Must be + encoded as "EIA_API_KEY: xxxxxx" + + Returns: + str: The EIA API key. + """ + with filename.open() as f: + for line in f.readlines(): + if ":" in line: + name, val = line.strip().split(":") + if name == "EIA_API_KEY": + return val.strip() + + +@define +class EIAIndustrialNaturalGasConfig(BaseConfig): + """EIA Industrial Natural Gas Pricing API Configuration. + + Args: + state (str): Two-letter, upper case state abbreviation. Must be one of the 50 U.S. states. + resource_year (int): The YYYY-format year whose data should be retrieved. Must be between + 2001 and the current year, inclusive of endpoints. + monthly (Path): True, if monthly data is desired, False if annual data is desired. + api_key_file (Path): Full file name of the file where the API key is located. + """ + + state: str = field( + converter=str.upper, + validator=attrs.validators.in_(STATES), + ) + resource_year: int = field(validator=attrs.validators.in_(range(2001, CURRENT_YEAR + 1))) + monthly: bool = field(validator=attrs.validators.instance_of(bool)) + api_key_file: str = field(converter=get_path) + + +class EIAIndustrialNaturalGasResource: + """Create the class.""" + + def __init__(self, resource_config: dict): + # self.setup() + self.config = EIAIndustrialNaturalGasConfig.from_dict( + # self.options["resource_config"], + resource_config, + additional_cls_name=self.__class__.__name__, + ) + self.url = self.create_url() + + # def initialize(self): + # self.options.declare("plant_config", types=dict) + # self.options.declare("resource_config", types=dict) + # self.options.declare("driver_config", types=dict) + + def create_url(self): + base_url = "https://api.eia.gov/v2/natural-gas/pri/sum/data/" + frequency = f"frequency={'monthly' if self.config.monthly else 'annual'}" + data = "data[0]=value" + facet = f"facets[series][]=N3035{self.config.state}3" + start = f"start={self.config.resource_year}" + end = f"end={self.config.resource_year}" + if self.config.monthly: + start = f"{start}-01" + end = f"{start}-12" + sort_col = "sort[0][column]=period" + sort_dir = "sort[0][direction]=asc" + api_key = f"api_key={get_eia_api_key(self.config.api_key_file)}" + + url_opts = "&".join((frequency, data, facet, start, end, sort_col, sort_dir, api_key)) + url = f"{base_url}?{url_opts}" + return url + + def setup(self): + # Define inputs and outputs + self.config = EIAIndustrialNaturalGasConfig.from_dict( + self.options["resource_config"], + additional_cls_name=self.__class__.__name__, + ) + # site_config = self.options["plant_config"]["site"] + + # self.add_input("latitude", site_config.get("latitude", 0.0), units="deg") + # self.add_input("longitude", site_config.get("longitude", 0.0), units="deg") + # self.add_output("discharge", shape=8760, val=0.0, units="ft**3/s") + + def load_data(self, filename: str | Path | None = None): + # download_from_api(self.url, filename) + r = requests.get(self.url) + if r.status_code != 200: + err = json.loads(r.text)["error"] + msg = f"{err['code']}: {err['message']}" + raise requests.exceptions.HTTPError(msg) + + cols = ["period", "area-name", "value", "units"] + df = pd.DataFrame.from_dict(json.loads(r.text)["response"]["data"])[cols] + df.period = pd.to_datetime(df.period) + + if filename is not None: + df.to_csv(filename, index=False) From f0898f5f45ed8b77ad4111017f8c8e58fa5dcf22 Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Mon, 27 Apr 2026 14:52:37 -0700 Subject: [PATCH 02/40] probably working integration into H2I --- h2integrate/resource/ng_price.py | 206 +++++++++++++++++++------------ 1 file changed, 129 insertions(+), 77 deletions(-) diff --git a/h2integrate/resource/ng_price.py b/h2integrate/resource/ng_price.py index a3210e0b8..d5d8643de 100644 --- a/h2integrate/resource/ng_price.py +++ b/h2integrate/resource/ng_price.py @@ -11,59 +11,65 @@ from h2integrate.core.file_utils import get_path -STATES = states = [ - "AL", - "AK", - "AZ", - "AR", - "CA", - "CO", - "CT", - "DC", - "DE", - "FL", - "GA", - "HI", - "ID", - "IL", - "IN", - "IA", - "KS", - "KY", - "LA", - "ME", - "MD", - "MA", - "MI", - "MN", - "MS", - "MO", - "MT", - "NE", - "NV", - "NH", - "NJ", - "NM", - "NY", - "NC", - "ND", - "OH", - "OK", - "OR", - "PA", - "RI", - "SC", - "SD", - "TN", - "TX", - "UT", - "VT", - "VA", - "WA", - "WV", - "WI", - "WY", -] +STATE_MAP = states = { + "Alabama": "AL", + "Alaska": "AK", + "Arizona": "AZ", + "Arkansas": "AR", + "California": "CA", + "Colorado": "CO", + "Connecticut": "CT", + "Delaware": "DE", + "Florida": "FL", + "Georgia": "GA", + "Hawaii": "HI", + "Idaho": "ID", + "Illinois": "IL", + "Indiana": "IN", + "Iowa": "IA", + "Kansas": "KS", + "Kentucky": "KY", + "Louisiana": "LA", + "Maine": "ME", + "Maryland": "MD", + "Massachusetts": "MA", + "Michigan": "MI", + "Minnesota": "MN", + "Mississippi": "MS", + "Missouri": "MO", + "Montana": "MT", + "Nebraska": "NE", + "Nevada": "NV", + "New Hampshire": "NH", + "New Jersey": "NJ", + "New Mexico": "NM", + "New York": "NY", + "North Carolina": "NC", + "North Dakota": "ND", + "Ohio": "OH", + "Oklahoma": "OK", + "Oregon": "OR", + "Pennsylvania": "PA", + "Rhode Island": "RI", + "South Carolina": "SC", + "South Dakota": "SD", + "Tennessee": "TN", + "Texas": "TX", + "Utah": "UT", + "Vermont": "VT", + "Virginia": "VA", + "Washington": "WA", + "West Virginia": "WV", + "Wisconsin": "WI", + "Wyoming": "WY", + "District of Columbia": "DC", + "American Samoa": "AS", + "Guam": "GU", + "Northern Mariana Islands": "MP", + "Puerto Rico": "PR", + "United States Minor Outlying Islands": "UM", + "Virgin Islands, U.S.": "VI", +} CURRENT_YEAR = datetime.now().year @@ -95,19 +101,30 @@ class EIAIndustrialNaturalGasConfig(BaseConfig): 2001 and the current year, inclusive of endpoints. monthly (Path): True, if monthly data is desired, False if annual data is desired. api_key_file (Path): Full file name of the file where the API key is located. + latitude (float, optional): Latitude of the site, optional. + latitude (float, optional): Longitude of the site, optional. + filename (str, optinal): Filename for where to save the data or where the data may + already be located. If the file exists, it will be used, and filtered to the + :py:attr:`resource_year`, otherwise, the data will be saved to this location. """ - state: str = field( - converter=str.upper, - validator=attrs.validators.in_(STATES), - ) resource_year: int = field(validator=attrs.validators.in_(range(2001, CURRENT_YEAR + 1))) monthly: bool = field(validator=attrs.validators.instance_of(bool)) api_key_file: str = field(converter=get_path) + state: str = field( + converter=str.upper, + validator=attrs.validators.in_(STATE_MAP.values()), + ) + latitude: float = field(default=0) + longitude: float = field(default=0) + filename: str = field(default=None, converter=attrs.converters.optional(get_path)) class EIAIndustrialNaturalGasResource: - """Create the class.""" + """EIA Industrial Natural Gas Pricing Downloader. + + See https://www.eia.gov/dnav/ng/hist/n3035us3m.htm for further details. + """ def __init__(self, resource_config: dict): # self.setup() @@ -118,10 +135,21 @@ def __init__(self, resource_config: dict): ) self.url = self.create_url() - # def initialize(self): - # self.options.declare("plant_config", types=dict) - # self.options.declare("resource_config", types=dict) - # self.options.declare("driver_config", types=dict) + def initialize(self): + self.options.declare("plant_config", types=dict) + self.options.declare("resource_config", types=dict) + self.options.declare("driver_config", types=dict) + + def setup(self): + # Define inputs and outputs + self.config = EIAIndustrialNaturalGasConfig.from_dict( + self.options["resource_config"], + additional_cls_name=self.__class__.__name__, + ) + site_config = self.options["plant_config"]["site"] + self.add_input("latitude", site_config.get("latitude", 0.0), units="deg") + self.add_input("longitude", site_config.get("longitude", 0.0), units="deg") + self.add_output("price", shape=12, val=0.0, units="USD/(ft**3/1000)") def create_url(self): base_url = "https://api.eia.gov/v2/natural-gas/pri/sum/data/" @@ -141,29 +169,53 @@ def create_url(self): url = f"{base_url}?{url_opts}" return url - def setup(self): - # Define inputs and outputs - self.config = EIAIndustrialNaturalGasConfig.from_dict( - self.options["resource_config"], - additional_cls_name=self.__class__.__name__, - ) - # site_config = self.options["plant_config"]["site"] + def load_data(self, filename: Path | None = None) -> pd.DataFrame: + """Loads the previously saved data from :py:attr:`filename` if ``resource_year`` + is available as either annual or monthly data, otherwise queries the EIA API. + + Args: + filename (Path | None, optional): The full filename where the natural gas pricing data + should be saved to or loaded from, if available. Defaults to None. + + Raises: + requests.exceptions.HTTPError: Raised if an unsuccessful API query result is returned. + + Returns: + pandas.DataFrame: DataFrame with index "period" and column "value" with natural gas + pricing in $/MCF (USD per thousands of cubic feet) as either the monthly value + or extrapolated annual values to a monthly resolution. + """ + filename = Path(filename).resolve() + if filename.exists(): + df = pd.read_csv(filename, parse_dates=["period"]).set_index("period") + df = df.loc[df.index.dt.year.eq(self.config.resource_year)] + match df.shape[0]: + case 12: + return df + case 1: + year = self.config.resource_year + df = df.reindex( + pd.date_range(f"{year}-01", f"{year}-12", freq="MS"), method="nearest" + ) + return df + case _: + pass - # self.add_input("latitude", site_config.get("latitude", 0.0), units="deg") - # self.add_input("longitude", site_config.get("longitude", 0.0), units="deg") - # self.add_output("discharge", shape=8760, val=0.0, units="ft**3/s") - - def load_data(self, filename: str | Path | None = None): - # download_from_api(self.url, filename) r = requests.get(self.url) if r.status_code != 200: err = json.loads(r.text)["error"] msg = f"{err['code']}: {err['message']}" raise requests.exceptions.HTTPError(msg) - cols = ["period", "area-name", "value", "units"] + cols = ["period", "value"] df = pd.DataFrame.from_dict(json.loads(r.text)["response"]["data"])[cols] df.period = pd.to_datetime(df.period) + df = df.set_index("period") if filename is not None: - df.to_csv(filename, index=False) + df.to_csv(filename, index_label="period") + return df + + def compute(self, inputs, outputs): + ng_price_monthly = self.load_data(self.config.filename) + outputs["price"] = ng_price_monthly.to_numpy() From 194f5922a2f3612ccf411d1390b748321453d0ef Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Mon, 27 Apr 2026 14:59:09 -0700 Subject: [PATCH 03/40] ensure data are always in monthly format --- h2integrate/resource/ng_price.py | 37 ++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/h2integrate/resource/ng_price.py b/h2integrate/resource/ng_price.py index d5d8643de..e0e81f90f 100644 --- a/h2integrate/resource/ng_price.py +++ b/h2integrate/resource/ng_price.py @@ -73,6 +73,28 @@ CURRENT_YEAR = datetime.now().year +def convert_to_monthly(df: pd.DataFrame, year: int) -> pd.DataFrame | None: + """Converts an annual timeseries to monthly by repeating the one value, or returns + the data passed, if already monthly. + + Args: + df (pd.DataFrame): The annual or monthly natural gas pricing data. + year (int): The resource year. + + Returns: + pd.DataFrame | None: Returns back the monthly data if the original data have either + 1 or 12 data entries, otherwise None is returned. + """ + match df.shape[0]: + case 12: + return df + case 1: + df = df.reindex(pd.date_range(f"{year}-01", f"{year}-12", freq="MS"), method="nearest") + return df + case _: + pass + + def get_eia_api_key(filename: Path) -> str: """Retrieves the EIA API key from a file, and returns the key following "EIA_API_KEY:". @@ -189,17 +211,9 @@ def load_data(self, filename: Path | None = None) -> pd.DataFrame: if filename.exists(): df = pd.read_csv(filename, parse_dates=["period"]).set_index("period") df = df.loc[df.index.dt.year.eq(self.config.resource_year)] - match df.shape[0]: - case 12: - return df - case 1: - year = self.config.resource_year - df = df.reindex( - pd.date_range(f"{year}-01", f"{year}-12", freq="MS"), method="nearest" - ) - return df - case _: - pass + df = convert_to_monthly(df, self.config.resource_year) + if df is not None: + return df r = requests.get(self.url) if r.status_code != 200: @@ -211,6 +225,7 @@ def load_data(self, filename: Path | None = None) -> pd.DataFrame: df = pd.DataFrame.from_dict(json.loads(r.text)["response"]["data"])[cols] df.period = pd.to_datetime(df.period) df = df.set_index("period") + df = convert_to_monthly(df) if filename is not None: df.to_csv(filename, index_label="period") From 80987d2f17aad8efac8f51e54ca9c93325dbf3e6 Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:03:52 -0700 Subject: [PATCH 04/40] add openmdao --- h2integrate/resource/ng_price.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/h2integrate/resource/ng_price.py b/h2integrate/resource/ng_price.py index e0e81f90f..07a1a848f 100644 --- a/h2integrate/resource/ng_price.py +++ b/h2integrate/resource/ng_price.py @@ -5,6 +5,7 @@ import attrs import pandas as pd import requests +import openmdao.api as om from attrs import field, define from h2integrate.core.utilities import BaseConfig @@ -142,7 +143,7 @@ class EIAIndustrialNaturalGasConfig(BaseConfig): filename: str = field(default=None, converter=attrs.converters.optional(get_path)) -class EIAIndustrialNaturalGasResource: +class EIAIndustrialNaturalGasResource(om.ExplicitComponent): """EIA Industrial Natural Gas Pricing Downloader. See https://www.eia.gov/dnav/ng/hist/n3035us3m.htm for further details. From aaa333ad4db5d076181a99a0850b9dc55f1563ea Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Wed, 29 Apr 2026 13:19:39 -0700 Subject: [PATCH 05/40] move feedstocks to its own folder --- h2integrate/core/supported_models.py | 2 +- h2integrate/feedstocks/__init__.py | 1 + .../{core => feedstocks}/feedstocks.py | 0 h2integrate/feedstocks/test/__init__.py | 0 h2integrate/feedstocks/test/conftest.py | 68 +++++++++++++++++++ .../test/test_feedstocks.py | 0 6 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 h2integrate/feedstocks/__init__.py rename h2integrate/{core => feedstocks}/feedstocks.py (100%) create mode 100644 h2integrate/feedstocks/test/__init__.py create mode 100644 h2integrate/feedstocks/test/conftest.py rename h2integrate/{core => feedstocks}/test/test_feedstocks.py (100%) diff --git a/h2integrate/core/supported_models.py b/h2integrate/core/supported_models.py index 62e197de9..0f12de1d9 100644 --- a/h2integrate/core/supported_models.py +++ b/h2integrate/core/supported_models.py @@ -1,6 +1,6 @@ +from h2integrate.feedstocks import FeedstockCostModel, FeedstockPerformanceModel from h2integrate.resource.river import RiverResource from h2integrate.resource.tidal import TidalResource -from h2integrate.core.feedstocks import FeedstockCostModel, FeedstockPerformanceModel from h2integrate.transporters.pipe import PipePerformanceModel from h2integrate.transporters.cable import CablePerformanceModel from h2integrate.converters.grid.grid import GridCostModel, GridPerformanceModel diff --git a/h2integrate/feedstocks/__init__.py b/h2integrate/feedstocks/__init__.py new file mode 100644 index 000000000..791d3f64e --- /dev/null +++ b/h2integrate/feedstocks/__init__.py @@ -0,0 +1 @@ +from h2integrate.feedstocks.feedstocks import FeedstockPerformanceModel, FeedstockCostModel diff --git a/h2integrate/core/feedstocks.py b/h2integrate/feedstocks/feedstocks.py similarity index 100% rename from h2integrate/core/feedstocks.py rename to h2integrate/feedstocks/feedstocks.py diff --git a/h2integrate/feedstocks/test/__init__.py b/h2integrate/feedstocks/test/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/h2integrate/feedstocks/test/conftest.py b/h2integrate/feedstocks/test/conftest.py new file mode 100644 index 000000000..378efd555 --- /dev/null +++ b/h2integrate/feedstocks/test/conftest.py @@ -0,0 +1,68 @@ +""" +Pytest configuration file. +""" + +import os + +from h2integrate import EXAMPLE_DIR + +from test.conftest import ( # noqa: F401 + temp_dir, + temp_dir_module, + temp_copy_of_example, + pytest_collection_modifyitems, + temp_copy_of_example_module_scope, +) + + +def pytest_sessionstart(session): + initial_om_report_setting = os.getenv("OPENMDAO_REPORTS") + if initial_om_report_setting is not None: + os.environ["TMP_OPENMDAO_REPORTS"] = initial_om_report_setting + + os.environ["OPENMDAO_REPORTS"] = "none" + + # set environment variables used for + # tests in h2integrate/core/test/test_recorder.py + os.environ["TEST_RECORDER_OUTPUT_EXAMPLE"] = "05_wind_h2_opt" + os.environ["TEST_RECORDER_OUTPUT_DIR"] = "testingtesting_output_dir" + os.environ["TEST_RECORDER_OUTPUT_FILE0"] = "testingtesting_filename.sql" + os.environ["TEST_RECORDER_OUTPUT_FILE1"] = "testingtesting_filename0.sql" + os.environ["TEST_RECORDER_OUTPUT_FILE2"] = "testingtesting_filename1.sql" + + +def pytest_sessionfinish(session, exitstatus): + initial_om_report_setting = os.getenv("TMP_OPENMDAO_REPORTS") + if initial_om_report_setting is not None: + os.environ["OPENMDAO_REPORTS"] = initial_om_report_setting + os.environ.pop("TMP_OPENMDAO_REPORTS", None) + + # remove files that were created in h2integrate/core/test/test_recorder.py + if os.getenv("TEST_RECORDER_OUTPUT_EXAMPLE") is not None: + test_dir = ( + EXAMPLE_DIR + / os.getenv("TEST_RECORDER_OUTPUT_EXAMPLE") + / os.getenv("TEST_RECORDER_OUTPUT_DIR") + ) + file0path = test_dir / os.getenv("TEST_RECORDER_OUTPUT_FILE0") + file1path = test_dir / os.getenv("TEST_RECORDER_OUTPUT_FILE1") + file2path = test_dir / os.getenv("TEST_RECORDER_OUTPUT_FILE2") + if file0path.exists(): + file0path.unlink() + if file1path.exists(): + file1path.unlink() + if file2path.exists(): + file2path.unlink() + # remove folder created in h2integrate/core/test/test_recorder.py + if test_dir.exists(): + files_in_test_folder = list(test_dir.iterdir()) + if len(files_in_test_folder) == 0: + test_dir.rmdir() + + # remove environment variables used for tests in + # h2integrate/core/test/test_recorder.py + os.environ.pop("TEST_RECORDER_OUTPUT_EXAMPLE", None) + os.environ.pop("TEST_RECORDER_OUTPUT_DIR", None) + os.environ.pop("TEST_RECORDER_OUTPUT_FILE0", None) + os.environ.pop("TEST_RECORDER_OUTPUT_FILE1", None) + os.environ.pop("TEST_RECORDER_OUTPUT_FILE2", None) diff --git a/h2integrate/core/test/test_feedstocks.py b/h2integrate/feedstocks/test/test_feedstocks.py similarity index 100% rename from h2integrate/core/test/test_feedstocks.py rename to h2integrate/feedstocks/test/test_feedstocks.py From f8fd1be7de56d8d788a58cf73d5dda50ddb55e53 Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:27:38 -0700 Subject: [PATCH 06/40] move natural gas pricing to feedstocks and convert config for compliance --- .../eia_ng_pricing.py} | 184 ++++++++++++------ 1 file changed, 121 insertions(+), 63 deletions(-) rename h2integrate/{resource/ng_price.py => feedstocks/eia_ng_pricing.py} (54%) diff --git a/h2integrate/resource/ng_price.py b/h2integrate/feedstocks/eia_ng_pricing.py similarity index 54% rename from h2integrate/resource/ng_price.py rename to h2integrate/feedstocks/eia_ng_pricing.py index 07a1a848f..d3780260b 100644 --- a/h2integrate/resource/ng_price.py +++ b/h2integrate/feedstocks/eia_ng_pricing.py @@ -3,16 +3,17 @@ from datetime import datetime import attrs +import numpy as np import pandas as pd import requests -import openmdao.api as om from attrs import field, define -from h2integrate.core.utilities import BaseConfig from h2integrate.core.file_utils import get_path +from h2integrate.core.model_baseclasses import BaseConfig, CostModelBaseClass -STATE_MAP = states = { +MCF_to_MMBTU = 1 / 0.964 +STATE_MAP = { "Alabama": "AL", "Alaska": "AK", "Arizona": "AZ", @@ -64,15 +65,21 @@ "Wisconsin": "WI", "Wyoming": "WY", "District of Columbia": "DC", - "American Samoa": "AS", - "Guam": "GU", - "Northern Mariana Islands": "MP", - "Puerto Rico": "PR", - "United States Minor Outlying Islands": "UM", - "Virgin Islands, U.S.": "VI", + "United States": "US", } CURRENT_YEAR = datetime.now().year +EIA_FACET = { + "wellhead": "N9190{}3", + "imports": "N9100{}3", + "citygate": "N3050{}3", + "residential": "N3010{}3", + "commercial": "N3020{}3", + "industrial": "N3035{}3", + "electrical_power": "N3045{}3", + "exports": "N9130{}3", +} + def convert_to_monthly(df: pd.DataFrame, year: int) -> pd.DataFrame | None: """Converts an annual timeseries to monthly by repeating the one value, or returns @@ -96,6 +103,33 @@ def convert_to_monthly(df: pd.DataFrame, year: int) -> pd.DataFrame | None: pass +def convert_state_value(state: str) -> str: + """Convert potential two-letter state abbreviations to upper case and all else to title + casing to align with the ``STATE_MAP`` keys and values. + + Args: + state (str): Either a two-letter state abbreviation or full state name. + + Returns: + str: Upper case state abbreviation or title case state name. + """ + if len(state) == 2: + return state.upper() + return state.title() + + +def convert_state_to_code(state: str) -> str: + """Converts the :py:attr:`state` name to a two-letter abbreviation or returns the input value. + + Args: + state (str): Full state name in title casing or two-letter state abbreviation in upper case. + + Returns: + str: Two-letter state abbreviation. + """ + return STATE_MAP.get(state, state) + + def get_eia_api_key(filename: Path) -> str: """Retrieves the EIA API key from a file, and returns the key following "EIA_API_KEY:". @@ -115,70 +149,68 @@ def get_eia_api_key(filename: Path) -> str: @define -class EIAIndustrialNaturalGasConfig(BaseConfig): - """EIA Industrial Natural Gas Pricing API Configuration. +class EIANaturalGasFeedstockConfig(BaseConfig): + """EIA Industrial Natural Gas Pricing API configuration and downloader for the US and all 50 US + states, in $/MCF, converted to $/MMBtu. Please see + https://www.eia.gov/opendata/browser/natural-gas/pri/sum for further details about data + availability. Args: - state (str): Two-letter, upper case state abbreviation. Must be one of the 50 U.S. states. + state (str): Full name of the state or two-letter state abbreviation, such as + "United States" or "US". Only the "US" or all 50 states will produce valid results. resource_year (int): The YYYY-format year whose data should be retrieved. Must be between 2001 and the current year, inclusive of endpoints. + cost_year (int): dollar-year for costs. Defaults to the current year. monthly (Path): True, if monthly data is desired, False if annual data is desired. api_key_file (Path): Full file name of the file where the API key is located. - latitude (float, optional): Latitude of the site, optional. - latitude (float, optional): Longitude of the site, optional. filename (str, optinal): Filename for where to save the data or where the data may - already be located. If the file exists, it will be used, and filtered to the - :py:attr:`resource_year`, otherwise, the data will be saved to this location. + already be located. If the file exists, the columns "period", "state", and "price" must + exist, otherwise the file will not be used. "period" should be of the form YYYY or + YYYY-MM, and state should be either the full state name or the two-letter abbreviation. + annual_cost (float, optional): fixed cost associated with the feedstock in USD/year. + Defaults to 0.0. + start_up_cost (float, optional): one-time capital cost associated with the feedstock in USD. + Defaults to 0.0. + commodity_rate_units (str): feedstock usage rate units (such as "galUS/h", "kg/h" or "kW") + commodity_amount_units (str, optional): the amount units of the commodity (i.e., + "galUS", "kg" or "kW*h"). If None, will be set as `commodity_rate_units*h` """ resource_year: int = field(validator=attrs.validators.in_(range(2001, CURRENT_YEAR + 1))) monthly: bool = field(validator=attrs.validators.instance_of(bool)) api_key_file: str = field(converter=get_path) state: str = field( - converter=str.upper, - validator=attrs.validators.in_(STATE_MAP.values()), + converter=attrs.converters.pipe(convert_state_value, convert_state_to_code), + validator=attrs.validators.in_([*STATE_MAP, *STATE_MAP.values()]), ) - latitude: float = field(default=0) - longitude: float = field(default=0) + price_category: str = field(converter=str.lower, validator=attrs.validators.in_(EIA_FACET)) + commodity_rate_units: str = field() + commodity_amount_units: str = field() + + url: str = field(init=False) + series: str = field(init=False) + price: np.ndarray = field(init=False) + cost_year: int = field(default=CURRENT_YEAR) + annual_cost: float = field(default=0.0, converter=float) + start_up_cost: float = field(default=0.0, converter=float) + commodity: str = field(default="natural_gas", init=False) filename: str = field(default=None, converter=attrs.converters.optional(get_path)) - -class EIAIndustrialNaturalGasResource(om.ExplicitComponent): - """EIA Industrial Natural Gas Pricing Downloader. - - See https://www.eia.gov/dnav/ng/hist/n3035us3m.htm for further details. - """ - - def __init__(self, resource_config: dict): - # self.setup() - self.config = EIAIndustrialNaturalGasConfig.from_dict( - # self.options["resource_config"], - resource_config, - additional_cls_name=self.__class__.__name__, - ) + def __attrs_post_init__(self): + """Creates the EIA natural gas facet series code based on validated user inputs, sets the + :py:attr:`commodity_amount_units` if not given a value, and fetches the EIA natural gas + price. + """ + self.series = EIA_FACET[self.price_category].format(self.state) + if self.commodity_amount_units is None: + self.commodity_amount_units = f"({self.commodity_rate_units})*h" self.url = self.create_url() - def initialize(self): - self.options.declare("plant_config", types=dict) - self.options.declare("resource_config", types=dict) - self.options.declare("driver_config", types=dict) - - def setup(self): - # Define inputs and outputs - self.config = EIAIndustrialNaturalGasConfig.from_dict( - self.options["resource_config"], - additional_cls_name=self.__class__.__name__, - ) - site_config = self.options["plant_config"]["site"] - self.add_input("latitude", site_config.get("latitude", 0.0), units="deg") - self.add_input("longitude", site_config.get("longitude", 0.0), units="deg") - self.add_output("price", shape=12, val=0.0, units="USD/(ft**3/1000)") - def create_url(self): base_url = "https://api.eia.gov/v2/natural-gas/pri/sum/data/" frequency = f"frequency={'monthly' if self.config.monthly else 'annual'}" data = "data[0]=value" - facet = f"facets[series][]=N3035{self.config.state}3" + facet = f"facets[series][]={self.config.series}" start = f"start={self.config.resource_year}" end = f"end={self.config.resource_year}" if self.config.monthly: @@ -192,9 +224,9 @@ def create_url(self): url = f"{base_url}?{url_opts}" return url - def load_data(self, filename: Path | None = None) -> pd.DataFrame: + def get_data(self, filename: Path | None = None) -> pd.DataFrame: """Loads the previously saved data from :py:attr:`filename` if ``resource_year`` - is available as either annual or monthly data, otherwise queries the EIA API. + is available as either annual or monthly data, otherwise data is retrieved from the EIA API. Args: filename (Path | None, optional): The full filename where the natural gas pricing data @@ -205,15 +237,18 @@ def load_data(self, filename: Path | None = None) -> pd.DataFrame: Returns: pandas.DataFrame: DataFrame with index "period" and column "value" with natural gas - pricing in $/MCF (USD per thousands of cubic feet) as either the monthly value - or extrapolated annual values to a monthly resolution. + pricing in $/MMBtu (converted from the EIA's USD per thousands of cubic feet) as + either the monthly value or extrapolated annual values to a monthly resolution. """ - filename = Path(filename).resolve() - if filename.exists(): - df = pd.read_csv(filename, parse_dates=["period"]).set_index("period") - df = df.loc[df.index.dt.year.eq(self.config.resource_year)] - df = convert_to_monthly(df, self.config.resource_year) - if df is not None: + if filename is None: + filename = self.filename + + if filename is not None: + filename = Path(filename).resolve() + if filename.exists(): + df = pd.read_csv(filename, parse_dates=["period"]).set_index("period") + df = df.loc[df.index.dt.year.eq(self.config.resource_year)] + df = convert_to_monthly(df, self.config.resource_year) return df r = requests.get(self.url) @@ -223,15 +258,38 @@ def load_data(self, filename: Path | None = None) -> pd.DataFrame: raise requests.exceptions.HTTPError(msg) cols = ["period", "value"] - df = pd.DataFrame.from_dict(json.loads(r.text)["response"]["data"])[cols] + df = pd.DataFrame.from_dict(json.loads(r.text)["response"]["data"]) + if df.size == 0: + raise ValueError(f"No data for combination {self.state=}, {self.price_category=}") + df.period = pd.to_datetime(df.period) - df = df.set_index("period") + df = df[cols].set_index("period") df = convert_to_monthly(df) if filename is not None: df.to_csv(filename, index_label="period") return df + +class EIANaturalGasFeedstockCostModel(CostModelBaseClass): + """ """ + + _time_step_bounds = (3600, 3600) # (min, max) time step lengths (seconds) allowed + + def setup(self): + # Define inputs and outputs + self.config = EIANaturalGasFeedstockConfig.from_dict( + self.options["resource_config"], + additional_cls_name=self.__class__.__name__, + ) + self.config.get_data() + self.n_timesteps = int(self.options["plant_config"]["plant"]["simulation"]["n_timesteps"]) + int(self.options["plant_config"]["plant"]["plant_life"]) + site_config = self.options["plant_config"]["site"] + self.add_input("latitude", site_config.get("latitude", 0.0), units="deg") + self.add_input("longitude", site_config.get("longitude", 0.0), units="deg") + self.add_output("price", shape=12, val=0.0, units="USD/(ft**3/1000)") + def compute(self, inputs, outputs): ng_price_monthly = self.load_data(self.config.filename) outputs["price"] = ng_price_monthly.to_numpy() From 6e978f6d22c14c82c932a5f35535d5011676b115 Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 11:07:22 -0700 Subject: [PATCH 07/40] update long comment and start building out NG cost model --- h2integrate/feedstocks/eia_ng_pricing.py | 120 +++++++++++++++++++---- h2integrate/feedstocks/feedstocks.py | 4 +- 2 files changed, 101 insertions(+), 23 deletions(-) diff --git a/h2integrate/feedstocks/eia_ng_pricing.py b/h2integrate/feedstocks/eia_ng_pricing.py index d3780260b..a037ed58b 100644 --- a/h2integrate/feedstocks/eia_ng_pricing.py +++ b/h2integrate/feedstocks/eia_ng_pricing.py @@ -3,7 +3,6 @@ from datetime import datetime import attrs -import numpy as np import pandas as pd import requests from attrs import field, define @@ -12,6 +11,8 @@ from h2integrate.core.model_baseclasses import BaseConfig, CostModelBaseClass +HOURS_PER_YEAR = 8760 +SECONDS_PER_HOUR = 3600 MCF_to_MMBTU = 1 / 0.964 STATE_MAP = { "Alabama": "AL", @@ -171,9 +172,6 @@ class EIANaturalGasFeedstockConfig(BaseConfig): Defaults to 0.0. start_up_cost (float, optional): one-time capital cost associated with the feedstock in USD. Defaults to 0.0. - commodity_rate_units (str): feedstock usage rate units (such as "galUS/h", "kg/h" or "kW") - commodity_amount_units (str, optional): the amount units of the commodity (i.e., - "galUS", "kg" or "kW*h"). If None, will be set as `commodity_rate_units*h` """ resource_year: int = field(validator=attrs.validators.in_(range(2001, CURRENT_YEAR + 1))) @@ -184,16 +182,16 @@ class EIANaturalGasFeedstockConfig(BaseConfig): validator=attrs.validators.in_([*STATE_MAP, *STATE_MAP.values()]), ) price_category: str = field(converter=str.lower, validator=attrs.validators.in_(EIA_FACET)) - commodity_rate_units: str = field() - commodity_amount_units: str = field() url: str = field(init=False) series: str = field(init=False) - price: np.ndarray = field(init=False) + price: pd.DataFrame = field(init=False, validator=attrs.validators.instance_of(pd.DataFrame)) cost_year: int = field(default=CURRENT_YEAR) annual_cost: float = field(default=0.0, converter=float) start_up_cost: float = field(default=0.0, converter=float) commodity: str = field(default="natural_gas", init=False) + commodity_rate_units: str = field(default="MMBtu/h", init=False) + commodity_amount_units: str = field(default="MMBtu", init=False) filename: str = field(default=None, converter=attrs.converters.optional(get_path)) def __attrs_post_init__(self): @@ -204,9 +202,10 @@ def __attrs_post_init__(self): self.series = EIA_FACET[self.price_category].format(self.state) if self.commodity_amount_units is None: self.commodity_amount_units = f"({self.commodity_rate_units})*h" - self.url = self.create_url() + self.url = self.create_eia_api_url() + self.price = self.get_data() - def create_url(self): + def create_eia_api_url(self): base_url = "https://api.eia.gov/v2/natural-gas/pri/sum/data/" frequency = f"frequency={'monthly' if self.config.monthly else 'annual'}" data = "data[0]=value" @@ -249,7 +248,8 @@ def get_data(self, filename: Path | None = None) -> pd.DataFrame: df = pd.read_csv(filename, parse_dates=["period"]).set_index("period") df = df.loc[df.index.dt.year.eq(self.config.resource_year)] df = convert_to_monthly(df, self.config.resource_year) - return df + if df is not None: + return df r = requests.get(self.url) if r.status_code != 200: @@ -265,6 +265,7 @@ def get_data(self, filename: Path | None = None) -> pd.DataFrame: df.period = pd.to_datetime(df.period) df = df[cols].set_index("period") df = convert_to_monthly(df) + df.value *= MCF_to_MMBTU if filename is not None: df.to_csv(filename, index_label="period") @@ -282,14 +283,93 @@ def setup(self): self.options["resource_config"], additional_cls_name=self.__class__.__name__, ) - self.config.get_data() self.n_timesteps = int(self.options["plant_config"]["plant"]["simulation"]["n_timesteps"]) - int(self.options["plant_config"]["plant"]["plant_life"]) - site_config = self.options["plant_config"]["site"] - self.add_input("latitude", site_config.get("latitude", 0.0), units="deg") - self.add_input("longitude", site_config.get("longitude", 0.0), units="deg") - self.add_output("price", shape=12, val=0.0, units="USD/(ft**3/1000)") - - def compute(self, inputs, outputs): - ng_price_monthly = self.load_data(self.config.filename) - outputs["price"] = ng_price_monthly.to_numpy() + + self.add_output("price", shape=12, val=self.config.price, units="USD/MMBtu") + + super().setup() + + self.dt = self.options["plant_config"]["plant"]["simulation"]["dt"] + self.plant_life = int(self.options["plant_config"]["plant"]["plant_life"]) + self.fraction_of_year_simulated = ( + self.dt / SECONDS_PER_HOUR * self.n_timesteps / HOURS_PER_YEAR + ) + + self.add_input( + f"{self.config.commodity}_consumed", + val=0.0, + shape=self.n_timesteps, + units=self.config.commodity_rate_units, + desc=f"Consumption profile of {self.config.commodity}", + ) + self.add_input( + f"{self.config.commodity}_out", + val=0, + shape=self.n_timesteps, + units=self.config.commodity_rate_units, + ) + self.add_input( + "price", + val=self.config.price, + units=f"USD/({self.config.commodity_amount_units})", + desc=f"Price profile of {self.config.commodity}", + ) + + self.add_output( + f"total_{self.config.commodity}_consumed", + val=0.0, + units=self.config.commodity_amount_units, + ) + + self.add_output( + f"annual_{self.config.commodity}_consumed", + val=0.0, + shape=self.plant_life, + units=f"({self.config.commodity_amount_units})/year", + ) + + # Capacity factor is feedstock_consumed/max_feedstock_available + self.add_output( + "capacity_factor", + val=0.0, + shape=self.plant_life, + units="unitless", + desc="Capacity factor", + ) + + # The should be equal to the commodity_capacity input of the FeedstockPerformanceModel + self.add_output( + f"rated_{self.config.commodity}_production", + val=0, + units=self.config.commodity_rate_units, + ) + + # lifetime estimate of item replacements, represented as a fraction of the capacity. + self.add_output("replacement_schedule", val=0.0, shape=self.plant_life, units="unitless") + + def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): + outputs["capacity_factor"] = ( + inputs[f"{self.config.commodity}_consumed"].sum() + / inputs[f"{self.config.commodity}_out"].sum() + ) + outputs[f"total_{self.config.commodity}_consumed"] = inputs[ + f"{self.config.commodity}_consumed" + ].sum() * (self.dt / 3600) + + # TODO: update to handle varying consumption levels when feedstock consumption is available + outputs[f"annual_{self.config.commodity}_consumed"] = outputs[ + f"total_{self.config.commodity}_consumed" + ] * (1 / self.fraction_of_year_simulated) + + outputs[f"rated_{self.config.commodity}_production"] = inputs[ + f"{self.config.commodity}_out" + ].max() + + # TODO: Calculate costs + price = inputs["price"] + hourly_consumption = inputs[f"{self.config.commodity}_consumed"] + cost_per_year = sum(price * hourly_consumption) + + outputs["CapEx"] = self.config.start_up_cost + outputs["OpEx"] = self.config.annual_cost + outputs["VarOpEx"] = cost_per_year diff --git a/h2integrate/feedstocks/feedstocks.py b/h2integrate/feedstocks/feedstocks.py index a0f457c3c..d6b7e553c 100644 --- a/h2integrate/feedstocks/feedstocks.py +++ b/h2integrate/feedstocks/feedstocks.py @@ -177,9 +177,7 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): f"{self.config.commodity}_consumed" ].sum() * (self.dt / 3600) - # Estimate annual consumption based on consumption over the simulation - # NOTE: once we standardize feedstock consumption outputs in models, this should - # be updated to handle consumption that varies over years of operation + # TODO: update to handle varying consumption levels when feedstock consumption is available outputs[f"annual_{self.config.commodity}_consumed"] = outputs[ f"total_{self.config.commodity}_consumed" ] * (1 / self.fraction_of_year_simulated) From 52a5bcbb0d57b0ff7f234ba96d76be26daf7e9ee Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 12:30:22 -0700 Subject: [PATCH 08/40] update compute docstring and include feedstocks folder in api docs --- docs/api.md | 1 + h2integrate/feedstocks/feedstocks.py | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/api.md b/docs/api.md index 6cf44f280..794ce6363 100644 --- a/docs/api.md +++ b/docs/api.md @@ -8,6 +8,7 @@ :recursive: core + feedstocks converters control finances diff --git a/h2integrate/feedstocks/feedstocks.py b/h2integrate/feedstocks/feedstocks.py index d6b7e553c..4717c5cbb 100644 --- a/h2integrate/feedstocks/feedstocks.py +++ b/h2integrate/feedstocks/feedstocks.py @@ -166,13 +166,21 @@ def setup(self): self.add_output("replacement_schedule", val=0.0, shape=plant_life, units="unitless") def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): - # Capacity factor is the total amount consumed / the total amount available + """Calculates the following outputs: + + - ``capacity_factor``: commodity_consumed / commodity_out + - ``total_commodity_consumed``: sum of commodity_consumed divided by number + of hours simulated. + - ``anual_commodity_consumed``: :py:attr:`total_commodity_consumed` * (1 / years simulated) + - ``rated_commodity_production``: maximum input ``commodity_out``. + - ``CapEx``: :py:attr:`FeedstockCostConfig.start_up_cost`. + - ``OpEx``: :py:attr:`FeedstockCostConfig.annual_cost`. + - ``VarOpEx``: sum of (:py:attr:`FeedstockCostConfig.price` * input ``commodity_consumed``). + """ outputs["capacity_factor"] = ( inputs[f"{self.config.commodity}_consumed"].sum() / inputs[f"{self.config.commodity}_out"].sum() ) - - # Sum the amount consumed outputs[f"total_{self.config.commodity}_consumed"] = inputs[ f"{self.config.commodity}_consumed" ].sum() * (self.dt / 3600) @@ -186,7 +194,6 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): f"{self.config.commodity}_out" ].max() - # Calculate costs price = inputs["price"] hourly_consumption = inputs[f"{self.config.commodity}_consumed"] cost_per_year = sum(price * hourly_consumption) From 17b62dd34586b6623aef6d354e96adfc672128f8 Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 13:59:08 -0700 Subject: [PATCH 09/40] update inline comment usage --- h2integrate/feedstocks/feedstocks.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/h2integrate/feedstocks/feedstocks.py b/h2integrate/feedstocks/feedstocks.py index 4717c5cbb..e1ac007b8 100644 --- a/h2integrate/feedstocks/feedstocks.py +++ b/h2integrate/feedstocks/feedstocks.py @@ -100,6 +100,7 @@ def setup(self): ) self.n_timesteps = int(self.options["plant_config"]["plant"]["simulation"]["n_timesteps"]) plant_life = int(self.options["plant_config"]["plant"]["plant_life"]) + plant_life *= 1 # Set cost outputs super().setup() @@ -138,15 +139,12 @@ def setup(self): val=0.0, units=self.config.commodity_amount_units, ) - self.add_output( f"annual_{self.config.commodity}_consumed", val=0.0, shape=self.plant_life, units=f"({self.config.commodity_amount_units})/year", ) - - # Capacity factor is feedstock_consumed/max_feedstock_available self.add_output( "capacity_factor", val=0.0, @@ -154,17 +152,22 @@ def setup(self): units="unitless", desc="Capacity factor", ) + self.add_output( + "replacement_schedule", + val=0.0, + shape=self.plant_life, + units="unitless", + desc="Lifetime estimate of item replacements as a fraction of capacity", + ) - # The should be equal to the commodity_capacity input of the FeedstockPerformanceModel + # TODO: Update to the commodity_capacity input of the FeedstockPerformanceModel + # NOTE: Should I set this to rated_capacity if it's available? self.add_output( f"rated_{self.config.commodity}_production", val=0, units=self.config.commodity_rate_units, ) - # lifetime estimate of item replacements, represented as a fraction of the capacity. - self.add_output("replacement_schedule", val=0.0, shape=plant_life, units="unitless") - def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): """Calculates the following outputs: From febfa219e0d549cce712198d480f1e50253ed4d5 Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 13:59:46 -0700 Subject: [PATCH 10/40] convert price to hourly over full year and update comments/docstrings --- h2integrate/feedstocks/eia_ng_pricing.py | 56 ++++++++++++++++++------ 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/h2integrate/feedstocks/eia_ng_pricing.py b/h2integrate/feedstocks/eia_ng_pricing.py index a037ed58b..1c69fd72a 100644 --- a/h2integrate/feedstocks/eia_ng_pricing.py +++ b/h2integrate/feedstocks/eia_ng_pricing.py @@ -96,9 +96,9 @@ def convert_to_monthly(df: pd.DataFrame, year: int) -> pd.DataFrame | None: """ match df.shape[0]: case 12: - return df + return df.resample("MS").bfill() # ensure it's start of the month case 1: - df = df.reindex(pd.date_range(f"{year}-01", f"{year}-12", freq="MS"), method="nearest") + df = df.resample("MS").nearest() return df case _: pass @@ -248,6 +248,7 @@ def get_data(self, filename: Path | None = None) -> pd.DataFrame: df = pd.read_csv(filename, parse_dates=["period"]).set_index("period") df = df.loc[df.index.dt.year.eq(self.config.resource_year)] df = convert_to_monthly(df, self.config.resource_year) + df = df.rename(columns={"value": "price"}) if df is not None: return df @@ -265,7 +266,8 @@ def get_data(self, filename: Path | None = None) -> pd.DataFrame: df.period = pd.to_datetime(df.period) df = df[cols].set_index("period") df = convert_to_monthly(df) - df.value *= MCF_to_MMBTU + df = df.rename(columns={"value": "price"}) + df.price *= MCF_to_MMBTU if filename is not None: df.to_csv(filename, index_label="period") @@ -277,16 +279,28 @@ class EIANaturalGasFeedstockCostModel(CostModelBaseClass): _time_step_bounds = (3600, 3600) # (min, max) time step lengths (seconds) allowed + def _extrapolate_price(self) -> pd.DataFrame: + """Converts the monthly EIA price timeseries to an hourly time series for ``plant_life`` + number of years. + """ + price = self.config.price.copy() + + last = price.iloc[[-1]].resample("ME").ffill() + last.index = [pd.to_datetime(last.index[0].to_pydatetime().replace(hour=23))] + price = pd.concat((price, last)).resample("h").ffill() + return price + def setup(self): - # Define inputs and outputs + """Defines the inputs and outputs of the model and converts the + :py:attr:`EIANaturalGasFeedstockConfig.price` to an hourly timeseries for the + ``plant_life``. + """ self.config = EIANaturalGasFeedstockConfig.from_dict( self.options["resource_config"], additional_cls_name=self.__class__.__name__, ) self.n_timesteps = int(self.options["plant_config"]["plant"]["simulation"]["n_timesteps"]) - self.add_output("price", shape=12, val=self.config.price, units="USD/MMBtu") - super().setup() self.dt = self.options["plant_config"]["plant"]["simulation"]["dt"] @@ -294,6 +308,7 @@ def setup(self): self.fraction_of_year_simulated = ( self.dt / SECONDS_PER_HOUR * self.n_timesteps / HOURS_PER_YEAR ) + price = self._extrapolate_price() self.add_input( f"{self.config.commodity}_consumed", @@ -310,7 +325,7 @@ def setup(self): ) self.add_input( "price", - val=self.config.price, + val=price.price.to_numpy(), units=f"USD/({self.config.commodity_amount_units})", desc=f"Price profile of {self.config.commodity}", ) @@ -320,15 +335,12 @@ def setup(self): val=0.0, units=self.config.commodity_amount_units, ) - self.add_output( f"annual_{self.config.commodity}_consumed", val=0.0, shape=self.plant_life, units=f"({self.config.commodity_amount_units})/year", ) - - # Capacity factor is feedstock_consumed/max_feedstock_available self.add_output( "capacity_factor", val=0.0, @@ -336,18 +348,34 @@ def setup(self): units="unitless", desc="Capacity factor", ) + self.add_output( + "replacement_schedule", + val=0.0, + shape=self.plant_life, + units="unitless", + desc="Lifetime estimate of item replacements as a fraction of capacity", + ) - # The should be equal to the commodity_capacity input of the FeedstockPerformanceModel + # TODO: Update to the commodity_capacity input of the FeedstockPerformanceModel + # NOTE: Should I set this to rated_capacity if it's available? self.add_output( f"rated_{self.config.commodity}_production", val=0, units=self.config.commodity_rate_units, ) - # lifetime estimate of item replacements, represented as a fraction of the capacity. - self.add_output("replacement_schedule", val=0.0, shape=self.plant_life, units="unitless") - def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): + """Calculates the following outputs: + + - ``capacity_factor``: commodity_consumed / commodity_out + - ``total_commodity_consumed``: sum of commodity_consumed divided by number + of hours simulated. + - ``anual_commodity_consumed``: :py:attr:`total_commodity_consumed` * (1 / years simulated) + - ``rated_commodity_production``: maximum input ``commodity_out``. + - ``CapEx``: :py:attr:`FeedstockCostConfig.start_up_cost`. + - ``OpEx``: :py:attr:`FeedstockCostConfig.annual_cost`. + - ``VarOpEx``: sum of (:py:attr:`FeedstockCostConfig.price` * input ``commodity_consumed``). + """ outputs["capacity_factor"] = ( inputs[f"{self.config.commodity}_consumed"].sum() / inputs[f"{self.config.commodity}_out"].sum() From fcf54c54db2bc698232c7a49b5604294abef937e Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 15:21:46 -0700 Subject: [PATCH 11/40] remove placeholder for lint ignore --- h2integrate/feedstocks/feedstocks.py | 1 - 1 file changed, 1 deletion(-) diff --git a/h2integrate/feedstocks/feedstocks.py b/h2integrate/feedstocks/feedstocks.py index 2f237ec88..35344754b 100644 --- a/h2integrate/feedstocks/feedstocks.py +++ b/h2integrate/feedstocks/feedstocks.py @@ -101,7 +101,6 @@ def setup(self): ) self.n_timesteps = int(self.options["plant_config"]["plant"]["simulation"]["n_timesteps"]) plant_life = int(self.options["plant_config"]["plant"]["plant_life"]) - plant_life *= 1 # Set cost outputs super().setup() From 7675156c00f45effb74ed49b70365aa1ae610839 Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 15:22:32 -0700 Subject: [PATCH 12/40] ensure price timeseries matches n_timesteps --- h2integrate/feedstocks/eia_ng_pricing.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/h2integrate/feedstocks/eia_ng_pricing.py b/h2integrate/feedstocks/eia_ng_pricing.py index 1c69fd72a..05d8bd4ab 100644 --- a/h2integrate/feedstocks/eia_ng_pricing.py +++ b/h2integrate/feedstocks/eia_ng_pricing.py @@ -279,7 +279,7 @@ class EIANaturalGasFeedstockCostModel(CostModelBaseClass): _time_step_bounds = (3600, 3600) # (min, max) time step lengths (seconds) allowed - def _extrapolate_price(self) -> pd.DataFrame: + def _extrapolate_price_to_hourly(self) -> pd.DataFrame: """Converts the monthly EIA price timeseries to an hourly time series for ``plant_life`` number of years. """ @@ -288,6 +288,12 @@ def _extrapolate_price(self) -> pd.DataFrame: last = price.iloc[[-1]].resample("ME").ffill() last.index = [pd.to_datetime(last.index[0].to_pydatetime().replace(hour=23))] price = pd.concat((price, last)).resample("h").ffill() + if price.shape[0] != self.n_timesteps: + msg = ( + "An error occurred converting EIA data to hourly to match size: " + f"{price.shape[0]} to simulation {self.n_timesteps=}" + ) + raise ValueError(msg) return price def setup(self): @@ -308,7 +314,7 @@ def setup(self): self.fraction_of_year_simulated = ( self.dt / SECONDS_PER_HOUR * self.n_timesteps / HOURS_PER_YEAR ) - price = self._extrapolate_price() + price = self._extrapolate_price_to_hourly() self.add_input( f"{self.config.commodity}_consumed", From 829835d820cf6f2028ed204ee7229ec87eaddc7c Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 16:18:28 -0700 Subject: [PATCH 13/40] add leap year handling for clean 8760s --- h2integrate/feedstocks/eia_ng_pricing.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/h2integrate/feedstocks/eia_ng_pricing.py b/h2integrate/feedstocks/eia_ng_pricing.py index 05d8bd4ab..7eb19736e 100644 --- a/h2integrate/feedstocks/eia_ng_pricing.py +++ b/h2integrate/feedstocks/eia_ng_pricing.py @@ -287,7 +287,12 @@ def _extrapolate_price_to_hourly(self) -> pd.DataFrame: last = price.iloc[[-1]].resample("ME").ffill() last.index = [pd.to_datetime(last.index[0].to_pydatetime().replace(hour=23))] - price = pd.concat((price, last)).resample("h").ffill() + price = ( + pd.concat((price, last)) + .resample("h") + .ffill() + .drop(price.loc[(price.index.month == 2) & (price.index.day == 29)].index) + ) if price.shape[0] != self.n_timesteps: msg = ( "An error occurred converting EIA data to hourly to match size: " From d5baed6e3ddb31551c6eb7319715457cae3b7c60 Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 16:24:35 -0700 Subject: [PATCH 14/40] update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 997316642..d4a65cc0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Unreleased + - Change commodity in DRI and EAF model from pig iron to sponge iron based on likely carbon content [PR 670](https://github.com/NatLabRockies/H2Integrate/pull/670) - Bugfix for round-trip efficiency handling when calling `check_inputs` around `StoragePerformanceModel` [PR 684](https://github.com/NatLabRockies/H2Integrate/pull/684) - Bugfix. Include nuclear in electricity producing tech list and improve error message for zero-length electricity producing techs in model when electricity is specified as the commodity. [PR 685](https://github.com/NatLabRockies/H2Integrate/pull/685) @@ -17,8 +18,13 @@ - Add `{commodity}_set_point` as an input to hydrogen fuel cell model [PR 709](https://github.com/NatLabRockies/H2Integrate/pull/709) - Rename `n_control_window` to `n_control_window_hours` for unit clarity [PR 712](https://github.com/NatLabRockies/H2Integrate/pull/712) - Update N2 diagram for demand openloop control from static and outdated to dynamic and interactive [PR 714](https://github.com/NatLabRockies/H2Integrate/pull/714) +- `feedstocks.py` has moved from `h2integrate/core/` to `h2_integrate/feedstocks` +- Creates the `EIANaturalGasFeedstockConfig` and `EIANaturalGasFeedstockCostModel` to load EIA + natural gas prices from file or to retrieve them from the EIA API. The model is able to retrieve + the US or any of the 50 states' annual or monthly values, which will be converted into an hourly timeseries. ## 0.8 [April 15, 2026] + - Updated README and docs intro page with expanded H2I description, reorganized sections, and streamlined installation instructions [PR 677](https://github.com/NatLabRockies/H2Integrate/pull/677) - Update energy conversion ratio in H2 SMR model [PR 606](https://github.com/NatLabRockies/H2Integrate/pull/606) - Update iron models and examples [PR 601](https://github.com/NatLabRockies/H2Integrate/pull/601) From adbb8d824b80f23f654ba5b4e23779dbc4f42efa Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 17:00:46 -0700 Subject: [PATCH 15/40] fix typos, make api_key_file consistent, and enable environment variables --- h2integrate/feedstocks/eia_ng_pricing.py | 50 ++++++++++++++++-------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/h2integrate/feedstocks/eia_ng_pricing.py b/h2integrate/feedstocks/eia_ng_pricing.py index 7eb19736e..6def47917 100644 --- a/h2integrate/feedstocks/eia_ng_pricing.py +++ b/h2integrate/feedstocks/eia_ng_pricing.py @@ -1,3 +1,4 @@ +import os import json from pathlib import Path from datetime import datetime @@ -131,22 +132,38 @@ def convert_state_to_code(state: str) -> str: return STATE_MAP.get(state, state) -def get_eia_api_key(filename: Path) -> str: +def get_eia_api_key(api_key_file: Path | None) -> str: """Retrieves the EIA API key from a file, and returns the key following "EIA_API_KEY:". Args: - filename (Path): Full file path and name of where the EIA API key is located. Must be - encoded as "EIA_API_KEY: xxxxxx" + api_key_file (Path, optional): Full file path and name of where the EIA API key is located. + If none is provided, then the API key is retrieved from the environment variables. Must + be encoded as "EIA_API_KEY: xxxxxx" + + Raises: + ValueError: Raised either if no file is provided and an environment variable has not be + defined, or if a filename is provided but "EIA_API_KEY" is not found. Returns: str: The EIA API key. """ - with filename.open() as f: + if api_key_file is None: + key = os.environ.get("EIA_API_KEY") + if key is None: + msg = ( + "No `api_key_file` provided for the EIA API, and 'EIA_API_KEY' is not defined as an" + "environment variable." + ) + raise ValueError(msg) + return key + + with api_key_file.open() as f: for line in f.readlines(): if ":" in line: name, val = line.strip().split(":") if name == "EIA_API_KEY": return val.strip() + raise ValueError(f"No 'EIA_API_KEY' defined in {api_key_file=}") @define @@ -163,8 +180,9 @@ class EIANaturalGasFeedstockConfig(BaseConfig): 2001 and the current year, inclusive of endpoints. cost_year (int): dollar-year for costs. Defaults to the current year. monthly (Path): True, if monthly data is desired, False if annual data is desired. - api_key_file (Path): Full file name of the file where the API key is located. - filename (str, optinal): Filename for where to save the data or where the data may + api_key_file (Path, optional): Full file name of the file where the API key is located. If + no file name is provided, then the environment variables ``EIA_API_KEY`` is used. + filename (str, optional): Filename for where to save the data or where the data may already be located. If the file exists, the columns "period", "state", and "price" must exist, otherwise the file will not be used. "period" should be of the form YYYY or YYYY-MM, and state should be either the full state name or the two-letter abbreviation. @@ -176,7 +194,7 @@ class EIANaturalGasFeedstockConfig(BaseConfig): resource_year: int = field(validator=attrs.validators.in_(range(2001, CURRENT_YEAR + 1))) monthly: bool = field(validator=attrs.validators.instance_of(bool)) - api_key_file: str = field(converter=get_path) + api_key_file: str | None = field(converter=attrs.converters.optional(get_path)) state: str = field( converter=attrs.converters.pipe(convert_state_value, convert_state_to_code), validator=attrs.validators.in_([*STATE_MAP, *STATE_MAP.values()]), @@ -207,17 +225,17 @@ def __attrs_post_init__(self): def create_eia_api_url(self): base_url = "https://api.eia.gov/v2/natural-gas/pri/sum/data/" - frequency = f"frequency={'monthly' if self.config.monthly else 'annual'}" + frequency = f"frequency={'monthly' if self.monthly else 'annual'}" data = "data[0]=value" - facet = f"facets[series][]={self.config.series}" - start = f"start={self.config.resource_year}" - end = f"end={self.config.resource_year}" - if self.config.monthly: + facet = f"facets[series][]={self.series}" + start = f"start={self.resource_year}" + end = f"end={self.resource_year}" + if self.monthly: start = f"{start}-01" end = f"{start}-12" sort_col = "sort[0][column]=period" sort_dir = "sort[0][direction]=asc" - api_key = f"api_key={get_eia_api_key(self.config.api_key_file)}" + api_key = f"api_key={get_eia_api_key(self.api_key_file)}" url_opts = "&".join((frequency, data, facet, start, end, sort_col, sort_dir, api_key)) url = f"{base_url}?{url_opts}" @@ -242,12 +260,13 @@ def get_data(self, filename: Path | None = None) -> pd.DataFrame: if filename is None: filename = self.filename + cols = ["period", "value"] if filename is not None: filename = Path(filename).resolve() if filename.exists(): df = pd.read_csv(filename, parse_dates=["period"]).set_index("period") - df = df.loc[df.index.dt.year.eq(self.config.resource_year)] - df = convert_to_monthly(df, self.config.resource_year) + df = df.loc[df.index.dt.year.eq(self.resource_year) & df.state.eq(self.state)] + df = convert_to_monthly(df, self.resource_year) df = df.rename(columns={"value": "price"}) if df is not None: return df @@ -258,7 +277,6 @@ def get_data(self, filename: Path | None = None) -> pd.DataFrame: msg = f"{err['code']}: {err['message']}" raise requests.exceptions.HTTPError(msg) - cols = ["period", "value"] df = pd.DataFrame.from_dict(json.loads(r.text)["response"]["data"]) if df.size == 0: raise ValueError(f"No data for combination {self.state=}, {self.price_category=}") From 2cbcfdc1d9af9c7af6ecc29d8e34c2a27050834b Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 17:08:39 -0700 Subject: [PATCH 16/40] update docstrings and spacing --- h2integrate/feedstocks/eia_ng_pricing.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/h2integrate/feedstocks/eia_ng_pricing.py b/h2integrate/feedstocks/eia_ng_pricing.py index 6def47917..731c1f95a 100644 --- a/h2integrate/feedstocks/eia_ng_pricing.py +++ b/h2integrate/feedstocks/eia_ng_pricing.py @@ -180,6 +180,9 @@ class EIANaturalGasFeedstockConfig(BaseConfig): 2001 and the current year, inclusive of endpoints. cost_year (int): dollar-year for costs. Defaults to the current year. monthly (Path): True, if monthly data is desired, False if annual data is desired. + price_category (str): One of "wellhead", "imports", "citygate", "residential", "commercial", + "industrial", "electrical_power", or "exports". Note that not all categories will return + state-level data. api_key_file (Path, optional): Full file name of the file where the API key is located. If no file name is provided, then the environment variables ``EIA_API_KEY`` is used. filename (str, optional): Filename for where to save the data or where the data may @@ -200,7 +203,6 @@ class EIANaturalGasFeedstockConfig(BaseConfig): validator=attrs.validators.in_([*STATE_MAP, *STATE_MAP.values()]), ) price_category: str = field(converter=str.lower, validator=attrs.validators.in_(EIA_FACET)) - url: str = field(init=False) series: str = field(init=False) price: pd.DataFrame = field(init=False, validator=attrs.validators.instance_of(pd.DataFrame)) From ddba1d18fb5034d229c6904a686a1287dd8535f4 Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 17:11:33 -0700 Subject: [PATCH 17/40] add the EIA model to the docs page --- docs/technology_models/feedstocks.md | 46 ++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/docs/technology_models/feedstocks.md b/docs/technology_models/feedstocks.md index fed95df68..7fae7a1df 100644 --- a/docs/technology_models/feedstocks.md +++ b/docs/technology_models/feedstocks.md @@ -32,6 +32,7 @@ technology_interconnections: [ ``` Where: + - `name_of_feedstock_source`: Name of your feedstock source - `consuming_technology`: Technology that uses the feedstock - `commodity`: Type identifier (e.g., "natural_gas", "water", "electricity") @@ -85,9 +86,54 @@ The `price` parameter is flexible - you can specify constant pricing with a sing ``` ### Consumed Feedstock Outputs + The feedstock model outputs cost and performance information about the consumed feedstock. The most notable outputs are: - `VarOpEx`: cost of the feedstock consumed (in `USD/yr`) - `total_{commodity}_consumed`: total feedstock consumed over simulation (in `commodity_amount_units`) - `annual_{commodity}_consumed`: annual feedstock consumed (in `commodity_amount_units/yr`) - `rated_{commodity}_production`: this is equal to the the `rated_capacity` of the feedstock model (in `commodity_rate_units`) - `capacity_factor`: ratio of the feedstock consumed to the maximum feedstock available + +## EIA Natural Gas Pricing + +A special case of the feedstock cost model `EIANaturalGasFeedstockCostModel` (see +[the relevant API docs](https://h2integrate.readthedocs.io/en/latest/_autosummary/h2integrate.feedstocks.eia_ng_pricing.html) +for complete details) exists to enable users to download data from the EIA API's natural gas price +portal. Access to the wellhead, import, citygate, residential, commercial, industrial, electrical +power, and exports price facets are supported for all 50 US states and the US as a whole, though +it is best to see which data are +[availble online in the EIA API documentation](https://www.eia.gov/opendata/browser/natural-gas/pri/sum) +prior to using in an analysis. + +Users are expected to get an EIA API key from the +[EIA Open Data portal](https://www.eia.gov/opendata/), or to download the data as as CSV file for +the model to load. + +At present, the EIA natural gas cost model uses only a single year of price data (annual or monthly) +and extrapolates it to an hourly timeseries automatically. + +### Configuring the EIA Cost Model + +Similar to the standard feedstock model, the following variables are able to be set by the user + +- `cost_year` (int): Dollar year for cost inputs +- `annual_cost` (float, optional): Fixed cost per year in USD/year. Defaults to 0.0 +- `start_up_cost` (float, optional): One-time capital cost in USD. Defaults to 0.0 + +Additionally, there are a few other settings that users will need to provide for the model to work +that differ from the standard cost model. + +- `resource_year` (int): Which year to obtain the data from in the range [2001, 2026]. +- `monthly` (bool): If True, the monthly data are retrieved, otherwise the annual price is used. +- `state` (str): Full name of the state or two-letter state abbreviation, such as "United States" or + "US". Only the "US" or all 50 states will produce valid results +- `price_category` (str): One of "wellhead", "imports", "citygate", "residential", "commercial", + "industrial", "electrical_power", or "exports". Note that not all categories will return + state-level data. +- `api_key_file` (str, optional): The file where the user's API key is stored. If storing in a file, + define it on its own line using the convention "EIA_API_KEY: xxxx", or have the API key defined as + an environment variable set as "EIA_API_KEY". + +- `commodity`: Set to "natural_gas" internally. +- `commodity_rate_units`: Set to "MMBtu/h" internally. +- `commodity_amount_units`: Set to "MMBtu" internally. From d714c6d0cb87cd3304854f843578d57dbbde337f Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 17:11:57 -0700 Subject: [PATCH 18/40] add requests instead of relying on other packages requiring it --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 0a67eb712..942e7e98e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ dependencies = [ "ProFAST", "Pyomo>=6.1.2", "rainflow", + "requests", "requests-cache", "retry_requests", "rich>=13.7.0", From 786bd0e8ac2a76b0d2506cb9cb10c160d1fd65cf Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 17:35:25 -0700 Subject: [PATCH 19/40] add to supported models --- h2integrate/core/supported_models.py | 7 ++++++- h2integrate/feedstocks/__init__.py | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/h2integrate/core/supported_models.py b/h2integrate/core/supported_models.py index 0f12de1d9..628578b09 100644 --- a/h2integrate/core/supported_models.py +++ b/h2integrate/core/supported_models.py @@ -1,4 +1,8 @@ -from h2integrate.feedstocks import FeedstockCostModel, FeedstockPerformanceModel +from h2integrate.feedstocks import ( + FeedstockCostModel, + FeedstockPerformanceModel, + EIANaturalGasFeedstockCostModel, +) from h2integrate.resource.river import RiverResource from h2integrate.resource.tidal import TidalResource from h2integrate.transporters.pipe import PipePerformanceModel @@ -310,6 +314,7 @@ # Feedstock "FeedstockPerformanceModel": FeedstockPerformanceModel, "FeedstockCostModel": FeedstockCostModel, + "EIANaturalGasFeedstockCostModel": EIANaturalGasFeedstockCostModel, # Grid "GridPerformanceModel": GridPerformanceModel, "GridCostModel": GridCostModel, diff --git a/h2integrate/feedstocks/__init__.py b/h2integrate/feedstocks/__init__.py index 791d3f64e..f65cb6562 100644 --- a/h2integrate/feedstocks/__init__.py +++ b/h2integrate/feedstocks/__init__.py @@ -1 +1,2 @@ from h2integrate.feedstocks.feedstocks import FeedstockPerformanceModel, FeedstockCostModel +from h2integrate.feedstocks.eia_ng_pricing import EIANaturalGasFeedstockCostModel From 789a41746ae92a79064c2fe84475c719bdb1cfc1 Mon Sep 17 00:00:00 2001 From: "Hammond, Rob" <13874373+RHammond2@users.noreply.github.com> Date: Thu, 30 Apr 2026 17:37:33 -0700 Subject: [PATCH 20/40] update class hierarchy --- docs/_static/class_hierarchy.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/_static/class_hierarchy.html b/docs/_static/class_hierarchy.html index acd5c8d55..57f48046e 100644 --- a/docs/_static/class_hierarchy.html +++ b/docs/_static/class_hierarchy.html @@ -380,8 +380,8 @@
// parsing and collecting nodes and edges from the python - nodes = new vis.DataSet([{"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoRuleBaseClass", "label": "PyomoRuleBaseClass", "shape": "hexagon", "size": 19.5, "title": "PyomoRuleBaseClass\ncontrol/control_rules/pyomo_rule_baseclass.py\n[Control / General]", "x": 654.0, "y": 0.0}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoDispatchGenericConverter", "label": "PyomoDispatchGenericConverter", "shape": "dot", "size": 18.0, "title": "PyomoDispatchGenericConverter\ncontrol/control_rules/converters/generic_converter.py\n[Converter / Other]", "x": 354.00000000000006, "y": 519.6152422706632}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoRuleStorageBaseclass", "label": "PyomoRuleStorageBaseclass", "shape": "diamond", "size": 18.0, "title": "PyomoRuleStorageBaseclass\ncontrol/control_rules/storage/pyomo_storage_rule_baseclass.py\n[Storage / General]", "x": 354.00000000000006, "y": -519.6152422706632}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HeuristicLoadFollowingController", "label": "HeuristicLoadFollowingController", "shape": "hexagon", "size": 18.0, "title": "HeuristicLoadFollowingController\ncontrol/control_strategies/heuristic_pyomo_controller.py\n[Control / General]", "x": 681.5146849936184, "y": 83.93066263524416}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OptimizedDispatchController", "label": "OptimizedDispatchController", "shape": "hexagon", "size": 18.0, "title": "OptimizedDispatchController\ncontrol/control_strategies/optimized_pyomo_controller.py\n[Control / General]", "x": 595.9704659224221, "y": 137.9411572197277}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoControllerBaseClass", "label": "PyomoControllerBaseClass", "shape": "hexagon", "size": 19.5, "title": "PyomoControllerBaseClass\ncontrol/control_strategies/pyomo_controller_baseclass.py\n[Control / General]", "x": 490.497033242125, "y": 100.30628231184586}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DemandOpenLoopConverterController", "label": "DemandOpenLoopConverterController", "shape": "dot", "size": 18.0, "title": "DemandOpenLoopConverterController\ncontrol/control_strategies/converters/demand_openloop_converter_controller.py\n[Converter / Other]", "x": 381.5146849936184, "y": 603.5459049059074}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "FlexibleDemandOpenLoopConverterController", "label": "FlexibleDemandOpenLoopConverterController", "shape": "dot", "size": 18.0, "title": "FlexibleDemandOpenLoopConverterController\ncontrol/control_strategies/converters/flexible_demand_openloop_controller.py\n[Converter / Other]", "x": 295.9704659224222, "y": 657.556399490391}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ConverterOpenLoopControlBase", "label": "ConverterOpenLoopControlBase", "shape": "dot", "size": 19.5, "title": "ConverterOpenLoopControlBase\ncontrol/control_strategies/converters/openloop_controller_base.py\n[Converter / Other]", "x": 190.49703324212504, "y": 619.921524582509}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DemandOpenLoopStorageController", "label": "DemandOpenLoopStorageController", "shape": "diamond", "size": 18.0, "title": "DemandOpenLoopStorageController\ncontrol/control_strategies/storage/demand_openloop_storage_controller.py\n[Storage / General]", "x": 381.5146849936184, "y": -435.684579635419}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StorageOpenLoopControlBase", "label": "StorageOpenLoopControlBase", "shape": "diamond", "size": 19.5, "title": "StorageOpenLoopControlBase\ncontrol/control_strategies/storage/openloop_storage_control_base.py\n[Storage / General]", "x": 295.9704659224222, "y": -381.6740850509355}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleStorageOpenLoopController", "label": "SimpleStorageOpenLoopController", "shape": "diamond", "size": 18.0, "title": "SimpleStorageOpenLoopController\ncontrol/control_strategies/storage/simple_openloop_controller.py\n[Storage / General]", "x": 190.49703324212504, "y": -419.30895995881735}, {"borderWidth": 4.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GenericConverterCostModel", "label": "GenericConverterCostModel", "shape": "dot", "size": 18.0, "title": "GenericConverterCostModel\nconverters/generic_converter_cost.py\n[Converter / Other]", "x": 145.46396870697228, "y": 510.5789248680738}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AmmoniaSynLoopPerformanceModel", "label": "AmmoniaSynLoopPerformanceModel", "shape": "dot", "size": 18.0, "title": "AmmoniaSynLoopPerformanceModel\nconverters/ammonia/ammonia_synloop.py\n[Converter / Ammonia]", "x": 196.07066428268575, "y": 399.2836455167026}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AmmoniaSynLoopCostModel", "label": "AmmoniaSynLoopCostModel", "shape": "dot", "size": 18.0, "title": "AmmoniaSynLoopCostModel\nconverters/ammonia/ammonia_synloop.py\n[Converter / Ammonia]", "x": 314.1748353171905, "y": 358.23657563925707}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleAmmoniaPerformanceModel", "label": "SimpleAmmoniaPerformanceModel", "shape": "dot", "size": 18.0, "title": "SimpleAmmoniaPerformanceModel\nconverters/ammonia/simple_ammonia_model.py\n[Converter / Ammonia]", "x": 427.3866955453086, "y": 415.9296970001345}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleAmmoniaCostModel", "label": "SimpleAmmoniaCostModel", "shape": "dot", "size": 18.0, "title": "SimpleAmmoniaCostModel\nconverters/ammonia/simple_ammonia_model.py\n[Converter / Ammonia]", "x": 464.86869651385996, "y": 538.9624102758452}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DOCPerformanceModel", "label": "DOCPerformanceModel", "shape": "dot", "size": 18.0, "title": "DOCPerformanceModel\nconverters/co2/marine/direct_ocean_capture.py\n[Converter / CO2]", "x": 401.8380100526995, "y": 652.4752426790114}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DOCCostModel", "label": "DOCCostModel", "shape": "dot", "size": 18.0, "title": "DOCCostModel\nconverters/co2/marine/direct_ocean_capture.py\n[Converter / CO2]", "x": 275.4766306653483, "y": 686.367077656095}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OAEPerformanceModel", "label": "OAEPerformanceModel", "shape": "dot", "size": 18.0, "title": "OAEPerformanceModel\nconverters/co2/marine/ocean_alkalinity_enhancement.py\n[Converter / CO2]", "x": 162.51973411654936, "y": 618.7587064658168}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OAECostModel", "label": "OAECostModel", "shape": "dot", "size": 18.0, "title": "OAECostModel\nconverters/co2/marine/ocean_alkalinity_enhancement.py\n[Converter / CO2]", "x": 132.30008363629267, "y": 489.9260504531493}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OAECostAndFinancialModel", "label": "OAECostAndFinancialModel", "shape": "dot", "size": 18.0, "title": "OAECostAndFinancialModel\nconverters/co2/marine/ocean_alkalinity_enhancement.py\n[Converter / CO2]", "x": 204.07169197994392, "y": 378.05691605701645}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GridPerformanceModel", "label": "GridPerformanceModel", "shape": "dot", "size": 18.0, "title": "GridPerformanceModel\nconverters/grid/grid.py\n[Converter / Grid]", "x": 334.8356346312979, "y": 351.5883439482972}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GridCostModel", "label": "GridCostModel", "shape": "dot", "size": 18.0, "title": "GridCostModel\nconverters/grid/grid.py\n[Converter / Grid]", "x": 445.2483626468303, "y": 427.2576287598383}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HOPPComponent", "label": "HOPPComponent", "shape": "dot", "size": 18.0, "title": "HOPPComponent\nconverters/hopp/hopp_wrapper.py\n[Converter / HOPP]", "x": 467.89945575036916, "y": 559.5711144381876}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "BasicElectrolyzerCostModel", "label": "BasicElectrolyzerCostModel", "shape": "dot", "size": 18.0, "title": "BasicElectrolyzerCostModel\nconverters/hydrogen/basic_cost_model.py\n[Converter / Hydrogen]", "x": 388.52479069439454, "y": 668.2502362408371}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CustomElectrolyzerCostModel", "label": "CustomElectrolyzerCostModel", "shape": "dot", "size": 18.0, "title": "CustomElectrolyzerCostModel\nconverters/hydrogen/custom_electrolyzer_cost_model.py\n[Converter / Hydrogen]", "x": 254.95587519115207, "y": 687.0298062682064}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectrolyzerPerformanceBaseClass", "label": "ElectrolyzerPerformanceBaseClass", "shape": "dot", "size": 18.75, "title": "ElectrolyzerPerformanceBaseClass\nconverters/hydrogen/electrolyzer_baseclass.py\n[Converter / Hydrogen]", "x": 148.23188605097528, "y": 604.1026945245679}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectrolyzerCostBaseClass", "label": "ElectrolyzerCostBaseClass", "shape": "dot", "size": 20.25, "title": "ElectrolyzerCostBaseClass\nconverters/hydrogen/electrolyzer_baseclass.py\n[Converter / Hydrogen]", "x": 133.36725042373115, "y": 469.52006517094185}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "LinearH2FuelCellPerformanceModel", "label": "LinearH2FuelCellPerformanceModel", "shape": "dot", "size": 18.0, "title": "LinearH2FuelCellPerformanceModel\nconverters/hydrogen/h2_fuel_cell.py\n[Converter / Hydrogen]", "x": 219.71628617567444, "y": 364.9365146910501}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "H2FuelCellCostModel", "label": "H2FuelCellCostModel", "shape": "dot", "size": 18.0, "title": "H2FuelCellCostModel\nconverters/hydrogen/h2_fuel_cell.py\n[Converter / Hydrogen]", "x": 355.1041492280802, "y": 354.021250329648}, {"borderWidth": 2.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ECOElectrolyzerPerformanceModel", "label": "ECOElectrolyzerPerformanceModel", "shape": "dot", "size": 18.75, "title": "ECOElectrolyzerPerformanceModel\nconverters/hydrogen/pem_electrolyzer.py\n[Converter / Hydrogen]", "x": 457.3868701242386, "y": 443.67489981359984}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SingliticoCostModel", "label": "SingliticoCostModel", "shape": "dot", "size": 18.0, "title": "SingliticoCostModel\nconverters/hydrogen/singlitico_cost_model.py\n[Converter / Hydrogen]", "x": 464.32599185808436, "y": 579.6816222169927}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteamMethaneReformerPerformanceModel", "label": "SteamMethaneReformerPerformanceModel", "shape": "dot", "size": 18.0, "title": "SteamMethaneReformerPerformanceModel\nconverters/hydrogen/steam_methane_reformer.py\n[Converter / Hydrogen]", "x": 371.4771426730072, "y": 679.5211142634946}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteamMethaneReformerCostModel", "label": "SteamMethaneReformerCostModel", "shape": "dot", "size": 18.0, "title": "SteamMethaneReformerCostModel\nconverters/hydrogen/steam_methane_reformer.py\n[Converter / Hydrogen]", "x": 235.02263686980024, "y": 682.4640066455394}, {"borderWidth": 1, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WOMBATElectrolyzerModel", "label": "WOMBATElectrolyzerModel", "shape": "dot", "size": 18.0, "title": "WOMBATElectrolyzerModel\nconverters/hydrogen/wombat_model.py\n[Converter / Hydrogen]", "x": 137.75520350257173, "y": 586.5247035561051}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AspenGeoH2SurfacePerformanceModel", "label": "AspenGeoH2SurfacePerformanceModel", "shape": "dot", "size": 18.0, "title": "AspenGeoH2SurfacePerformanceModel\nconverters/hydrogen/geologic/aspen_surface_processing.py\n[Converter / Hydrogen]", "x": 138.82266933071406, "y": 449.78253020788407}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AspenGeoH2SurfaceCostModel", "label": "AspenGeoH2SurfaceCostModel", "shape": "dot", "size": 18.0, "title": "AspenGeoH2SurfaceCostModel\nconverters/hydrogen/geologic/aspen_surface_processing.py\n[Converter / Hydrogen]", "x": 237.75031112092074, "y": 355.20533917946307}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SubsurfacePerformanceBaseClass", "label": "GeoH2SubsurfacePerformanceBaseClass", "shape": "dot", "size": 19.5, "title": "GeoH2SubsurfacePerformanceBaseClass\nconverters/hydrogen/geologic/h2_well_subsurface_baseclass.py\n[Converter / Hydrogen]", "x": 374.6281389037414, "y": 360.29187496794947}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SubsurfaceCostBaseClass", "label": "GeoH2SubsurfaceCostBaseClass", "shape": "dot", "size": 18.75, "title": "GeoH2SubsurfaceCostBaseClass\nconverters/hydrogen/geologic/h2_well_subsurface_baseclass.py\n[Converter / Hydrogen]", "x": 466.4055623972124, "y": 462.10704538085054}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SurfacePerformanceBaseClass", "label": "GeoH2SurfacePerformanceBaseClass", "shape": "dot", "size": 18.75, "title": "GeoH2SurfacePerformanceBaseClass\nconverters/hydrogen/geologic/h2_well_surface_baseclass.py\n[Converter / Hydrogen]", "x": 457.29625514695636, "y": 598.974685153}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SurfaceCostBaseClass", "label": "GeoH2SurfaceCostBaseClass", "shape": "dot", "size": 18.75, "title": "GeoH2SurfaceCostBaseClass\nconverters/hydrogen/geologic/h2_well_surface_baseclass.py\n[Converter / Hydrogen]", "x": 352.69394266907716, "y": 687.8500909879936}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SubsurfaceCostModel", "label": "GeoH2SubsurfaceCostModel", "shape": "dot", "size": 18.0, "title": "GeoH2SubsurfaceCostModel\nconverters/hydrogen/geologic/mathur_modified.py\n[Converter / Hydrogen]", "x": 215.97749629487083, "y": 674.7190103458506}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGeoH2PerformanceModel", "label": "NaturalGeoH2PerformanceModel", "shape": "dot", "size": 18.0, "title": "NaturalGeoH2PerformanceModel\nconverters/hydrogen/geologic/simple_natural_geoh2.py\n[Converter / Hydrogen]", "x": 130.10006459565557, "y": 567.4301139070021}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StimulatedGeoH2PerformanceModel", "label": "StimulatedGeoH2PerformanceModel", "shape": "dot", "size": 18.0, "title": "StimulatedGeoH2PerformanceModel\nconverters/hydrogen/geologic/templeton_serpentinization.py\n[Converter / Hydrogen]", "x": 147.24746231494296, "y": 431.00196408502995}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HumbertEwinPerformanceComponent", "label": "HumbertEwinPerformanceComponent", "shape": "dot", "size": 18.0, "title": "HumbertEwinPerformanceComponent\nconverters/iron/humbert_ewin_perf.py\n[Converter / Iron]", "x": 257.1218087348483, "y": 348.2128765835568}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HumbertStinnEwinCostComponent", "label": "HumbertStinnEwinCostComponent", "shape": "dot", "size": 18.0, "title": "HumbertStinnEwinCostComponent\nconverters/iron/humbert_stinn_ewin_cost.py\n[Converter / Iron]", "x": 393.127798919391, "y": 369.3668678529177}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "IronReductionPlantBasePerformanceComponent", "label": "IronReductionPlantBasePerformanceComponent", "shape": "dot", "size": 19.5, "title": "IronReductionPlantBasePerformanceComponent\nconverters/iron/iron_dri_base.py\n[Converter / Iron]", "x": 472.7432425021856, "y": 481.72468051933606}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "IronReductionPlantBaseCostComponent", "label": "IronReductionPlantBaseCostComponent", "shape": "dot", "size": 19.5, "title": "IronReductionPlantBaseCostComponent\nconverters/iron/iron_dri_base.py\n[Converter / Iron]", "x": 447.5964940759568, "y": 617.1774165566931}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenIronReductionPlantCostComponent", "label": "HydrogenIronReductionPlantCostComponent", "shape": "dot", "size": 18.0, "title": "HydrogenIronReductionPlantCostComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 332.8582311277839, "y": 693.5386065641161}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasIronReductionPlantCostComponent", "label": "NaturalGasIronReductionPlantCostComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasIronReductionPlantCostComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 198.08741067383664, "y": 664.4169227814615}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenIronReductionPlantPerformanceComponent", "label": "HydrogenIronReductionPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "HydrogenIronReductionPlantPerformanceComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 125.05667606340373, "y": 547.4023747662839}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasIronReductionPlantPerformanceComponent", "label": "NaturalGasIronReductionPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasIronReductionPlantPerformanceComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 158.13159569226642, "y": 413.4399350698954}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "IronTransportCostComponent", "label": "IronTransportCostComponent", "shape": "dot", "size": 18.0, "title": "IronTransportCostComponent\nconverters/iron/iron_transport.py\n[Converter / Iron]", "x": 277.3170451038727, "y": 343.8116602929422}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MartinIronMineCostComponent", "label": "MartinIronMineCostComponent", "shape": "dot", "size": 18.0, "title": "MartinIronMineCostComponent\nconverters/iron/martin_mine_cost_model.py\n[Converter / Iron]", "x": 410.34667103931827, "y": 380.8143317189373}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MartinIronMinePerformanceComponent", "label": "MartinIronMinePerformanceComponent", "shape": "dot", "size": 18.0, "title": "MartinIronMinePerformanceComponent\nconverters/iron/martin_mine_perf_model.py\n[Converter / Iron]", "x": 476.5045216453125, "y": 502.0640467626806}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CO2HMethanolPlantPerformanceModel", "label": "CO2HMethanolPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "CO2HMethanolPlantPerformanceModel\nconverters/methanol/co2h_methanol_plant.py\n[Converter / Methanol]", "x": 435.6032844812971, "y": 634.0383483160249}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CO2HMethanolPlantCostModel", "label": "CO2HMethanolPlantCostModel", "shape": "dot", "size": 18.0, "title": "CO2HMethanolPlantCostModel\nconverters/methanol/co2h_methanol_plant.py\n[Converter / Methanol]", "x": 312.397198395929, "y": 696.6617329784204}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CO2HMethanolPlantFinanceModel", "label": "CO2HMethanolPlantFinanceModel", "shape": "dot", "size": 18.0, "title": "CO2HMethanolPlantFinanceModel\nconverters/methanol/co2h_methanol_plant.py\n[Converter / Methanol]", "x": 181.59887823138087, "y": 651.8947433487028}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MethanolPerformanceBaseClass", "label": "MethanolPerformanceBaseClass", "shape": "dot", "size": 19.5, "title": "MethanolPerformanceBaseClass\nconverters/methanol/methanol_baseclass.py\n[Converter / Methanol]", "x": 122.57016631214177, "y": 526.8414257008284}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MethanolCostBaseClass", "label": "MethanolCostBaseClass", "shape": "dot", "size": 19.5, "title": "MethanolCostBaseClass\nconverters/methanol/methanol_baseclass.py\n[Converter / Methanol]", "x": 171.16653718660294, "y": 397.3379277912476}, {"borderWidth": 5.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MethanolFinanceBaseClass", "label": "MethanolFinanceBaseClass", "shape": "dot", "size": 19.5, "title": "MethanolFinanceBaseClass\nconverters/methanol/methanol_baseclass.py\n[Converter / Methanol]", "x": 297.9567320757243, "y": 341.96032536534904}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SMRMethanolPlantPerformanceModel", "label": "SMRMethanolPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "SMRMethanolPlantPerformanceModel\nconverters/methanol/smr_methanol_plant.py\n[Converter / Methanol]", "x": 426.0483695992057, "y": 394.3462137236294}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SMRMethanolPlantCostModel", "label": "SMRMethanolPlantCostModel", "shape": "dot", "size": 18.0, "title": "SMRMethanolPlantCostModel\nconverters/methanol/smr_methanol_plant.py\n[Converter / Methanol]", "x": 477.7221481121271, "y": 522.7617594581504}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SMRMethanolPlantFinanceModel", "label": "SMRMethanolPlantFinanceModel", "shape": "dot", "size": 18.0, "title": "SMRMethanolPlantFinanceModel\nconverters/methanol/smr_methanol_plant.py\n[Converter / Methanol]", "x": 421.5900357312307, "y": 649.3263064239829}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasProducerPerformance", "label": "SimpleGasProducerPerformance", "shape": "dot", "size": 18.0, "title": "SimpleGasProducerPerformance\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 291.6617846858414, "y": 697.2472342697002}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasConsumerPerformance", "label": "SimpleGasConsumerPerformance", "shape": "dot", "size": 18.0, "title": "SimpleGasConsumerPerformance\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 166.7377307793895, "y": 637.4155597628255}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasProducerCost", "label": "SimpleGasProducerCost", "shape": "dot", "size": 18.0, "title": "SimpleGasProducerCost\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 122.61501748970383, "y": 506.0883069258821}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasConsumerCost", "label": "SimpleGasConsumerCost", "shape": "dot", "size": 18.0, "title": "SimpleGasConsumerCost\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 186.0962842524805, "y": 382.9162899098914}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasPerformanceModel", "label": "NaturalGasPerformanceModel", "shape": "dot", "size": 18.0, "title": "NaturalGasPerformanceModel\nconverters/natural_gas/natural_gas_cc_ct.py\n[Converter / Natural Gas]", "x": 318.70784523855275, "y": 342.6335096083759}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasCostModel", "label": "NaturalGasCostModel", "shape": "dot", "size": 18.0, "title": "NaturalGasCostModel\nconverters/natural_gas/natural_gas_cc_ct.py\n[Converter / Natural Gas]", "x": 440.01818000446065, "y": 409.711151044547}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleASUPerformanceModel", "label": "SimpleASUPerformanceModel", "shape": "dot", "size": 18.0, "title": "SimpleASUPerformanceModel\nconverters/nitrogen/simple_ASU.py\n[Converter / Nitrogen]", "x": 476.4229423877047, "y": 543.4914097987054}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleASUCostModel", "label": "SimpleASUCostModel", "shape": "dot", "size": 18.0, "title": "SimpleASUCostModel\nconverters/nitrogen/simple_ASU.py\n[Converter / Nitrogen]", "x": 405.8053310426993, "y": 662.8323620651722}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "QuinnNuclearPerformanceModel", "label": "QuinnNuclearPerformanceModel", "shape": "dot", "size": 18.0, "title": "QuinnNuclearPerformanceModel\nconverters/nuclear/nuclear_plant.py\n[Converter / Nuclear]", "x": 270.9728236746558, "y": 695.3246470713278}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "QuinnNuclearCostModel", "label": "QuinnNuclearCostModel", "shape": "dot", "size": 18.0, "title": "QuinnNuclearCostModel\nconverters/nuclear/nuclear_plant.py\n[Converter / Nuclear]", "x": 153.70695713111738, "y": 621.2265965964602}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBResComPVCostModel", "label": "ATBResComPVCostModel", "shape": "dot", "size": 18.0, "title": "ATBResComPVCostModel\nconverters/solar/atb_res_com_pv_cost.py\n[Converter / Solar]", "x": 125.15798881477986, "y": 485.45904675387027}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBUtilityPVCostModel", "label": "ATBUtilityPVCostModel", "shape": "dot", "size": 18.0, "title": "ATBUtilityPVCostModel\nconverters/solar/atb_utility_pv_cost.py\n[Converter / Solar]", "x": 202.6738837183378, "y": 370.3719161929008}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SolarPerformanceBaseClass", "label": "SolarPerformanceBaseClass", "shape": "dot", "size": 18.75, "title": "SolarPerformanceBaseClass\nconverters/solar/solar_baseclass.py\n[Converter / Solar]", "x": 339.2585979029505, "y": 345.79348732987785}, {"borderWidth": 3.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PYSAMSolarPlantPerformanceModel", "label": "PYSAMSolarPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "PYSAMSolarPlantPerformanceModel\nconverters/solar/solar_pysam.py\n[Converter / Solar]", "x": 452.065454128473, "y": 426.66163127900427}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelPerformanceModel", "label": "SteelPerformanceModel", "shape": "dot", "size": 18.0, "title": "SteelPerformanceModel\nconverters/steel/steel.py\n[Converter / Steel]", "x": 472.649734666257, "y": 563.9450473646525}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelCostAndFinancialModel", "label": "SteelCostAndFinancialModel", "shape": "dot", "size": 18.0, "title": "SteelCostAndFinancialModel\nconverters/steel/steel.py\n[Converter / Steel]", "x": 388.49787317589113, "y": 674.3722639236605}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelPerformanceBaseClass", "label": "SteelPerformanceBaseClass", "shape": "dot", "size": 18.75, "title": "SteelPerformanceBaseClass\nconverters/steel/steel_baseclass.py\n[Converter / Steel]", "x": 250.63471198908354, "y": 690.9423987961834}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelCostBaseClass", "label": "SteelCostBaseClass", "shape": "dot", "size": 18.75, "title": "SteelCostBaseClass\nconverters/steel/steel_baseclass.py\n[Converter / Steel]", "x": 142.68426480640017, "y": 603.5782213775121}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectricArcFurnacePlantBasePerformanceComponent", "label": "ElectricArcFurnacePlantBasePerformanceComponent", "shape": "dot", "size": 19.5, "title": "ElectricArcFurnacePlantBasePerformanceComponent\nconverters/steel/steel_eaf_base.py\n[Converter / Steel]", "x": 130.14466399280232, "y": 465.25467439672315}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectricArcFurnacePlantBaseCostComponent", "label": "ElectricArcFurnacePlantBaseCostComponent", "shape": "dot", "size": 19.5, "title": "ElectricArcFurnacePlantBaseCostComponent\nconverters/steel/steel_eaf_base.py\n[Converter / Steel]", "x": 220.6469531807619, "y": 359.87582716793}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenEAFPlantCostComponent", "label": "HydrogenEAFPlantCostComponent", "shape": "dot", "size": 18.0, "title": "HydrogenEAFPlantCostComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 359.31121758299275, "y": 351.37954310208585}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasEAFPlantCostComponent", "label": "NaturalGasEAFPlantCostComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasEAFPlantCostComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 462.0259973538852, "y": 444.94300653746575}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenEAFPlantPerformanceComponent", "label": "HydrogenEAFPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "HydrogenEAFPlantPerformanceComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 466.469783435919, "y": 583.8281056844546}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasEAFPlantPerformanceComponent", "label": "NaturalGasEAFPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasEAFPlantPerformanceComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 369.92474578553976, "y": 683.7887775311128}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ReverseOsmosisPerformanceModel", "label": "ReverseOsmosisPerformanceModel", "shape": "dot", "size": 18.0, "title": "ReverseOsmosisPerformanceModel\nconverters/water/desal/desalination.py\n[Converter / Water]", "x": 230.93881303278727, "y": 684.1744802901646}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ReverseOsmosisCostModel", "label": "ReverseOsmosisCostModel", "shape": "dot", "size": 18.0, "title": "ReverseOsmosisCostModel\nconverters/water/desal/desalination.py\n[Converter / Water]", "x": 133.81979889995569, "y": 584.7300584166642}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DesalinationPerformanceBaseClass", "label": "DesalinationPerformanceBaseClass", "shape": "dot", "size": 18.75, "title": "DesalinationPerformanceBaseClass\nconverters/water/desal/desalination_baseclass.py\n[Converter / Water]", "x": 137.49417600907128, "y": 445.7633149496428}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DesalinationCostBaseClass", "label": "DesalinationCostBaseClass", "shape": "dot", "size": 18.75, "title": "DesalinationCostBaseClass\nconverters/water/desal/desalination_baseclass.py\n[Converter / Water]", "x": 239.75327641839016, "y": 351.5709546286854}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "RunOfRiverHydroPerformanceModel", "label": "RunOfRiverHydroPerformanceModel", "shape": "dot", "size": 18.0, "title": "RunOfRiverHydroPerformanceModel\nconverters/water_power/hydro_plant_run_of_river.py\n[Converter / Water Power]", "x": 378.58088334190944, "y": 359.30382820899604}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "RunOfRiverHydroCostModel", "label": "RunOfRiverHydroCostModel", "shape": "dot", "size": 18.0, "title": "RunOfRiverHydroCostModel\nconverters/water_power/hydro_plant_run_of_river.py\n[Converter / Water Power]", "x": 469.76420957583946, "y": 464.2904617494691}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PySAMMarineCostModel", "label": "PySAMMarineCostModel", "shape": "dot", "size": 18.0, "title": "PySAMMarineCostModel\nconverters/water_power/pysam_marine_cost.py\n[Converter / Water Power]", "x": 457.9779920949609, "y": 602.8591583936793}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PySAMTidalPerformanceModel", "label": "PySAMTidalPerformanceModel", "shape": "dot", "size": 18.0, "title": "PySAMTidalPerformanceModel\nconverters/water_power/tidal_pysam.py\n[Converter / Water Power]", "x": 350.3533328633538, "y": 690.9537471100347}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBWindPlantCostModel", "label": "ATBWindPlantCostModel", "shape": "dot", "size": 18.0, "title": "ATBWindPlantCostModel\nconverters/wind/atb_wind_cost.py\n[Converter / Wind]", "x": 212.16304848236933, "y": 675.1228946485747}, {"borderWidth": 3.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "FlorisWindPlantPerformanceModel", "label": "FlorisWindPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "FlorisWindPlantPerformanceModel\nconverters/wind/floris.py\n[Converter / Wind]", "x": 127.23416415600352, "y": 564.9519998347746}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindArdPerformanceCompatibilityComponent", "label": "WindArdPerformanceCompatibilityComponent", "shape": "dot", "size": 18.0, "title": "WindArdPerformanceCompatibilityComponent\nconverters/wind/wind_plant_ard.py\n[Converter / Wind]", "x": 147.0974013238951, "y": 427.25925952607975}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindArdCostCompatibilityComponent", "label": "WindArdCostCompatibilityComponent", "shape": "dot", "size": 18.0, "title": "WindArdCostCompatibilityComponent\nconverters/wind/wind_plant_ard.py\n[Converter / Wind]", "x": 259.72053996522834, "y": 345.57025167411484}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindPerformanceBaseClass", "label": "WindPerformanceBaseClass", "shape": "dot", "size": 19.5, "title": "WindPerformanceBaseClass\nconverters/wind/wind_plant_baseclass.py\n[Converter / Wind]", "x": 396.79707304437557, "y": 369.4500991809332}, {"borderWidth": 3.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PYSAMWindPlantPerformanceModel", "label": "PYSAMWindPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "PYSAMWindPlantPerformanceModel\nconverters/wind/wind_pysam.py\n[Converter / Wind]", "x": 475.1748837158849, "y": 484.4293708946534}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "FeedstockCostModel", "label": "FeedstockCostModel", "shape": "ellipse", "size": 18.0, "title": "FeedstockCostModel\ncore/feedstocks.py\n[Core / General]", "x": -245.9999999999999, "y": 519.6152422706632}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PerformanceModelBaseClass", "label": "PerformanceModelBaseClass", "shape": "ellipse", "size": 39.0, "title": "PerformanceModelBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -218.48531500638154, "y": 603.5459049059074}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CostModelBaseClass", "label": "CostModelBaseClass", "shape": "ellipse", "size": 45.0, "title": "CostModelBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -304.02953407757775, "y": 657.556399490391}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ResizeablePerformanceModelBaseClass", "label": "ResizeablePerformanceModelBaseClass", "shape": "ellipse", "size": 19.5, "title": "ResizeablePerformanceModelBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -409.5029667578749, "y": 619.921524582509}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CacheBaseClass", "label": "CacheBaseClass", "shape": "ellipse", "size": 19.5, "title": "CacheBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -454.5360312930277, "y": 510.5789248680738}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SiteBaseComponent", "label": "SiteBaseComponent", "shape": "ellipse", "size": 18.75, "title": "SiteBaseComponent\ncore/sites.py\n[Core / General]", "x": -403.9293357173142, "y": 399.2836455167026}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SiteLocationComponent", "label": "SiteLocationComponent", "shape": "ellipse", "size": 18.0, "title": "SiteLocationComponent\ncore/sites.py\n[Core / General]", "x": -285.82516468280943, "y": 358.23657563925707}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProFastBase", "label": "ProFastBase", "shape": "star", "size": 19.5, "title": "ProFastBase\nfinances/profast_base.py\n[Finance / General]", "x": -546.0, "y": 7.347880794884119e-14}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProFastLCO", "label": "ProFastLCO", "shape": "star", "size": 18.0, "title": "ProFastLCO\nfinances/profast_lco.py\n[Finance / General]", "x": -518.4853150063816, "y": 83.93066263524423}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProFastNPV", "label": "ProFastNPV", "shape": "star", "size": 18.0, "title": "ProFastNPV\nfinances/profast_npv.py\n[Finance / General]", "x": -604.0295340775779, "y": 137.94115721972778}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ResourceBaseAPIModel", "label": "ResourceBaseAPIModel", "shape": "triangle", "size": 19.5, "title": "ResourceBaseAPIModel\nresource/resource_base.py\n[Resource / General]", "x": -246.00000000000028, "y": -519.6152422706631}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NLRDeveloperAPISolarResourceBase", "label": "NLRDeveloperAPISolarResourceBase", "shape": "triangle", "size": 24.75, "title": "NLRDeveloperAPISolarResourceBase\nresource/solar/nlr_developer_api_base.py\n[Resource / General]", "x": -218.48531500638194, "y": -435.6845796354189}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESAggregatedSolarAPI", "label": "GOESAggregatedSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESAggregatedSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -304.02953407757815, "y": -381.6740850509354}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESConusSolarAPI", "label": "GOESConusSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESConusSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -409.5029667578753, "y": -419.30895995881724}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESFullDiscSolarAPI", "label": "GOESFullDiscSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESFullDiscSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -454.53603129302803, "y": -528.6515596732525}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESTMYSolarAPI", "label": "GOESTMYSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESTMYSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -403.9293357173146, "y": -639.9468390246236}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "Himawari7SolarAPI", "label": "Himawari7SolarAPI", "shape": "triangle", "size": 18.0, "title": "Himawari7SolarAPI\nresource/solar/nlr_developer_himawari_api_models.py\n[Resource / General]", "x": -285.8251646828098, "y": -680.9939089020693}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "Himawari8SolarAPI", "label": "Himawari8SolarAPI", "shape": "triangle", "size": 18.0, "title": "Himawari8SolarAPI\nresource/solar/nlr_developer_himawari_api_models.py\n[Resource / General]", "x": -172.61330445469173, "y": -623.3007875411918}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HimawariTMYSolarAPI", "label": "HimawariTMYSolarAPI", "shape": "triangle", "size": 18.0, "title": "HimawariTMYSolarAPI\nresource/solar/nlr_developer_himawari_api_models.py\n[Resource / General]", "x": -135.13130348614035, "y": -500.2680742654811}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MeteosatPrimeMeridianSolarAPI", "label": "MeteosatPrimeMeridianSolarAPI", "shape": "triangle", "size": 18.0, "title": "MeteosatPrimeMeridianSolarAPI\nresource/solar/nlr_developer_meteosat_prime_meridian_models.py\n[Resource / General]", "x": -198.16198994730087, "y": -386.75524186231485}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MeteosatPrimeMeridianTMYSolarAPI", "label": "MeteosatPrimeMeridianTMYSolarAPI", "shape": "triangle", "size": 18.0, "title": "MeteosatPrimeMeridianTMYSolarAPI\nresource/solar/nlr_developer_meteosat_prime_meridian_models.py\n[Resource / General]", "x": -324.52336933465205, "y": -352.86340688523126}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OpenMeteoHistoricalSolarResource", "label": "OpenMeteoHistoricalSolarResource", "shape": "triangle", "size": 18.0, "title": "OpenMeteoHistoricalSolarResource\nresource/solar/openmeteo_solar.py\n[Resource / General]", "x": -437.480265883451, "y": -420.47177807550946}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SolarResourceBaseAPIModel", "label": "SolarResourceBaseAPIModel", "shape": "triangle", "size": 19.5, "title": "SolarResourceBaseAPIModel\nresource/solar/solar_resource_base.py\n[Resource / General]", "x": -467.69991636370764, "y": -549.304434088177}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WTKNLRDeveloperAPIWindResource", "label": "WTKNLRDeveloperAPIWindResource", "shape": "triangle", "size": 18.0, "title": "WTKNLRDeveloperAPIWindResource\nresource/wind/nlr_developer_wtk_api.py\n[Resource / General]", "x": -395.9283080200564, "y": -661.1735684843098}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OpenMeteoHistoricalWindResource", "label": "OpenMeteoHistoricalWindResource", "shape": "triangle", "size": 18.0, "title": "OpenMeteoHistoricalWindResource\nresource/wind/openmeteo_wind.py\n[Resource / General]", "x": -265.1643653687024, "y": -687.6421405930291}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindResourceBaseAPIModel", "label": "WindResourceBaseAPIModel", "shape": "triangle", "size": 19.5, "title": "WindResourceBaseAPIModel\nresource/wind/wind_resource_base.py\n[Resource / General]", "x": -154.75163735317008, "y": -611.972855781488}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GenericStorageCostModel", "label": "GenericStorageCostModel", "shape": "diamond", "size": 18.0, "title": "GenericStorageCostModel\nstorage/generic_storage_cost.py\n[Storage / General]", "x": 145.46396870697228, "y": -528.6515596732526}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StorageAutoSizingModel", "label": "StorageAutoSizingModel", "shape": "diamond", "size": 18.0, "title": "StorageAutoSizingModel\nstorage/simple_storage_auto_sizing.py\n[Storage / General]", "x": 196.07066428268575, "y": -639.9468390246238}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StoragePerformanceBase", "label": "StoragePerformanceBase", "shape": "diamond", "size": 20.25, "title": "StoragePerformanceBase\nstorage/storage_baseclass.py\n[Storage / General]", "x": 314.1748353171905, "y": -680.9939089020693}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StoragePerformanceModel", "label": "StoragePerformanceModel", "shape": "diamond", "size": 18.0, "title": "StoragePerformanceModel\nstorage/storage_performance_model.py\n[Storage / General]", "x": 427.3866955453086, "y": -623.3007875411919}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBBatteryCostModel", "label": "ATBBatteryCostModel", "shape": "diamond", "size": 18.0, "title": "ATBBatteryCostModel\nstorage/battery/atb_battery_cost.py\n[Storage / General]", "x": 464.86869651385996, "y": -500.26807426548123}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PySAMBatteryPerformanceModel", "label": "PySAMBatteryPerformanceModel", "shape": "diamond", "size": 18.0, "title": "PySAMBatteryPerformanceModel\nstorage/battery/pysam_battery.py\n[Storage / General]", "x": 401.8380100526995, "y": -386.75524186231496}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenStorageBaseCostModel", "label": "HydrogenStorageBaseCostModel", "shape": "diamond", "size": 20.25, "title": "HydrogenStorageBaseCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 275.4766306653483, "y": -352.86340688523137}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "LinedRockCavernStorageCostModel", "label": "LinedRockCavernStorageCostModel", "shape": "diamond", "size": 18.0, "title": "LinedRockCavernStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 162.51973411654936, "y": -420.4717780755096}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SaltCavernStorageCostModel", "label": "SaltCavernStorageCostModel", "shape": "diamond", "size": 18.0, "title": "SaltCavernStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 132.30008363629267, "y": -549.3044340881771}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PipeStorageCostModel", "label": "PipeStorageCostModel", "shape": "diamond", "size": 18.0, "title": "PipeStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 204.07169197994392, "y": -661.17356848431}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MCHTOLStorageCostModel", "label": "MCHTOLStorageCostModel", "shape": "diamond", "size": 18.0, "title": "MCHTOLStorageCostModel\nstorage/hydrogen/mch_storage.py\n[Storage / General]", "x": 334.8356346312979, "y": -687.6421405930291}]); - edges = new vis.DataSet([{"arrows": "to", "from": "PyomoRuleBaseClass", "to": "PyomoDispatchGenericConverter"}, {"arrows": "to", "from": "PyomoRuleBaseClass", "to": "PyomoRuleStorageBaseclass"}, {"arrows": "to", "from": "PyomoControllerBaseClass", "to": "HeuristicLoadFollowingController"}, {"arrows": "to", "from": "PyomoControllerBaseClass", "to": "OptimizedDispatchController"}, {"arrows": "to", "from": "ConverterOpenLoopControlBase", "to": "DemandOpenLoopConverterController"}, {"arrows": "to", "from": "ConverterOpenLoopControlBase", "to": "FlexibleDemandOpenLoopConverterController"}, {"arrows": "to", "from": "StorageOpenLoopControlBase", "to": "DemandOpenLoopStorageController"}, {"arrows": "to", "from": "StorageOpenLoopControlBase", "to": "SimpleStorageOpenLoopController"}, {"arrows": "to", "from": "ElectrolyzerPerformanceBaseClass", "to": "ECOElectrolyzerPerformanceModel"}, {"arrows": "to", "from": "ElectrolyzerCostBaseClass", "to": "BasicElectrolyzerCostModel"}, {"arrows": "to", "from": "ElectrolyzerCostBaseClass", "to": "CustomElectrolyzerCostModel"}, {"arrows": "to", "from": "ElectrolyzerCostBaseClass", "to": "SingliticoCostModel"}, {"arrows": "to", "from": "ECOElectrolyzerPerformanceModel", "to": "WOMBATElectrolyzerModel"}, {"arrows": "to", "from": "GeoH2SubsurfacePerformanceBaseClass", "to": "NaturalGeoH2PerformanceModel"}, {"arrows": "to", "from": "GeoH2SubsurfacePerformanceBaseClass", "to": "StimulatedGeoH2PerformanceModel"}, {"arrows": "to", "from": "GeoH2SubsurfaceCostBaseClass", "to": "GeoH2SubsurfaceCostModel"}, {"arrows": "to", "from": "GeoH2SurfacePerformanceBaseClass", "to": "AspenGeoH2SurfacePerformanceModel"}, {"arrows": "to", "from": "GeoH2SurfaceCostBaseClass", "to": "AspenGeoH2SurfaceCostModel"}, {"arrows": "to", "from": "IronReductionPlantBasePerformanceComponent", "to": "HydrogenIronReductionPlantPerformanceComponent"}, {"arrows": "to", "from": "IronReductionPlantBasePerformanceComponent", "to": "NaturalGasIronReductionPlantPerformanceComponent"}, {"arrows": "to", "from": "IronReductionPlantBaseCostComponent", "to": "HydrogenIronReductionPlantCostComponent"}, {"arrows": "to", "from": "IronReductionPlantBaseCostComponent", "to": "NaturalGasIronReductionPlantCostComponent"}, {"arrows": "to", "from": "MethanolPerformanceBaseClass", "to": "CO2HMethanolPlantPerformanceModel"}, {"arrows": "to", "from": "MethanolPerformanceBaseClass", "to": "SMRMethanolPlantPerformanceModel"}, {"arrows": "to", "from": "MethanolCostBaseClass", "to": "CO2HMethanolPlantCostModel"}, {"arrows": "to", "from": "MethanolCostBaseClass", "to": "SMRMethanolPlantCostModel"}, {"arrows": "to", "from": "MethanolFinanceBaseClass", "to": "CO2HMethanolPlantFinanceModel"}, {"arrows": "to", "from": "MethanolFinanceBaseClass", "to": "SMRMethanolPlantFinanceModel"}, {"arrows": "to", "from": "SolarPerformanceBaseClass", "to": "PYSAMSolarPlantPerformanceModel"}, {"arrows": "to", "from": "SteelPerformanceBaseClass", "to": "SteelPerformanceModel"}, {"arrows": "to", "from": "SteelCostBaseClass", "to": "SteelCostAndFinancialModel"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBasePerformanceComponent", "to": "HydrogenEAFPlantPerformanceComponent"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBasePerformanceComponent", "to": "NaturalGasEAFPlantPerformanceComponent"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBaseCostComponent", "to": "HydrogenEAFPlantCostComponent"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBaseCostComponent", "to": "NaturalGasEAFPlantCostComponent"}, {"arrows": "to", "from": "DesalinationPerformanceBaseClass", "to": "ReverseOsmosisPerformanceModel"}, {"arrows": "to", "from": "DesalinationCostBaseClass", "to": "ReverseOsmosisCostModel"}, {"arrows": "to", "from": "WindPerformanceBaseClass", "to": "FlorisWindPlantPerformanceModel"}, {"arrows": "to", "from": "WindPerformanceBaseClass", "to": "PYSAMWindPlantPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleAmmoniaPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "DOCPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "OAEPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "GridPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "HOPPComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "LinearH2FuelCellPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SteamMethaneReformerPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "GeoH2SubsurfacePerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "GeoH2SurfacePerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "HumbertEwinPerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "IronReductionPlantBasePerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "MartinIronMinePerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "MethanolPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleGasProducerPerformance"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleGasConsumerPerformance"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "NaturalGasPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleASUPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "QuinnNuclearPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SolarPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SteelPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "ElectricArcFurnacePlantBasePerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "DesalinationPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "RunOfRiverHydroPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "PySAMTidalPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "WindArdPerformanceCompatibilityComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "WindPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "ResizeablePerformanceModelBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "StoragePerformanceBase"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GenericConverterCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "AmmoniaSynLoopCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleAmmoniaCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "DOCCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "OAECostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "OAECostAndFinancialModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GridCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ElectrolyzerCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "H2FuelCellCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SteamMethaneReformerCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GeoH2SubsurfaceCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GeoH2SurfaceCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "HumbertStinnEwinCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "IronReductionPlantBaseCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "IronTransportCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "MartinIronMineCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "MethanolCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleGasProducerCost"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleGasConsumerCost"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "NaturalGasCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleASUCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "QuinnNuclearCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBResComPVCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBUtilityPVCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SteelCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ElectricArcFurnacePlantBaseCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "DesalinationCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "RunOfRiverHydroCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "PySAMMarineCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBWindPlantCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "WindArdCostCompatibilityComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "FeedstockCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GenericStorageCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBBatteryCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "HydrogenStorageBaseCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "MCHTOLStorageCostModel"}, {"arrows": "to", "from": "ResizeablePerformanceModelBaseClass", "to": "AmmoniaSynLoopPerformanceModel"}, {"arrows": "to", "from": "ResizeablePerformanceModelBaseClass", "to": "ElectrolyzerPerformanceBaseClass"}, {"arrows": "to", "from": "CacheBaseClass", "to": "HOPPComponent"}, {"arrows": "to", "from": "CacheBaseClass", "to": "FlorisWindPlantPerformanceModel"}, {"arrows": "to", "from": "SiteBaseComponent", "to": "SiteLocationComponent"}, {"arrows": "to", "from": "ProFastBase", "to": "ProFastLCO"}, {"arrows": "to", "from": "ProFastBase", "to": "ProFastNPV"}, {"arrows": "to", "from": "ResourceBaseAPIModel", "to": "SolarResourceBaseAPIModel"}, {"arrows": "to", "from": "ResourceBaseAPIModel", "to": "WindResourceBaseAPIModel"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESAggregatedSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESConusSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESFullDiscSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESTMYSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "Himawari7SolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "Himawari8SolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "HimawariTMYSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "MeteosatPrimeMeridianSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "MeteosatPrimeMeridianTMYSolarAPI"}, {"arrows": "to", "from": "SolarResourceBaseAPIModel", "to": "NLRDeveloperAPISolarResourceBase"}, {"arrows": "to", "from": "SolarResourceBaseAPIModel", "to": "OpenMeteoHistoricalSolarResource"}, {"arrows": "to", "from": "WindResourceBaseAPIModel", "to": "WTKNLRDeveloperAPIWindResource"}, {"arrows": "to", "from": "WindResourceBaseAPIModel", "to": "OpenMeteoHistoricalWindResource"}, {"arrows": "to", "from": "StoragePerformanceBase", "to": "StorageAutoSizingModel"}, {"arrows": "to", "from": "StoragePerformanceBase", "to": "StoragePerformanceModel"}, {"arrows": "to", "from": "StoragePerformanceBase", "to": "PySAMBatteryPerformanceModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "LinedRockCavernStorageCostModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "SaltCavernStorageCostModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "PipeStorageCostModel"}]); + nodes = new vis.DataSet([{"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SiteBaseComponent", "label": "SiteBaseComponent", "shape": "ellipse", "size": 18.710526315789473, "title": "SiteBaseComponent\ncore/sites.py\n[Core / General]", "x": -79.5125603737886, "y": 584.9567473090942}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SiteLocationComponent", "label": "SiteLocationComponent", "shape": "ellipse", "size": 18.0, "title": "SiteLocationComponent\ncore/sites.py\n[Core / General]", "x": -51.99787538017026, "y": 668.8874099443384}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PerformanceModelBaseClass", "label": "PerformanceModelBaseClass", "shape": "ellipse", "size": 40.026315789473685, "title": "PerformanceModelBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -137.54209445136647, "y": 722.897904528822}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CostModelBaseClass", "label": "CostModelBaseClass", "shape": "ellipse", "size": 45.0, "title": "CostModelBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -243.0155271316636, "y": 685.2630296209401}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ResizeablePerformanceModelBaseClass", "label": "ResizeablePerformanceModelBaseClass", "shape": "ellipse", "size": 19.42105263157895, "title": "ResizeablePerformanceModelBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -288.0485916668164, "y": 575.9204299065049}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CacheBaseClass", "label": "CacheBaseClass", "shape": "ellipse", "size": 19.42105263157895, "title": "CacheBaseClass\ncore/model_baseclasses.py\n[Core / General]", "x": -237.4418960911029, "y": 464.62515055513364}, {"borderWidth": 4.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GenericConverterCostModel", "label": "GenericConverterCostModel", "shape": "dot", "size": 18.0, "title": "GenericConverterCostModel\nconverters/generic_converter_cost.py\n[Converter / Other]", "x": 428.09388111524015, "y": 469.0988894808179}, {"borderWidth": 3.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PYSAMSolarPlantPerformanceModel", "label": "PYSAMSolarPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "PYSAMSolarPlantPerformanceModel\nconverters/solar/solar_pysam.py\n[Converter / Solar]", "x": 455.6085661088585, "y": 553.0295521160621}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBUtilityPVCostModel", "label": "ATBUtilityPVCostModel", "shape": "dot", "size": 18.0, "title": "ATBUtilityPVCostModel\nconverters/solar/atb_utility_pv_cost.py\n[Converter / Solar]", "x": 370.0643470376623, "y": 607.0400467005456}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBResComPVCostModel", "label": "ATBResComPVCostModel", "shape": "dot", "size": 18.0, "title": "ATBResComPVCostModel\nconverters/solar/atb_res_com_pv_cost.py\n[Converter / Solar]", "x": 264.59091435736514, "y": 569.4051717926637}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SolarPerformanceBaseClass", "label": "SolarPerformanceBaseClass", "shape": "dot", "size": 18.710526315789473, "title": "SolarPerformanceBaseClass\nconverters/solar/solar_baseclass.py\n[Converter / Solar]", "x": 219.55784982221238, "y": 460.06257207822847}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectrolyzerPerformanceBaseClass", "label": "ElectrolyzerPerformanceBaseClass", "shape": "dot", "size": 18.710526315789473, "title": "ElectrolyzerPerformanceBaseClass\nconverters/hydrogen/electrolyzer_baseclass.py\n[Converter / Hydrogen]", "x": 270.16454539792585, "y": 348.7672927268573}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectrolyzerCostBaseClass", "label": "ElectrolyzerCostBaseClass", "shape": "dot", "size": 20.13157894736842, "title": "ElectrolyzerCostBaseClass\nconverters/hydrogen/electrolyzer_baseclass.py\n[Converter / Hydrogen]", "x": 388.2687164324306, "y": 307.72022284941175}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SingliticoCostModel", "label": "SingliticoCostModel", "shape": "dot", "size": 18.0, "title": "SingliticoCostModel\nconverters/hydrogen/singlitico_cost_model.py\n[Converter / Hydrogen]", "x": 501.4805766605487, "y": 365.4133442102892}, {"borderWidth": 1, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WOMBATElectrolyzerModel", "label": "WOMBATElectrolyzerModel", "shape": "dot", "size": 18.0, "title": "WOMBATElectrolyzerModel\nconverters/hydrogen/wombat_model.py\n[Converter / Hydrogen]", "x": 538.9625776291001, "y": 488.44605748599986}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "LinearH2FuelCellPerformanceModel", "label": "LinearH2FuelCellPerformanceModel", "shape": "dot", "size": 18.0, "title": "LinearH2FuelCellPerformanceModel\nconverters/hydrogen/h2_fuel_cell.py\n[Converter / Hydrogen]", "x": 475.93189116793957, "y": 601.9588898891661}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "H2FuelCellCostModel", "label": "H2FuelCellCostModel", "shape": "dot", "size": 18.0, "title": "H2FuelCellCostModel\nconverters/hydrogen/h2_fuel_cell.py\n[Converter / Hydrogen]", "x": 349.5705117805884, "y": 635.8507248662497}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteamMethaneReformerPerformanceModel", "label": "SteamMethaneReformerPerformanceModel", "shape": "dot", "size": 18.0, "title": "SteamMethaneReformerPerformanceModel\nconverters/hydrogen/steam_methane_reformer.py\n[Converter / Hydrogen]", "x": 236.61361523178945, "y": 568.2423536759715}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteamMethaneReformerCostModel", "label": "SteamMethaneReformerCostModel", "shape": "dot", "size": 18.0, "title": "SteamMethaneReformerCostModel\nconverters/hydrogen/steam_methane_reformer.py\n[Converter / Hydrogen]", "x": 206.39396475153276, "y": 439.409697663304}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "BasicElectrolyzerCostModel", "label": "BasicElectrolyzerCostModel", "shape": "dot", "size": 18.0, "title": "BasicElectrolyzerCostModel\nconverters/hydrogen/basic_cost_model.py\n[Converter / Hydrogen]", "x": 278.165573095184, "y": 327.54056326717114}, {"borderWidth": 2.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ECOElectrolyzerPerformanceModel", "label": "ECOElectrolyzerPerformanceModel", "shape": "dot", "size": 18.710526315789473, "title": "ECOElectrolyzerPerformanceModel\nconverters/hydrogen/pem_electrolyzer.py\n[Converter / Hydrogen]", "x": 408.929515746538, "y": 301.0719911584519}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CustomElectrolyzerCostModel", "label": "CustomElectrolyzerCostModel", "shape": "dot", "size": 18.0, "title": "CustomElectrolyzerCostModel\nconverters/hydrogen/custom_electrolyzer_cost_model.py\n[Converter / Hydrogen]", "x": 519.3422437620703, "y": 376.741275969993}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SubsurfaceCostModel", "label": "GeoH2SubsurfaceCostModel", "shape": "dot", "size": 18.0, "title": "GeoH2SubsurfaceCostModel\nconverters/hydrogen/geologic/mathur_modified.py\n[Converter / Hydrogen]", "x": 541.9933368656093, "y": 509.0547616483423}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SubsurfacePerformanceBaseClass", "label": "GeoH2SubsurfacePerformanceBaseClass", "shape": "dot", "size": 19.42105263157895, "title": "GeoH2SubsurfacePerformanceBaseClass\nconverters/hydrogen/geologic/h2_well_subsurface_baseclass.py\n[Converter / Hydrogen]", "x": 462.61867180963463, "y": 617.7338834509918}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SubsurfaceCostBaseClass", "label": "GeoH2SubsurfaceCostBaseClass", "shape": "dot", "size": 18.710526315789473, "title": "GeoH2SubsurfaceCostBaseClass\nconverters/hydrogen/geologic/h2_well_subsurface_baseclass.py\n[Converter / Hydrogen]", "x": 329.04975630639217, "y": 636.513453478361}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AspenGeoH2SurfacePerformanceModel", "label": "AspenGeoH2SurfacePerformanceModel", "shape": "dot", "size": 18.0, "title": "AspenGeoH2SurfacePerformanceModel\nconverters/hydrogen/geologic/aspen_surface_processing.py\n[Converter / Hydrogen]", "x": 222.32576716621537, "y": 553.5863417347226}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AspenGeoH2SurfaceCostModel", "label": "AspenGeoH2SurfaceCostModel", "shape": "dot", "size": 18.0, "title": "AspenGeoH2SurfaceCostModel\nconverters/hydrogen/geologic/aspen_surface_processing.py\n[Converter / Hydrogen]", "x": 207.46113153897124, "y": 419.00371238109653}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGeoH2PerformanceModel", "label": "NaturalGeoH2PerformanceModel", "shape": "dot", "size": 18.0, "title": "NaturalGeoH2PerformanceModel\nconverters/hydrogen/geologic/simple_natural_geoh2.py\n[Converter / Hydrogen]", "x": 293.81016729091453, "y": 314.4201619012048}, {"borderWidth": 3.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StimulatedGeoH2PerformanceModel", "label": "StimulatedGeoH2PerformanceModel", "shape": "dot", "size": 18.0, "title": "StimulatedGeoH2PerformanceModel\nconverters/hydrogen/geologic/templeton_serpentinization.py\n[Converter / Hydrogen]", "x": 429.1980303433203, "y": 303.5048975398027}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SurfacePerformanceBaseClass", "label": "GeoH2SurfacePerformanceBaseClass", "shape": "dot", "size": 18.710526315789473, "title": "GeoH2SurfacePerformanceBaseClass\nconverters/hydrogen/geologic/h2_well_surface_baseclass.py\n[Converter / Hydrogen]", "x": 531.4807512394786, "y": 393.1585470237545}, {"borderWidth": 4.0, "color": {"background": "#2E7D32", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GeoH2SurfaceCostBaseClass", "label": "GeoH2SurfaceCostBaseClass", "shape": "dot", "size": 18.710526315789473, "title": "GeoH2SurfaceCostBaseClass\nconverters/hydrogen/geologic/h2_well_surface_baseclass.py\n[Converter / Hydrogen]", "x": 538.4198729733245, "y": 529.1652694271473}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ReverseOsmosisPerformanceModel", "label": "ReverseOsmosisPerformanceModel", "shape": "dot", "size": 18.0, "title": "ReverseOsmosisPerformanceModel\nconverters/water/desal/desalination.py\n[Converter / Water]", "x": 445.5710237882473, "y": 629.0047614736493}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ReverseOsmosisCostModel", "label": "ReverseOsmosisCostModel", "shape": "dot", "size": 18.0, "title": "ReverseOsmosisCostModel\nconverters/water/desal/desalination.py\n[Converter / Water]", "x": 309.11651798504033, "y": 631.947653855694}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DesalinationPerformanceBaseClass", "label": "DesalinationPerformanceBaseClass", "shape": "dot", "size": 18.710526315789473, "title": "DesalinationPerformanceBaseClass\nconverters/water/desal/desalination_baseclass.py\n[Converter / Water]", "x": 211.84908461781183, "y": 536.0083507662598}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DesalinationCostBaseClass", "label": "DesalinationCostBaseClass", "shape": "dot", "size": 18.710526315789473, "title": "DesalinationCostBaseClass\nconverters/water/desal/desalination_baseclass.py\n[Converter / Water]", "x": 212.91655044595416, "y": 399.26617741803875}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "QuinnNuclearPerformanceModel", "label": "QuinnNuclearPerformanceModel", "shape": "dot", "size": 18.0, "title": "QuinnNuclearPerformanceModel\nconverters/nuclear/nuclear_plant.py\n[Converter / Nuclear]", "x": 311.84419223616084, "y": 304.68898638961775}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "QuinnNuclearCostModel", "label": "QuinnNuclearCostModel", "shape": "dot", "size": 18.0, "title": "QuinnNuclearCostModel\nconverters/nuclear/nuclear_plant.py\n[Converter / Nuclear]", "x": 448.7220200189815, "y": 309.77552217810415}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CMUElectricArcFurnaceCostModel", "label": "CMUElectricArcFurnaceCostModel", "shape": "dot", "size": 18.0, "title": "CMUElectricArcFurnaceCostModel\nconverters/steel/cmu_eaf_cost.py\n[Converter / Steel]", "x": 540.4994435124524, "y": 411.5906925910052}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenEAFPlantCostComponent", "label": "HydrogenEAFPlantCostComponent", "shape": "dot", "size": 18.0, "title": "HydrogenEAFPlantCostComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 531.3901362621964, "y": 548.4583323631547}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasEAFPlantCostComponent", "label": "NaturalGasEAFPlantCostComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasEAFPlantCostComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 426.78782378431725, "y": 637.3337381981482}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenEAFPlantPerformanceComponent", "label": "HydrogenEAFPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "HydrogenEAFPlantPerformanceComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 290.0713774101109, "y": 624.2026575560053}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasEAFPlantPerformanceComponent", "label": "NaturalGasEAFPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasEAFPlantPerformanceComponent\nconverters/steel/steel_eaf_plant.py\n[Converter / Steel]", "x": 204.19394571089566, "y": 516.9137611171568}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CMUElectricArcFurnaceScrapOnlyPerformanceComponent", "label": "CMUElectricArcFurnaceScrapOnlyPerformanceComponent", "shape": "dot", "size": 18.0, "title": "CMUElectricArcFurnaceScrapOnlyPerformanceComponent\nconverters/steel/cmu_electric_arc_furnace_scrap.py\n[Converter / Steel]", "x": 221.34134343018306, "y": 380.48561129518464}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectricArcFurnacePlantBasePerformanceComponent", "label": "ElectricArcFurnacePlantBasePerformanceComponent", "shape": "dot", "size": 19.42105263157895, "title": "ElectricArcFurnacePlantBasePerformanceComponent\nconverters/steel/steel_eaf_base.py\n[Converter / Steel]", "x": 331.21568985008844, "y": 297.6965237937115}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ElectricArcFurnacePlantBaseCostComponent", "label": "ElectricArcFurnacePlantBaseCostComponent", "shape": "dot", "size": 19.42105263157895, "title": "ElectricArcFurnacePlantBaseCostComponent\nconverters/steel/steel_eaf_base.py\n[Converter / Steel]", "x": 467.2216800346311, "y": 318.8505150630724}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CMUElectricArcFurnaceDRIPerformanceComponent", "label": "CMUElectricArcFurnaceDRIPerformanceComponent", "shape": "dot", "size": 18.0, "title": "CMUElectricArcFurnaceDRIPerformanceComponent\nconverters/steel/cmu_electric_arc_furnace_dri.py\n[Converter / Steel]", "x": 546.8371236174256, "y": 431.20832772949075}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelPerformanceBaseClass", "label": "SteelPerformanceBaseClass", "shape": "dot", "size": 18.710526315789473, "title": "SteelPerformanceBaseClass\nconverters/steel/steel_baseclass.py\n[Converter / Steel]", "x": 521.6903751911968, "y": 566.6610637668477}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelCostBaseClass", "label": "SteelCostBaseClass", "shape": "dot", "size": 18.710526315789473, "title": "SteelCostBaseClass\nconverters/steel/steel_baseclass.py\n[Converter / Steel]", "x": 406.952112243024, "y": 643.0222537742708}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelPerformanceModel", "label": "SteelPerformanceModel", "shape": "dot", "size": 18.0, "title": "SteelPerformanceModel\nconverters/steel/steel.py\n[Converter / Steel]", "x": 272.18129178907674, "y": 613.9005699916162}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SteelCostAndFinancialModel", "label": "SteelCostAndFinancialModel", "shape": "dot", "size": 18.0, "title": "SteelCostAndFinancialModel\nconverters/steel/steel.py\n[Converter / Steel]", "x": 199.15055717864382, "y": 496.88602197643854}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleASUPerformanceModel", "label": "SimpleASUPerformanceModel", "shape": "dot", "size": 18.0, "title": "SimpleASUPerformanceModel\nconverters/nitrogen/simple_ASU.py\n[Converter / Nitrogen]", "x": 232.2254768075065, "y": 362.9235822800501}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleASUCostModel", "label": "SimpleASUCostModel", "shape": "dot", "size": 18.0, "title": "SimpleASUCostModel\nconverters/nitrogen/simple_ASU.py\n[Converter / Nitrogen]", "x": 351.4109262191128, "y": 293.29530750309686}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBWindPlantCostModel", "label": "ATBWindPlantCostModel", "shape": "dot", "size": 18.0, "title": "ATBWindPlantCostModel\nconverters/wind/atb_wind_cost.py\n[Converter / Wind]", "x": 484.44055215455836, "y": 330.297978929092}, {"borderWidth": 3.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PYSAMWindPlantPerformanceModel", "label": "PYSAMWindPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "PYSAMWindPlantPerformanceModel\nconverters/wind/wind_pysam.py\n[Converter / Wind]", "x": 550.5984027605526, "y": 451.5476939728353}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindPerformanceBaseClass", "label": "WindPerformanceBaseClass", "shape": "dot", "size": 19.42105263157895, "title": "WindPerformanceBaseClass\nconverters/wind/wind_plant_baseclass.py\n[Converter / Wind]", "x": 509.69716559653716, "y": 583.5219955261796}, {"borderWidth": 3.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "FlorisWindPlantPerformanceModel", "label": "FlorisWindPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "FlorisWindPlantPerformanceModel\nconverters/wind/floris.py\n[Converter / Wind]", "x": 386.4910795111691, "y": 646.1453801885751}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindArdPerformanceCompatibilityComponent", "label": "WindArdPerformanceCompatibilityComponent", "shape": "dot", "size": 18.0, "title": "WindArdPerformanceCompatibilityComponent\nconverters/wind/wind_plant_ard.py\n[Converter / Wind]", "x": 255.69275934662096, "y": 601.3783905588575}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindArdCostCompatibilityComponent", "label": "WindArdCostCompatibilityComponent", "shape": "dot", "size": 18.0, "title": "WindArdCostCompatibilityComponent\nconverters/wind/wind_plant_ard.py\n[Converter / Wind]", "x": 196.66404742738186, "y": 476.325072910983}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SMRMethanolPlantPerformanceModel", "label": "SMRMethanolPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "SMRMethanolPlantPerformanceModel\nconverters/methanol/smr_methanol_plant.py\n[Converter / Methanol]", "x": 245.26041830184303, "y": 346.82157500140227}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SMRMethanolPlantCostModel", "label": "SMRMethanolPlantCostModel", "shape": "dot", "size": 18.0, "title": "SMRMethanolPlantCostModel\nconverters/methanol/smr_methanol_plant.py\n[Converter / Methanol]", "x": 372.0506131909644, "y": 291.4439725755037}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SMRMethanolPlantFinanceModel", "label": "SMRMethanolPlantFinanceModel", "shape": "dot", "size": 18.0, "title": "SMRMethanolPlantFinanceModel\nconverters/methanol/smr_methanol_plant.py\n[Converter / Methanol]", "x": 500.1422507144458, "y": 343.82986093378406}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MethanolPerformanceBaseClass", "label": "MethanolPerformanceBaseClass", "shape": "dot", "size": 19.42105263157895, "title": "MethanolPerformanceBaseClass\nconverters/methanol/methanol_baseclass.py\n[Converter / Methanol]", "x": 551.8160292273673, "y": 472.2454066683052}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MethanolCostBaseClass", "label": "MethanolCostBaseClass", "shape": "dot", "size": 19.42105263157895, "title": "MethanolCostBaseClass\nconverters/methanol/methanol_baseclass.py\n[Converter / Methanol]", "x": 495.6839168464708, "y": 598.8099536341376}, {"borderWidth": 5.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MethanolFinanceBaseClass", "label": "MethanolFinanceBaseClass", "shape": "dot", "size": 19.42105263157895, "title": "MethanolFinanceBaseClass\nconverters/methanol/methanol_baseclass.py\n[Converter / Methanol]", "x": 365.7556658010815, "y": 646.7308814798549}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CO2HMethanolPlantPerformanceModel", "label": "CO2HMethanolPlantPerformanceModel", "shape": "dot", "size": 18.0, "title": "CO2HMethanolPlantPerformanceModel\nconverters/methanol/co2h_methanol_plant.py\n[Converter / Methanol]", "x": 240.8316118946296, "y": 586.8992069729802}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CO2HMethanolPlantCostModel", "label": "CO2HMethanolPlantCostModel", "shape": "dot", "size": 18.0, "title": "CO2HMethanolPlantCostModel\nconverters/methanol/co2h_methanol_plant.py\n[Converter / Methanol]", "x": 196.70889860494393, "y": 455.57195413603677}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CO2HMethanolPlantFinanceModel", "label": "CO2HMethanolPlantFinanceModel", "shape": "dot", "size": 18.0, "title": "CO2HMethanolPlantFinanceModel\nconverters/methanol/co2h_methanol_plant.py\n[Converter / Methanol]", "x": 260.1901653677206, "y": 332.3999371200461}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenIronReductionPlantCostComponent", "label": "HydrogenIronReductionPlantCostComponent", "shape": "dot", "size": 18.0, "title": "HydrogenIronReductionPlantCostComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 392.80172635379284, "y": 292.1171568185306}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasIronReductionPlantCostComponent", "label": "NaturalGasIronReductionPlantCostComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasIronReductionPlantCostComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 514.1120611197007, "y": 359.1947982547017}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenIronReductionPlantPerformanceComponent", "label": "HydrogenIronReductionPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "HydrogenIronReductionPlantPerformanceComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 550.5168235029448, "y": 492.97505700886006}, {"borderWidth": 3.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasIronReductionPlantPerformanceComponent", "label": "NaturalGasIronReductionPlantPerformanceComponent", "shape": "dot", "size": 18.0, "title": "NaturalGasIronReductionPlantPerformanceComponent\nconverters/iron/iron_dri_plant.py\n[Converter / Iron]", "x": 479.8992121579394, "y": 612.3160092753269}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HumbertEwinPerformanceComponent", "label": "HumbertEwinPerformanceComponent", "shape": "dot", "size": 18.0, "title": "HumbertEwinPerformanceComponent\nconverters/iron/humbert_ewin_perf.py\n[Converter / Iron]", "x": 345.0667047898959, "y": 644.8082942814825}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MartinIronMineCostComponent", "label": "MartinIronMineCostComponent", "shape": "dot", "size": 18.0, "title": "MartinIronMineCostComponent\nconverters/iron/martin_mine_cost_model.py\n[Converter / Iron]", "x": 227.80083824635747, "y": 570.7102438066149}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "IronTransportCostComponent", "label": "IronTransportCostComponent", "shape": "dot", "size": 18.0, "title": "IronTransportCostComponent\nconverters/iron/iron_transport.py\n[Converter / Iron]", "x": 199.25186993001995, "y": 434.94269396402495}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "IronReductionPlantBasePerformanceComponent", "label": "IronReductionPlantBasePerformanceComponent", "shape": "dot", "size": 19.42105263157895, "title": "IronReductionPlantBasePerformanceComponent\nconverters/iron/iron_dri_base.py\n[Converter / Iron]", "x": 276.76776483357787, "y": 319.8555634030555}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "IronReductionPlantBaseCostComponent", "label": "IronReductionPlantBaseCostComponent", "shape": "dot", "size": 19.42105263157895, "title": "IronReductionPlantBaseCostComponent\nconverters/iron/iron_dri_base.py\n[Converter / Iron]", "x": 413.3524790181906, "y": 295.27713454003253}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MartinIronMinePerformanceComponent", "label": "MartinIronMinePerformanceComponent", "shape": "dot", "size": 18.0, "title": "MartinIronMinePerformanceComponent\nconverters/iron/martin_mine_perf_model.py\n[Converter / Iron]", "x": 526.1593352437131, "y": 376.14527848915895}, {"borderWidth": 4.0, "color": {"background": "#D84315", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HumbertStinnEwinCostComponent", "label": "HumbertStinnEwinCostComponent", "shape": "dot", "size": 18.0, "title": "HumbertStinnEwinCostComponent\nconverters/iron/humbert_stinn_ewin_cost.py\n[Converter / Iron]", "x": 546.743615781497, "y": 513.4286945748072}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HOPPComponent", "label": "HOPPComponent", "shape": "dot", "size": 18.0, "title": "HOPPComponent\nconverters/hopp/hopp_wrapper.py\n[Converter / HOPP]", "x": 462.5917542911312, "y": 623.8559111338152}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PySAMTidalPerformanceModel", "label": "PySAMTidalPerformanceModel", "shape": "dot", "size": 18.0, "title": "PySAMTidalPerformanceModel\nconverters/water_power/tidal_pysam.py\n[Converter / Water Power]", "x": 324.72859310432364, "y": 640.4260460063381}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PySAMMarineCostModel", "label": "PySAMMarineCostModel", "shape": "dot", "size": 18.0, "title": "PySAMMarineCostModel\nconverters/water_power/pysam_marine_cost.py\n[Converter / Water Power]", "x": 216.77814592164026, "y": 553.0618685876668}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "RunOfRiverHydroPerformanceModel", "label": "RunOfRiverHydroPerformanceModel", "shape": "dot", "size": 18.0, "title": "RunOfRiverHydroPerformanceModel\nconverters/water_power/hydro_plant_run_of_river.py\n[Converter / Water Power]", "x": 204.23854510804242, "y": 414.73832160687783}, {"borderWidth": 4.0, "color": {"background": "#4A90D9", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "RunOfRiverHydroCostModel", "label": "RunOfRiverHydroCostModel", "shape": "dot", "size": 18.0, "title": "RunOfRiverHydroCostModel\nconverters/water_power/hydro_plant_run_of_river.py\n[Converter / Water Power]", "x": 294.740834296002, "y": 309.3594743780847}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleAmmoniaPerformanceModel", "label": "SimpleAmmoniaPerformanceModel", "shape": "dot", "size": 18.0, "title": "SimpleAmmoniaPerformanceModel\nconverters/ammonia/simple_ammonia_model.py\n[Converter / Ammonia]", "x": 433.40509869823285, "y": 300.86319031224053}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleAmmoniaCostModel", "label": "SimpleAmmoniaCostModel", "shape": "dot", "size": 18.0, "title": "SimpleAmmoniaCostModel\nconverters/ammonia/simple_ammonia_model.py\n[Converter / Ammonia]", "x": 536.1198784691253, "y": 394.42665374762043}, {"borderWidth": 3.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AmmoniaSynLoopPerformanceModel", "label": "AmmoniaSynLoopPerformanceModel", "shape": "dot", "size": 18.0, "title": "AmmoniaSynLoopPerformanceModel\nconverters/ammonia/ammonia_synloop.py\n[Converter / Ammonia]", "x": 540.5636645511591, "y": 533.3117528946093}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "AmmoniaSynLoopCostModel", "label": "AmmoniaSynLoopCostModel", "shape": "dot", "size": 18.0, "title": "AmmoniaSynLoopCostModel\nconverters/ammonia/ammonia_synloop.py\n[Converter / Ammonia]", "x": 444.01862690077985, "y": 633.2724247412674}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DOCPerformanceModel", "label": "DOCPerformanceModel", "shape": "dot", "size": 18.0, "title": "DOCPerformanceModel\nconverters/co2/marine/direct_ocean_capture.py\n[Converter / CO2]", "x": 305.03269414802736, "y": 633.6581275003193}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DOCCostModel", "label": "DOCCostModel", "shape": "dot", "size": 18.0, "title": "DOCCostModel\nconverters/co2/marine/direct_ocean_capture.py\n[Converter / CO2]", "x": 207.91368001519578, "y": 534.2137056268189}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OAEPerformanceModel", "label": "OAEPerformanceModel", "shape": "dot", "size": 18.0, "title": "OAEPerformanceModel\nconverters/co2/marine/ocean_alkalinity_enhancement.py\n[Converter / CO2]", "x": 211.58805712431138, "y": 395.2469621597975}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OAECostModel", "label": "OAECostModel", "shape": "dot", "size": 18.0, "title": "OAECostModel\nconverters/co2/marine/ocean_alkalinity_enhancement.py\n[Converter / CO2]", "x": 313.84715753363025, "y": 301.0546018388401}, {"borderWidth": 4.0, "color": {"background": "#66BB6A", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OAECostAndFinancialModel", "label": "OAECostAndFinancialModel", "shape": "dot", "size": 18.0, "title": "OAECostAndFinancialModel\nconverters/co2/marine/ocean_alkalinity_enhancement.py\n[Converter / CO2]", "x": 452.67476445714954, "y": 308.7874754191507}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GridPerformanceModel", "label": "GridPerformanceModel", "shape": "dot", "size": 18.0, "title": "GridPerformanceModel\nconverters/grid/grid.py\n[Converter / Grid]", "x": 543.8580906910796, "y": 413.7741089596238}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GridCostModel", "label": "GridCostModel", "shape": "dot", "size": 18.0, "title": "GridCostModel\nconverters/grid/grid.py\n[Converter / Grid]", "x": 532.0718732102009, "y": 552.342805603834}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasPerformanceModel", "label": "NaturalGasPerformanceModel", "shape": "dot", "size": 18.0, "title": "NaturalGasPerformanceModel\nconverters/natural_gas/natural_gas_cc_ct.py\n[Converter / Natural Gas]", "x": 424.4472139785939, "y": 640.4373943201894}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NaturalGasCostModel", "label": "NaturalGasCostModel", "shape": "dot", "size": 18.0, "title": "NaturalGasCostModel\nconverters/natural_gas/natural_gas_cc_ct.py\n[Converter / Natural Gas]", "x": 286.2569295976094, "y": 624.6065418587294}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasProducerPerformance", "label": "SimpleGasProducerPerformance", "shape": "dot", "size": 18.0, "title": "SimpleGasProducerPerformance\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 201.3280452712436, "y": 514.4356470449293}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasConsumerPerformance", "label": "SimpleGasConsumerPerformance", "shape": "dot", "size": 18.0, "title": "SimpleGasConsumerPerformance\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 221.19128243913522, "y": 376.74290673623443}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasProducerCost", "label": "SimpleGasProducerCost", "shape": "dot", "size": 18.0, "title": "SimpleGasProducerCost\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 333.8144210804685, "y": 295.05389888426953}, {"borderWidth": 4.0, "color": {"background": "#1B3A5C", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleGasConsumerCost", "label": "SimpleGasConsumerCost", "shape": "dot", "size": 18.0, "title": "SimpleGasConsumerCost\nconverters/natural_gas/dummy_gas_components.py\n[Converter / Natural Gas]", "x": 470.89095415961566, "y": 318.9337463910879}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StoragePerformanceModel", "label": "StoragePerformanceModel", "shape": "diamond", "size": 18.0, "title": "StoragePerformanceModel\nstorage/storage_performance_model.py\n[Storage / General]", "x": 428.09388111524004, "y": -469.09888948081795}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StoragePerformanceBase", "label": "StoragePerformanceBase", "shape": "diamond", "size": 20.13157894736842, "title": "StoragePerformanceBase\nstorage/storage_baseclass.py\n[Storage / General]", "x": 455.6085661088584, "y": -385.16822684557377}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StorageAutoSizingModel", "label": "StorageAutoSizingModel", "shape": "diamond", "size": 18.0, "title": "StorageAutoSizingModel\nstorage/simple_storage_auto_sizing.py\n[Storage / General]", "x": 370.0643470376622, "y": -331.15773226109025}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GenericStorageCostModel", "label": "GenericStorageCostModel", "shape": "diamond", "size": 18.0, "title": "GenericStorageCostModel\nstorage/generic_storage_cost.py\n[Storage / General]", "x": 264.590914357365, "y": -368.7926071689721}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MCHTOLStorageCostModel", "label": "MCHTOLStorageCostModel", "shape": "diamond", "size": 18.0, "title": "MCHTOLStorageCostModel\nstorage/hydrogen/mch_storage.py\n[Storage / General]", "x": 219.55784982221226, "y": -478.13520688340736}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HydrogenStorageBaseCostModel", "label": "HydrogenStorageBaseCostModel", "shape": "diamond", "size": 20.842105263157894, "title": "HydrogenStorageBaseCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 270.16454539792574, "y": -589.4304862347785}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "LinedRockCavernStorageCostModel", "label": "LinedRockCavernStorageCostModel", "shape": "diamond", "size": 18.0, "title": "LinedRockCavernStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 388.2687164324305, "y": -630.4775561122241}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SaltCavernStorageCostModel", "label": "SaltCavernStorageCostModel", "shape": "diamond", "size": 18.0, "title": "SaltCavernStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 501.4805766605486, "y": -572.7844347513467}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PipeStorageCostModel", "label": "PipeStorageCostModel", "shape": "diamond", "size": 18.0, "title": "PipeStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 538.9625776291, "y": -449.75172147563603}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "CompressedGasStorageCostModel", "label": "CompressedGasStorageCostModel", "shape": "diamond", "size": 18.0, "title": "CompressedGasStorageCostModel\nstorage/hydrogen/h2_storage_cost.py\n[Storage / General]", "x": 475.93189116793945, "y": -336.23888907246976}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PySAMBatteryPerformanceModel", "label": "PySAMBatteryPerformanceModel", "shape": "diamond", "size": 18.0, "title": "PySAMBatteryPerformanceModel\nstorage/battery/pysam_battery.py\n[Storage / General]", "x": 349.5705117805883, "y": -302.34705409538617}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ATBBatteryCostModel", "label": "ATBBatteryCostModel", "shape": "diamond", "size": 18.0, "title": "ATBBatteryCostModel\nstorage/battery/atb_battery_cost.py\n[Storage / General]", "x": 236.61361523178934, "y": -369.9554252856643}, {"borderWidth": 4.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "FeedstockCostModel", "label": "FeedstockCostModel", "shape": "dot", "size": 18.0, "title": "FeedstockCostModel\nfeedstocks/feedstocks.py\n[Other / Other]", "x": -486.58132074145146, "y": -260.3302434705348}, {"borderWidth": 4.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "EIANaturalGasFeedstockCostModel", "label": "EIANaturalGasFeedstockCostModel", "shape": "dot", "size": 18.0, "title": "EIANaturalGasFeedstockCostModel\nfeedstocks/eia_ng_pricing.py\n[Other / Other]", "x": -459.0666357478331, "y": -176.39958083529064}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProFastLCO", "label": "ProFastLCO", "shape": "star", "size": 18.0, "title": "ProFastLCO\nfinances/profast_lco.py\n[Finance / General]", "x": -486.58132074145146, "y": 260.3302434705349}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProFastBase", "label": "ProFastBase", "shape": "star", "size": 19.42105263157895, "title": "ProFastBase\nfinances/profast_base.py\n[Finance / General]", "x": -459.0666357478331, "y": 344.2609061057791}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ProFastNPV", "label": "ProFastNPV", "shape": "star", "size": 18.0, "title": "ProFastNPV\nfinances/profast_npv.py\n[Finance / General]", "x": -544.6108548190293, "y": 398.2714006902626}, {"borderWidth": 5.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "ResourceBaseAPIModel", "label": "ResourceBaseAPIModel", "shape": "triangle", "size": 19.42105263157895, "title": "ResourceBaseAPIModel\nresource/resource_base.py\n[Resource / General]", "x": -79.51256037378874, "y": -584.9567473090942}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MeteosatPrimeMeridianSolarAPI", "label": "MeteosatPrimeMeridianSolarAPI", "shape": "triangle", "size": 18.0, "title": "MeteosatPrimeMeridianSolarAPI\nresource/solar/nlr_developer_meteosat_prime_meridian_models.py\n[Resource / General]", "x": -51.9978753801704, "y": -501.02608467385005}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "MeteosatPrimeMeridianTMYSolarAPI", "label": "MeteosatPrimeMeridianTMYSolarAPI", "shape": "triangle", "size": 18.0, "title": "MeteosatPrimeMeridianTMYSolarAPI\nresource/solar/nlr_developer_meteosat_prime_meridian_models.py\n[Resource / General]", "x": -137.5420944513666, "y": -447.0155900893665}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SolarResourceBaseAPIModel", "label": "SolarResourceBaseAPIModel", "shape": "triangle", "size": 19.42105263157895, "title": "SolarResourceBaseAPIModel\nresource/solar/solar_resource_base.py\n[Resource / General]", "x": -243.01552713166376, "y": -484.6504649972484}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OpenMeteoHistoricalSolarResource", "label": "OpenMeteoHistoricalSolarResource", "shape": "triangle", "size": 18.0, "title": "OpenMeteoHistoricalSolarResource\nresource/solar/openmeteo_solar.py\n[Resource / General]", "x": -288.0485916668165, "y": -593.9930647116836}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "Himawari7SolarAPI", "label": "Himawari7SolarAPI", "shape": "triangle", "size": 18.0, "title": "Himawari7SolarAPI\nresource/solar/nlr_developer_himawari_api_models.py\n[Resource / General]", "x": -237.44189609110305, "y": -705.2883440630549}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "Himawari8SolarAPI", "label": "Himawari8SolarAPI", "shape": "triangle", "size": 18.0, "title": "Himawari8SolarAPI\nresource/solar/nlr_developer_himawari_api_models.py\n[Resource / General]", "x": -119.33772505659829, "y": -746.3354139405003}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HimawariTMYSolarAPI", "label": "HimawariTMYSolarAPI", "shape": "triangle", "size": 18.0, "title": "HimawariTMYSolarAPI\nresource/solar/nlr_developer_himawari_api_models.py\n[Resource / General]", "x": -6.125864828480175, "y": -688.6422925796229}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "NLRDeveloperAPISolarResourceBase", "label": "NLRDeveloperAPISolarResourceBase", "shape": "triangle", "size": 24.394736842105264, "title": "NLRDeveloperAPISolarResourceBase\nresource/solar/nlr_developer_api_base.py\n[Resource / General]", "x": 31.356136140071186, "y": -565.6095793039123}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESAggregatedSolarAPI", "label": "GOESAggregatedSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESAggregatedSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -31.67455032108934, "y": -452.096746900746}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESConusSolarAPI", "label": "GOESConusSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESConusSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -158.0359297084405, "y": -418.2049119236624}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESFullDiscSolarAPI", "label": "GOESFullDiscSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESFullDiscSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -270.99282625723947, "y": -485.8132831139406}, {"borderWidth": 2.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GOESTMYSolarAPI", "label": "GOESTMYSolarAPI", "shape": "triangle", "size": 18.0, "title": "GOESTMYSolarAPI\nresource/solar/nlr_developer_goes_api_models.py\n[Resource / General]", "x": -301.2124767374961, "y": -614.6459391266081}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OpenMeteoHistoricalWindResource", "label": "OpenMeteoHistoricalWindResource", "shape": "triangle", "size": 18.0, "title": "OpenMeteoHistoricalWindResource\nresource/wind/openmeteo_wind.py\n[Resource / General]", "x": -229.44086839384488, "y": -726.515073522741}, {"borderWidth": 4.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WindResourceBaseAPIModel", "label": "WindResourceBaseAPIModel", "shape": "triangle", "size": 19.42105263157895, "title": "WindResourceBaseAPIModel\nresource/wind/wind_resource_base.py\n[Resource / General]", "x": -98.67692574249088, "y": -752.9836456314601}, {"borderWidth": 3.0, "color": {"background": "#555555", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "WTKNLRDeveloperAPIWindResource", "label": "WTKNLRDeveloperAPIWindResource", "shape": "triangle", "size": 18.0, "title": "WTKNLRDeveloperAPIWindResource\nresource/wind/nlr_developer_wtk_api.py\n[Resource / General]", "x": 11.735802273041458, "y": -677.3143608199191}, {"borderWidth": 3.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "GenericDemandComponent", "label": "GenericDemandComponent", "shape": "dot", "size": 18.0, "title": "GenericDemandComponent\ndemand/generic_demand.py\n[Other / Other]", "x": -544.6108548190293, "y": -122.38908625080711}, {"borderWidth": 4.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DemandComponentBase", "label": "DemandComponentBase", "shape": "dot", "size": 19.42105263157895, "title": "DemandComponentBase\ndemand/demand_base.py\n[Other / Other]", "x": -650.0842874993265, "y": -160.02396115868896}, {"borderWidth": 3.0, "color": {"background": "#F5C542", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "FlexibleDemandComponent", "label": "FlexibleDemandComponent", "shape": "dot", "size": 18.0, "title": "FlexibleDemandComponent\ndemand/flexible_demand.py\n[Other / Other]", "x": -695.1173520344793, "y": -269.36656087312423}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoStorageControllerBaseClass", "label": "PyomoStorageControllerBaseClass", "shape": "diamond", "size": 19.42105263157895, "title": "PyomoStorageControllerBaseClass\ncontrol/control_strategies/pyomo_storage_controller_baseclass.py\n[Storage / General]", "x": 206.39396475153265, "y": -498.78808129833186}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "StorageOpenLoopControlBase", "label": "StorageOpenLoopControlBase", "shape": "diamond", "size": 20.13157894736842, "title": "StorageOpenLoopControlBase\ncontrol/control_strategies/storage/openloop_storage_control_base.py\n[Storage / General]", "x": 278.1655730951839, "y": -610.6572156944648}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "DemandOpenLoopStorageController", "label": "DemandOpenLoopStorageController", "shape": "diamond", "size": 18.0, "title": "DemandOpenLoopStorageController\ncontrol/control_strategies/storage/demand_openloop_storage_controller.py\n[Storage / General]", "x": 408.9295157465379, "y": -637.1257878031839}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "HeuristicLoadFollowingStorageController", "label": "HeuristicLoadFollowingStorageController", "shape": "diamond", "size": 18.0, "title": "HeuristicLoadFollowingStorageController\ncontrol/control_strategies/storage/heuristic_pyomo_controller.py\n[Storage / General]", "x": 519.3422437620702, "y": -561.4565029916428}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "OptimizedDispatchStorageController", "label": "OptimizedDispatchStorageController", "shape": "diamond", "size": 18.0, "title": "OptimizedDispatchStorageController\ncontrol/control_strategies/storage/optimized_pyomo_controller.py\n[Storage / General]", "x": 541.9933368656092, "y": -429.1430173132935}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "SimpleStorageOpenLoopController", "label": "SimpleStorageOpenLoopController", "shape": "diamond", "size": 18.0, "title": "SimpleStorageOpenLoopController\ncontrol/control_strategies/storage/simple_openloop_controller.py\n[Storage / General]", "x": 462.6186718096345, "y": -320.4638955106441}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PeakLoadManagementHeuristicOpenLoopStorageController", "label": "PeakLoadManagementHeuristicOpenLoopStorageController", "shape": "diamond", "size": 18.0, "title": "PeakLoadManagementHeuristicOpenLoopStorageController\ncontrol/control_strategies/storage/plm_openloop_storage_controller.py\n[Storage / General]", "x": 329.04975630639206, "y": -301.68432548327485}, {"borderWidth": 5.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoRuleBaseClass", "label": "PyomoRuleBaseClass", "shape": "hexagon", "size": 19.42105263157895, "title": "PyomoRuleBaseClass\ncontrol/control_rules/pyomo_rule_baseclass.py\n[Control / General]", "x": 654.0, "y": 0.0}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoDispatchGenericConverter", "label": "PyomoDispatchGenericConverter", "shape": "dot", "size": 18.0, "title": "PyomoDispatchGenericConverter\ncontrol/control_rules/converters/generic_converter.py\n[Converter / Other]", "x": 549.2687648311249, "y": 433.9130181048081}, {"borderWidth": 4.0, "color": {"background": "#00ACC1", "border": "#555555", "highlight": {"background": "#FF6B6B", "border": "#FF0000"}, "hover": {"background": "#FFD700", "border": "#FF8C00"}}, "font": {"color": "#333333"}, "id": "PyomoRuleStorageBaseclass", "label": "PyomoRuleStorageBaseclass", "shape": "diamond", "size": 18.0, "title": "PyomoRuleStorageBaseclass\ncontrol/control_rules/storage/pyomo_storage_rule_baseclass.py\n[Storage / General]", "x": 222.32576716621526, "y": -384.6114372269132}]); + edges = new vis.DataSet([{"arrows": "to", "from": "SiteBaseComponent", "to": "SiteLocationComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "ResizeablePerformanceModelBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SolarPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "LinearH2FuelCellPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SteamMethaneReformerPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "GeoH2SubsurfacePerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "GeoH2SurfacePerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "DesalinationPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "QuinnNuclearPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "CMUElectricArcFurnaceScrapOnlyPerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "ElectricArcFurnacePlantBasePerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "CMUElectricArcFurnaceDRIPerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SteelPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleASUPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "WindPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "WindArdPerformanceCompatibilityComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "MethanolPerformanceBaseClass"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "HumbertEwinPerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "IronReductionPlantBasePerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "MartinIronMinePerformanceComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "HOPPComponent"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "PySAMTidalPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "RunOfRiverHydroPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleAmmoniaPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "DOCPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "OAEPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "GridPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "NaturalGasPerformanceModel"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleGasProducerPerformance"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "SimpleGasConsumerPerformance"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "StoragePerformanceBase"}, {"arrows": "to", "from": "PerformanceModelBaseClass", "to": "DemandComponentBase"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GenericConverterCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBUtilityPVCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBResComPVCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ElectrolyzerCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "H2FuelCellCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SteamMethaneReformerCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GeoH2SubsurfaceCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GeoH2SurfaceCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "DesalinationCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "QuinnNuclearCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "CMUElectricArcFurnaceCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ElectricArcFurnacePlantBaseCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SteelCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleASUCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBWindPlantCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "WindArdCostCompatibilityComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "MethanolCostBaseClass"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "MartinIronMineCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "IronTransportCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "IronReductionPlantBaseCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "HumbertStinnEwinCostComponent"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "PySAMMarineCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "RunOfRiverHydroCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleAmmoniaCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "AmmoniaSynLoopCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "DOCCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "OAECostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "OAECostAndFinancialModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GridCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "NaturalGasCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleGasProducerCost"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "SimpleGasConsumerCost"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "GenericStorageCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "MCHTOLStorageCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "HydrogenStorageBaseCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "ATBBatteryCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "FeedstockCostModel"}, {"arrows": "to", "from": "CostModelBaseClass", "to": "EIANaturalGasFeedstockCostModel"}, {"arrows": "to", "from": "ResizeablePerformanceModelBaseClass", "to": "ElectrolyzerPerformanceBaseClass"}, {"arrows": "to", "from": "ResizeablePerformanceModelBaseClass", "to": "AmmoniaSynLoopPerformanceModel"}, {"arrows": "to", "from": "CacheBaseClass", "to": "FlorisWindPlantPerformanceModel"}, {"arrows": "to", "from": "CacheBaseClass", "to": "HOPPComponent"}, {"arrows": "to", "from": "SolarPerformanceBaseClass", "to": "PYSAMSolarPlantPerformanceModel"}, {"arrows": "to", "from": "ElectrolyzerPerformanceBaseClass", "to": "ECOElectrolyzerPerformanceModel"}, {"arrows": "to", "from": "ElectrolyzerCostBaseClass", "to": "SingliticoCostModel"}, {"arrows": "to", "from": "ElectrolyzerCostBaseClass", "to": "BasicElectrolyzerCostModel"}, {"arrows": "to", "from": "ElectrolyzerCostBaseClass", "to": "CustomElectrolyzerCostModel"}, {"arrows": "to", "from": "ECOElectrolyzerPerformanceModel", "to": "WOMBATElectrolyzerModel"}, {"arrows": "to", "from": "GeoH2SubsurfacePerformanceBaseClass", "to": "NaturalGeoH2PerformanceModel"}, {"arrows": "to", "from": "GeoH2SubsurfacePerformanceBaseClass", "to": "StimulatedGeoH2PerformanceModel"}, {"arrows": "to", "from": "GeoH2SubsurfaceCostBaseClass", "to": "GeoH2SubsurfaceCostModel"}, {"arrows": "to", "from": "GeoH2SurfacePerformanceBaseClass", "to": "AspenGeoH2SurfacePerformanceModel"}, {"arrows": "to", "from": "GeoH2SurfaceCostBaseClass", "to": "AspenGeoH2SurfaceCostModel"}, {"arrows": "to", "from": "DesalinationPerformanceBaseClass", "to": "ReverseOsmosisPerformanceModel"}, {"arrows": "to", "from": "DesalinationCostBaseClass", "to": "ReverseOsmosisCostModel"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBasePerformanceComponent", "to": "HydrogenEAFPlantPerformanceComponent"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBasePerformanceComponent", "to": "NaturalGasEAFPlantPerformanceComponent"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBaseCostComponent", "to": "HydrogenEAFPlantCostComponent"}, {"arrows": "to", "from": "ElectricArcFurnacePlantBaseCostComponent", "to": "NaturalGasEAFPlantCostComponent"}, {"arrows": "to", "from": "SteelPerformanceBaseClass", "to": "SteelPerformanceModel"}, {"arrows": "to", "from": "SteelCostBaseClass", "to": "SteelCostAndFinancialModel"}, {"arrows": "to", "from": "WindPerformanceBaseClass", "to": "PYSAMWindPlantPerformanceModel"}, {"arrows": "to", "from": "WindPerformanceBaseClass", "to": "FlorisWindPlantPerformanceModel"}, {"arrows": "to", "from": "MethanolPerformanceBaseClass", "to": "SMRMethanolPlantPerformanceModel"}, {"arrows": "to", "from": "MethanolPerformanceBaseClass", "to": "CO2HMethanolPlantPerformanceModel"}, {"arrows": "to", "from": "MethanolCostBaseClass", "to": "SMRMethanolPlantCostModel"}, {"arrows": "to", "from": "MethanolCostBaseClass", "to": "CO2HMethanolPlantCostModel"}, {"arrows": "to", "from": "MethanolFinanceBaseClass", "to": "SMRMethanolPlantFinanceModel"}, {"arrows": "to", "from": "MethanolFinanceBaseClass", "to": "CO2HMethanolPlantFinanceModel"}, {"arrows": "to", "from": "IronReductionPlantBasePerformanceComponent", "to": "HydrogenIronReductionPlantPerformanceComponent"}, {"arrows": "to", "from": "IronReductionPlantBasePerformanceComponent", "to": "NaturalGasIronReductionPlantPerformanceComponent"}, {"arrows": "to", "from": "IronReductionPlantBaseCostComponent", "to": "HydrogenIronReductionPlantCostComponent"}, {"arrows": "to", "from": "IronReductionPlantBaseCostComponent", "to": "NaturalGasIronReductionPlantCostComponent"}, {"arrows": "to", "from": "StoragePerformanceBase", "to": "StoragePerformanceModel"}, {"arrows": "to", "from": "StoragePerformanceBase", "to": "StorageAutoSizingModel"}, {"arrows": "to", "from": "StoragePerformanceBase", "to": "PySAMBatteryPerformanceModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "LinedRockCavernStorageCostModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "SaltCavernStorageCostModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "PipeStorageCostModel"}, {"arrows": "to", "from": "HydrogenStorageBaseCostModel", "to": "CompressedGasStorageCostModel"}, {"arrows": "to", "from": "ProFastBase", "to": "ProFastLCO"}, {"arrows": "to", "from": "ProFastBase", "to": "ProFastNPV"}, {"arrows": "to", "from": "ResourceBaseAPIModel", "to": "SolarResourceBaseAPIModel"}, {"arrows": "to", "from": "ResourceBaseAPIModel", "to": "WindResourceBaseAPIModel"}, {"arrows": "to", "from": "SolarResourceBaseAPIModel", "to": "OpenMeteoHistoricalSolarResource"}, {"arrows": "to", "from": "SolarResourceBaseAPIModel", "to": "NLRDeveloperAPISolarResourceBase"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "MeteosatPrimeMeridianSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "MeteosatPrimeMeridianTMYSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "Himawari7SolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "Himawari8SolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "HimawariTMYSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESAggregatedSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESConusSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESFullDiscSolarAPI"}, {"arrows": "to", "from": "NLRDeveloperAPISolarResourceBase", "to": "GOESTMYSolarAPI"}, {"arrows": "to", "from": "WindResourceBaseAPIModel", "to": "OpenMeteoHistoricalWindResource"}, {"arrows": "to", "from": "WindResourceBaseAPIModel", "to": "WTKNLRDeveloperAPIWindResource"}, {"arrows": "to", "from": "DemandComponentBase", "to": "GenericDemandComponent"}, {"arrows": "to", "from": "DemandComponentBase", "to": "FlexibleDemandComponent"}, {"arrows": "to", "from": "PyomoStorageControllerBaseClass", "to": "HeuristicLoadFollowingStorageController"}, {"arrows": "to", "from": "PyomoStorageControllerBaseClass", "to": "OptimizedDispatchStorageController"}, {"arrows": "to", "from": "StorageOpenLoopControlBase", "to": "DemandOpenLoopStorageController"}, {"arrows": "to", "from": "StorageOpenLoopControlBase", "to": "SimpleStorageOpenLoopController"}, {"arrows": "to", "from": "StorageOpenLoopControlBase", "to": "PeakLoadManagementHeuristicOpenLoopStorageController"}, {"arrows": "to", "from": "PyomoRuleBaseClass", "to": "PyomoDispatchGenericConverter"}, {"arrows": "to", "from": "PyomoRuleBaseClass", "to": "PyomoRuleStorageBaseclass"}]); nodeColors = {}; allNodes = nodes.get({ returnType: "Object" }); @@ -446,7 +446,7 @@ Chemical