Skip to content
25 changes: 19 additions & 6 deletions h2integrate/core/h2integrate_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1219,12 +1219,6 @@ def connect_technologies(self):
f"{dispatching_tech_name}.dispatch_block_rule_function_{tech_name}",
)

if (pyxdsm is not None) and (len(technology_interconnections) > 0):
try:
create_xdsm_from_config(self.plant_config)
except FileNotFoundError as e:
print(f"Unable to create system XDSM diagram. Error: {e}")

def create_driver_model(self):
"""
Add the driver to the OpenMDAO model and add recorder.
Expand Down Expand Up @@ -1449,3 +1443,22 @@ def _structured(meta_list):
"explicit_outputs": _structured(explicit_meta),
"implicit_outputs": _structured(implicit_meta),
}

def create_xdsm(self):
"""Generates an XDSM diagram for the plant configuration and saves it to a PDF file.

Reads technology interconnections from the plant configuration and delegates
diagram creation to :func:`create_xdsm_from_config`. If ``pyxdsm`` is not
installed or no interconnections are defined, this method does nothing. A
:class:`FileNotFoundError` is caught and reported without raising.

Raises:
None: All exceptions are caught internally; errors are printed to stdout.
"""

technology_interconnections = self.plant_config.get("technology_interconnections", [])
if (pyxdsm is not None) and (len(technology_interconnections) > 0):
try:
create_xdsm_from_config(self.plant_config)
except FileNotFoundError as e:
print(f"Unable to create system XDSM diagram. Error: {e}")
83 changes: 83 additions & 0 deletions h2integrate/core/test/test_framework.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import shutil
from copy import deepcopy
from pathlib import Path
from unittest.mock import MagicMock, patch

import yaml
import numpy as np
import pytest

import h2integrate.core.h2integrate_model as h2i_model_module
from h2integrate import EXAMPLE_DIR
from h2integrate.core.h2integrate_model import H2IntegrateModel
from h2integrate.core.inputs.validation import load_tech_yaml, load_plant_yaml, load_driver_yaml
Expand Down Expand Up @@ -476,3 +478,84 @@ def test_system_order(subtests):

with subtests.test("Test expected names are in the correct order"):
assert names == expected_names


@pytest.mark.unit
def test_create_xdsm_calls_create_xdsm_from_config():
plant_config = {"technology_interconnections": [("wind", "electrolyzer", "electricity")]}
model = object.__new__(H2IntegrateModel)
model.plant_config = plant_config

with (
patch.object(h2i_model_module, "pyxdsm", MagicMock()),
patch.object(h2i_model_module, "create_xdsm_from_config") as mock_fn,
):
model.create_xdsm()

mock_fn.assert_called_once_with(plant_config)


@pytest.mark.unit
def test_create_xdsm_skips_when_pyxdsm_none():
plant_config = {"technology_interconnections": [("wind", "electrolyzer", "electricity")]}
model = object.__new__(H2IntegrateModel)
model.plant_config = plant_config

with (
patch.object(h2i_model_module, "pyxdsm", None),
patch.object(h2i_model_module, "create_xdsm_from_config") as mock_fn,
):
model.create_xdsm()

mock_fn.assert_not_called()


@pytest.mark.unit
def test_create_xdsm_skips_when_no_interconnections():
plant_config = {"technology_interconnections": []}
model = object.__new__(H2IntegrateModel)
model.plant_config = plant_config

with (
patch.object(h2i_model_module, "pyxdsm", MagicMock()),
patch.object(h2i_model_module, "create_xdsm_from_config") as mock_fn,
):
model.create_xdsm()

mock_fn.assert_not_called()


@pytest.mark.unit
def test_create_xdsm_skips_when_interconnections_key_missing():
plant_config = {}
model = object.__new__(H2IntegrateModel)
model.plant_config = plant_config

with (
patch.object(h2i_model_module, "pyxdsm", MagicMock()),
patch.object(h2i_model_module, "create_xdsm_from_config") as mock_fn,
):
model.create_xdsm()

mock_fn.assert_not_called()


@pytest.mark.unit
def test_create_xdsm_catches_file_not_found_error(capsys):
plant_config = {"technology_interconnections": [("wind", "electrolyzer", "electricity")]}
model = object.__new__(H2IntegrateModel)
model.plant_config = plant_config

with (
patch.object(h2i_model_module, "pyxdsm", MagicMock()),
patch.object(
h2i_model_module,
"create_xdsm_from_config",
side_effect=FileNotFoundError("latex not found"),
),
):
model.create_xdsm()

captured = capsys.readouterr()
assert "Unable to create system XDSM diagram" in captured.out
assert "latex not found" in captured.out
Loading