Examples showing rendering connectivity of a model#

Using the API of the idaes_connectivity package, you can extract the connectivity of a model, i.e., which units connect to which other ones by which streams. Then you can write that to a file, or convert it into other formats. The Mermaid format can be displayed in Jupyter Notebooks directly.

Dan Gunter (LBNL), Jan-2025

# Initial imports
from idaes_connectivity.base import Connectivity
from idaes_connectivity.jupyter import display_connectivity

Basic flowsheet example#

A simple flowsheet that does not require installation of any packages outside IDAES and Pyomo.

# example of loading a module by name
# by default, a function called "build()" is invoked to build the model
conn = Connectivity(
    input_module="idaes_connectivity.tests.example_flowsheet", model_flowsheet_attr="fs"
)
# display as Mermaid. The flag `jb=True` is a workaround for showing in docs, you can omit this
# in versions of Jupyter Lab and Jupyter Notebook that support Mermaid natively.
display_connectivity(conn, jb=True)
# same as above, but the model is built first then provided
from idaes_connectivity.tests import example_flowsheet

basic_model = example_flowsheet.build()
conn = Connectivity(input_model=basic_model.fs)
display_connectivity(conn, jb=True)

UKy plant example#

This example uses the University of Kentucky (UKy) plant flowsheet from the Process Optimization and Modeling for Minerals Sustainability (PrOMMiS) project. Therefore you must install PrOMMiS for it to work.

Build the model#

try:
    from prommis.uky.uky_flowsheet import build

    uky_model = build()
except ImportError:
    print("Import error, probably prommis is not installed")

Display model connectivity#

  • Left-to–right

  • Top-to-bottom

display_connectivity(
    input_model=uky_model.fs, mermaid_options=dict(direction="lr"), jb=True
)
display_connectivity(
    input_model=uky_model.fs, mermaid_options=dict(direction="td"), jb=True
)

Display connectivity as a matrix#

Use Pandas DataFrame to render more nicely

import pandas as pd

pd.set_option("display.max_columns", None)  # don't elide columns
conn = Connectivity(input_model=uky_model.fs)
pd.DataFrame(conn.as_table())
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
0 Arcs leach_mixer leach leach_liquid_feed sl_sep1 leach_solid_feed precipitator sl_sep2 leach_sx_mixer leach_filter_cake_liquid leach_filter_cake precip_sep precip_purge precip_sx_mixer roaster solex_cleaner_load solex_cleaner_strip cleaner_mixer cleaner_org_make_up acid_feed3 cleaner_sep cleaner_purge solex_rougher_load load_sep solex_rougher_scrub rougher_mixer rougher_org_make_up acid_feed1 scrub_sep solex_rougher_strip acid_feed2 rougher_sep sc_circuit_purge
1 leaching_feed_mixture -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 leaching_liq_feed 1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 leaching_liquid_outlet 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 leaching_sol_feed 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5 leaching_solid_outlet 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
6 precip_aq_outlet 0 0 0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
7 precip_solid_outlet 0 0 0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
8 sl_sep1_liquid_outlet 0 0 0 -1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
9 sl_sep1_retained_liquid_outlet 0 0 0 -1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10 sl_sep1_solid_outlet 0 0 0 -1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
11 sl_sep2_aq_purge 0 0 0 0 0 0 0 0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
12 sl_sep2_aq_recycle 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
13 sl_sep2_liquid_outlet 0 0 0 0 0 0 -1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
14 sl_sep2_retained_liquid_outlet 0 0 0 0 0 0 -1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
15 sl_sep2_solid_outlet 0 0 0 0 0 0 -1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
16 sx_cleaner_load_aq_feed 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
17 sx_cleaner_load_aq_outlet 0 0 0 0 0 0 0 1 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
18 sx_cleaner_load_org_outlet 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
19 sx_cleaner_mixed_org_recycle 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
20 sx_cleaner_org_feed 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
21 sx_cleaner_strip_acid_feed 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0
22 sx_cleaner_strip_aq_outlet 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
23 sx_cleaner_strip_org_outlet 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
24 sx_cleaner_strip_org_purge 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0
25 sx_cleaner_strip_org_recycle 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0
26 sx_rougher_load_aq_feed 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
27 sx_rougher_load_aq_outlet 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 0 0 0 0 0 0 0 0 0
28 sx_rougher_load_aq_recycle 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0
29 sx_rougher_load_org_outlet 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0
30 sx_rougher_mixed_org_recycle 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 -1 0 0 0 0 0 0 0
31 sx_rougher_org_feed 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0
32 sx_rougher_scrub_acid_feed 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 -1 0 0 0 0 0
33 sx_rougher_scrub_aq_outlet 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 1 0 0 0 0
34 sx_rougher_scrub_aq_recycle 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0
35 sx_rougher_scrub_org_outlet 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 1 0 0 0
36 sx_rougher_strip_acid_feed 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0
37 sx_rougher_strip_aq_outlet 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0
38 sx_rougher_strip_org_outlet 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0
39 sx_rougher_strip_org_purge 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1
40 sx_rougher_strip_org_recycle 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 -1 0

BSM2 example#

result = None
try:
    from watertap.flowsheets.full_water_resource_recovery_facility import (
        BSM2_P_extension as bsm2,
    )

    bsm2_model = bsm2.build()
    result = display_connectivity(
        input_model=bsm2_model.fs,
        mermaid_options=dict(direction="lr", stream_labels=True),
        jb=True,
    )
except ImportError:
    print("Import error, probably watertap is not installed")
result

Write to file#

You can also save the CSV, Mermaid, or D2 versions of the connectivity to a file for later processing in other interfaces.

from idaes_connectivity.base import CSV, Mermaid, D2
CSV(conn).write("uky_model.csv")
Mermaid(conn).write("uky_model.mmd")
D2(conn).write("uky_model.d2")
# this will only work if you have D2 installed (https://d2lang.com)
!d2 uky_model.d2
success: successfully compiled uky_model.d2 to uky_model.svg in 387.598799ms
# if you generated the SVG in the previous step you can show it here
from IPython.display import SVG

SVG("uky_model.svg")
_images/5ebfe1af8d79bf5b11985cb1e593073a6a42772e767fdca1c74da5d010a0527c.svg