Esempio n. 1
0
def test__unique_unit_name():
    fss = FlowsheetSerializer()
    fss._used_unit_names = {'inlet', 'inlet_1', 'outlet', 'toluene_prod'}
    assert fss._unique_unit_name('hydrogen_in') == 'hydrogen_in'
    assert fss._unique_unit_name('toluene') == 'toluene'
    assert fss._unique_unit_name('outlet') == 'outlet_1'
    assert fss._unique_unit_name('inlet') == 'inlet_2'
    assert fss._unique_unit_name('prod') == 'prod'
Esempio n. 2
0
def test__unique_unit_name():
    fss = FlowsheetSerializer()
    assert fss._unique_unit_name('hydrogen_in') == 'hydrogen_in_1'
    assert fss._unique_unit_name('toluene_prod') == 'toluene_prod_1'
    assert fss._unique_unit_name('feed') == "feed_1"
    # _used_unit_names is incremented by _unique_unit_name so this should have a suffix
    assert fss._unique_unit_name('toluene_prod') == 'toluene_prod_2'
    assert fss._unique_unit_name('feed') == "feed_2"
    assert fss._unique_unit_name('feed') == "feed_3"
Esempio n. 3
0
    def do_GET(self):
        if None in [self.flowsheet, self.name, self.flask_url]:
            raise ServerVariablesNotSetError

        serialized_flowsheet = FlowsheetSerializer().serialize(
            self.flowsheet, self.name)
        r = requests.get(self.flask_url)

        diff_model, model_json = compare_models(r.json(),
                                                serialized_flowsheet,
                                                keep_old_model=True)
        new_flowsheet = model_jointjs_conversion(diff_model, model_json)

        # Need to set the response and the headers or else you get CORS errors
        self.send_response(200)
        self.send_header("Access-Control-Allow-Origin", "*")
        self.send_header("Access-Control-Allow-Headers", "Content-Type")
        self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
        self.send_header("Content-type", "application/json")
        http.server.SimpleHTTPRequestHandler.end_headers(self)

        self.wfile.write(json.dumps(new_flowsheet).encode(encoding="utf_8"))
Esempio n. 4
0
def test_create_link_jointjs_json():
    out_json = {"model": {}}
    out_json["cells"] = []
    source_port = "out"
    dest_port = "in"
    source_id = "M101"
    dest_id = "F101"
    link_id = "s03"
    label = "foo"

    fss = FlowsheetSerializer()
    fss.create_link_jointjs_json(out_json, source_port, dest_port, source_id,
                                 dest_id, link_id, label)
    assert out_json == {
        'cells': [{
            'type':
            'standard.Link',
            'source': {
                'port': 'out',
                'id': 'M101'
            },
            'target': {
                'port': 'in',
                'id': 'F101'
            },
            'router': {
                'name': 'orthogonal',
                'padding': 10
            },
            'connector': {
                'name': 'normal',
                'attrs': {
                    'line': {
                        'stroke': '#5c9adb'
                    }
                }
            },
            'id':
            's03',
            'labels': [{
                "attrs": {
                    "rect": {
                        "fill": '#d7dce0',
                        "stroke": 'white',
                        'stroke-width': 0,
                        "fill-opacity": 0
                    },
                    "text": {
                        "text": label,
                        "fill": 'black',
                        'text-anchor': 'left',
                        "display": "none"
                    },
                },
                "position": {
                    "distance": 0.66,
                    "offset": -40
                }
            }, {
                "attrs": {
                    "text": {
                        "text": link_id
                    }
                }
            }],
            'z':
            2
        }],
        "model": {}
    }
Esempio n. 5
0
def test_create_image_jointjs_json():
    out_json = {"model": {}}
    out_json["cells"] = []
    x_pos = 0
    y_pos = 0
    component_id = "M101"
    component_type = "mixer"
    image = icon_mapping(component_type)
    port_group = {
        "groups": {
            "in": {
                "position": {
                    "name": "left",
                    "args": {
                        "x": 2,
                        "y": 25,
                        "dx": 1,
                        "dy": 1
                    }
                },
                "attrs": {
                    "rect": {
                        "stroke": '#000000',
                        'stroke-width': 0,
                        "width": 0,
                        "height": 0
                    }
                },
                "markup": '<g><rect/></g>'
            }
        },
        "items": [{
            "group": "in",
            "id": "in"
        }, {
            "group": "out",
            "id": "out"
        }]
    }

    fss = FlowsheetSerializer()
    fss.create_image_jointjs_json(out_json, x_pos, y_pos, component_id, image,
                                  component_type, port_group)
    assert out_json == {
        'cells': [{
            'type': 'standard.Image',
            'position': {
                'x': 0,
                'y': 0
            },
            'size': {
                'width': 50,
                'height': 50
            },
            'angle': 0,
            'id': 'M101',
            'z': (1, ),
            'attrs': {
                'image': {
                    'xlinkHref': '/images/icons/mixer.svg'
                },
                'label': {
                    'text': 'M101'
                },
                'root': {
                    'title': 'mixer'
                }
            },
            'ports': {
                "groups": {
                    "in": {
                        "position": {
                            "name": "left",
                            "args": {
                                "x": 2,
                                "y": 25,
                                "dx": 1,
                                "dy": 1
                            }
                        },
                        "attrs": {
                            "rect": {
                                "stroke": '#000000',
                                'stroke-width': 0,
                                "width": 0,
                                "height": 0
                            }
                        },
                        "markup": '<g><rect/></g>'
                    }
                },
                "items": [{
                    "group": "in",
                    "id": "in"
                }, {
                    "group": "out",
                    "id": "out"
                }]
            }
        }],
        "model": {}
    }
Esempio n. 6
0
def test_serialize_flowsheet():
    # Construct the model from idaes/examples/workshops/Module_2_Flowsheet/Module_2_Flowsheet_Solution.ipynb
    m = build_flowsheet()
    m.fs.properties = SWCO2ParameterBlock()
    m.fs.main_compressor = PressureChanger(
        default={
            'dynamic': False,
            'property_package': m.fs.properties,
            'compressor': True,
            'thermodynamic_assumption': ThermodynamicAssumption.isentropic
        })

    m.fs.bypass_compressor = PressureChanger(
        default={
            'dynamic': False,
            'property_package': m.fs.properties,
            'compressor': True,
            'thermodynamic_assumption': ThermodynamicAssumption.isentropic
        })

    m.fs.turbine = PressureChanger(
        default={
            'dynamic': False,
            'property_package': m.fs.properties,
            'compressor': False,
            'thermodynamic_assumption': ThermodynamicAssumption.isentropic
        })
    m.fs.boiler = Heater(
        default={
            'dynamic': False,
            'property_package': m.fs.properties,
            'has_pressure_change': True
        })
    m.fs.FG_cooler = Heater(
        default={
            'dynamic': False,
            'property_package': m.fs.properties,
            'has_pressure_change': True
        })
    m.fs.pre_boiler = Heater(
        default={
            'dynamic': False,
            'property_package': m.fs.properties,
            'has_pressure_change': False
        })
    m.fs.HTR_pseudo_tube = Heater(
        default={
            'dynamic': False,
            'property_package': m.fs.properties,
            'has_pressure_change': True
        })
    m.fs.LTR_pseudo_tube = Heater(
        default={
            'dynamic': False,
            'property_package': m.fs.properties,
            'has_pressure_change': True
        })

    # _set_numerical_details(m)

    fss = FlowsheetSerializer()
    fss.serialize_flowsheet(m.fs)

    unit_models = fss.get_unit_models()
    unit_model_names_types = []
    for unit_model in unit_models:
        unit_model_names_types.append(unit_models[unit_model])

    unit_models_names_type_truth = [{
        'name': 'M01',
        'type': 'mixer'
    }, {
        'name': 'H02',
        'type': 'heater'
    }, {
        'name': 'F03',
        'type': 'flash'
    }, {
        'name': 'main_compressor',
        'type': 'pressure_changer'
    }, {
        'name': 'bypass_compressor',
        'type': 'pressure_changer'
    }, {
        'name': 'turbine',
        'type': 'pressure_changer'
    }, {
        'name': 'boiler',
        'type': 'heater'
    }, {
        'name': 'FG_cooler',
        'type': 'heater'
    }, {
        'name': 'pre_boiler',
        'type': 'heater'
    }, {
        'name': 'HTR_pseudo_tube',
        'type': 'heater'
    }, {
        'name': 'LTR_pseudo_tube',
        'type': 'heater'
    }, {
        'name': 'split',
        'type': 'separator'
    }]

    # TODO: Examine whether these are in fact appropriate
    inlet_names = {'inlet', 'inlet_1_1',
                   'inlet_2_1'}.union({f'inlet_{n}'
                                       for n in range(1, 9)})
    outlet_names = {'outlet', 'vap_outlet',
                    'liq_outlet'}.union({f'outlet_{n}'
                                         for n in range(1, 8)})
    feed_and_outlet_names_type_truth = [{'name': name, 'type': 'feed'} for name in inlet_names] + \
                                       [{'name': name, 'type': 'product'} for name in outlet_names]
    unit_models_names_type_truth += feed_and_outlet_names_type_truth

    # canonicalize, because lists of dictionaries are awkward to compare
    set_result = set(tuple(sorted(d.items())) for d in unit_model_names_types)
    set_truth = set(
        tuple(sorted(d.items())) for d in unit_models_names_type_truth)
    difference = list(set_truth.symmetric_difference(set_result))
    assert len(difference) == 0

    # TODO Figure out how to test ports. Maybe find out if we can find the parent component for the port?
    # ports = fss.get_ports()
    # assert ports == {"<pyomo.network.port.SimplePort object at 0x7fe8d0d79278>": "<idaes.core.process_block._ScalarMixer object at 0x7fe8d0d60360>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0d792e8>": "<idaes.core.process_block._ScalarMixer object at 0x7fe8d0d60360>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0d79358>": "<idaes.core.process_block._ScalarMixer object at 0x7fe8d0d60360>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0d793c8>": "<idaes.core.process_block._ScalarMixer object at 0x7fe8d0d60360>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0d797b8>": "<idaes.core.process_block._ScalarHeater object at 0x7fe8d0db74c8>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0d79828>": "<idaes.core.process_block._ScalarHeater object at 0x7fe8d0db74c8>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0d79a58>": "<idaes.core.process_block._ScalarStoichiometricReactor object at 0x7fe8d0de2ab0>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0d79ac8>": "<idaes.core.process_block._ScalarStoichiometricReactor object at 0x7fe8d0de2ab0>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0d79eb8>": "<idaes.core.process_block._ScalarFlash object at 0x7fe8d0e0fdc8>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41128>": "<idaes.core.process_block._ScalarFlash object at 0x7fe8d0e0fdc8>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41198>": "<idaes.core.process_block._ScalarFlash object at 0x7fe8d0e0fdc8>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0d79f98>": "<idaes.core.process_block._ScalarFlash object at 0x7fe8d0e0fdc8>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41048>": "<idaes.core.process_block._ScalarFlash object at 0x7fe8d0e0fdc8>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e410b8>": "<idaes.core.process_block._ScalarFlash object at 0x7fe8d0e0fdc8>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41278>": "<idaes.core.process_block._ScalarSeparator object at 0x7fe8d0e45708>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41588>": "<idaes.core.process_block._ScalarSeparator object at 0x7fe8d0e45708>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e415f8>": "<idaes.core.process_block._ScalarSeparator object at 0x7fe8d0e45708>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41828>": "<idaes.core.process_block._ScalarPressureChanger object at 0x7fe8d0e686c0>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41898>": "<idaes.core.process_block._ScalarPressureChanger object at 0x7fe8d0e686c0>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41c88>": "<idaes.core.process_block._ScalarFlash object at 0x7fe8e1405cf0>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41eb8>": "<idaes.core.process_block._ScalarFlash object at 0x7fe8e1405cf0>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41f28>": "<idaes.core.process_block._ScalarFlash object at 0x7fe8e1405cf0>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41e48>": "<idaes.core.process_block._ScalarFlash object at 0x7fe8e1405cf0>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41dd8>": "<idaes.core.process_block._ScalarFlash object at 0x7fe8e1405cf0>",
    #                  "<pyomo.network.port.SimplePort object at 0x7fe8d0e41d68>": "<idaes.core.process_block._ScalarFlash object at 0x7fe8e1405cf0>"
    #                  }

    named_edges_results = {}
    edges = fss.get_edges()

    for name, end_points in edges.items():
        named_edges_results[name] = {
            "source": end_points["source"].getname(),
            "dest": end_points["dest"].getname()
        }

    named_edges_truth = {
        's01': {
            'source': 'M01',
            'dest': 'H02'
        },
        's02': {
            'source': 'H02',
            'dest': 'F03'
        }
    }

    # TODO: as obove, examine whether this is appropriate treatment for arcs connected to inlets/outlets
    # In particular, note that numbered inlet/outlet names are somewhat arbitrary;
    # they're only deterministic due to sorting upon automatic generation.
    in_out_edges_truth = {
        's_inlet': {
            'dest': 'split',
            'source': 'inlet'
        },
        's_inlet_1': {
            'dest': 'FG_cooler',
            'source': 'inlet_1'
        },
        's_inlet_1_1': {
            'dest': 'M01',
            'source': 'inlet_1_1'
        },
        's_inlet_2': {
            'dest': 'HTR_pseudo_tube',
            'source': 'inlet_2'
        },
        's_inlet_2_1': {
            'dest': 'M01',
            'source': 'inlet_2_1'
        },
        's_inlet_3': {
            'dest': 'LTR_pseudo_tube',
            'source': 'inlet_3'
        },
        's_inlet_4': {
            'dest': 'boiler',
            'source': 'inlet_4'
        },
        's_inlet_5': {
            'dest': 'bypass_compressor',
            'source': 'inlet_5'
        },
        's_inlet_6': {
            'dest': 'main_compressor',
            'source': 'inlet_6'
        },
        's_inlet_7': {
            'dest': 'pre_boiler',
            'source': 'inlet_7'
        },
        's_inlet_8': {
            'dest': 'turbine',
            'source': 'inlet_8'
        },
        's_liq_outlet': {
            'dest': 'liq_outlet',
            'source': 'F03'
        },
        's_outlet': {
            'dest': 'outlet',
            'source': 'FG_cooler'
        },
        's_outlet_1': {
            'dest': 'outlet_1',
            'source': 'HTR_pseudo_tube'
        },
        's_outlet_2': {
            'dest': 'outlet_2',
            'source': 'LTR_pseudo_tube'
        },
        's_outlet_3': {
            'dest': 'outlet_3',
            'source': 'boiler'
        },
        's_outlet_4': {
            'dest': 'outlet_4',
            'source': 'bypass_compressor'
        },
        's_outlet_5': {
            'dest': 'outlet_5',
            'source': 'main_compressor'
        },
        's_outlet_6': {
            'dest': 'outlet_6',
            'source': 'pre_boiler'
        },
        's_outlet_7': {
            'dest': 'outlet_7',
            'source': 'turbine'
        },
        's_vap_outlet': {
            'dest': 'vap_outlet',
            'source': 'F03'
        }
    }

    for edge, details in in_out_edges_truth.items():
        named_edges_truth[edge] = details

    assert named_edges_results == named_edges_truth
Esempio n. 7
0
def visualize(flowsheet,
              name,
              browser=True,
              overwrite=False,
              model_server_host='127.0.0.1'):
    """Visualizes the flowsheet, assigning it to the given name. 
    
    Attempts to
    open a browser window to display the visualization app, as well as
    directly showing the URL in case the browser fails to open.

    Usage example:
    
    m = ConcreteModel()
    m.fs = FlowsheetBlock(...)
    ...
    visualize(m.fs, "draftview")
        
    Args: 
        flowsheet: An IDAES flowsheetBlock to be visualized.
        name: A name string to assign to the visualization. This name will be
            attached to the visualization instance as long as the visualization app
            server stays running (e.g. until the parent python kernel is shut down)

    Returns:   
        None.

    Raises:
        None.#TODO
    """
    # Start the model server that contains a reference to the model so that the flask
    # server can ping it when refresh is called in order to get the updated model
    server = fsvis_server()

    url = f"http://{server.host}:{server.port}/app"

    model_server = ModelServer.getInstance(
        flowsheet, name, f"http://{server.host}:{server.port}/fs?id={name}",
        model_server_host)

    model_server_url = f"http://{model_server_host}:{model_server.port}"

    # Check if the {name}.viz file exists and overwrite is not true. If it was True
    # then we want to serialize the flowsheet and reset to the original
    file_path = os.path.expandvars(
        os.path.join(os.path.expanduser("~"), ".idaes", "viz", f"{name}.viz"))
    if os.path.isfile(file_path) and not overwrite:
        print(
            f"Model {name} visualization exists. Reloading the visualization.")
        print(
            "If you don't want to load the existing visualization specify overwrite=True "
            "when calling visualize")
        with open(file_path, "r") as viz_file:
            serialized_flowsheet = json.load(viz_file)
    else:
        serialized_flowsheet = FlowsheetSerializer().serialize(flowsheet, name)

    repeat_until_connection_available(requests.post,
                                      url,
                                      json=serialized_flowsheet,
                                      params={
                                          'id': slugify(name),
                                          "modelurl": model_server_url
                                      })
    if browser:
        success = webbrowser.open(url +
                                  f"?id={name}&modelurl={model_server_url}")
        print(f'Opened in browser window: {success}')
        print(f'{url}?id={name}&modelurl={model_server_url}')

    return server