watertap.ui package

Submodules

watertap.ui.fsapi module

Simple flowsheet interface API

class watertap.ui.fsapi.Actions(value)[source]

Bases: str, Enum

Known actions that can be run. Actions that users should not run directly (unless they know what they are doing) are prefixed with an underscore.

class watertap.ui.fsapi.FSI

Forward-reference to a FlowsheetInterface type, used in FlowsheetInterface.find()

alias of TypeVar(‘FSI’, bound=FlowsheetInterface)

class watertap.ui.fsapi.FlowsheetCategory(value)[source]

Bases: str, Enum

Flowsheet Categories

class watertap.ui.fsapi.FlowsheetExport(*, m: object = None, obj: object = None, name: None | str = '', description: None | str = '', exports: Dict[str, ModelExport] = {}, version: int = 2, requires_idaes_solver: bool = False, dof: int = 0, sweep_results: None | dict = {}, build_options: Dict[str, ModelOption] = {})[source]

Bases: BaseModel

A flowsheet and its contained exported model objects.

add(*args, data: dict | ModelExport | None = None, **kwargs) object[source]

Add a new variable (or other model object).

There are a few different ways of invoking this function. Users will typically use this form:

add(obj=<pyomo object>, name="My value name", ..etc..)

where the keywords after obj match the non-computed names in ModelExport.

If these same name/value pairs are already in a dictionary, this form is more convenient:

add(data=my_dict_of_name_value_pairs)

If you have an existing ModelExport object, you can add it more directly with:

add(my_object)
# -- OR --
add(data=my_object)
Parameters:
  • *args – If present, should be a single non-named argument, which is a ModelExport object. Create by adding it.

  • data – If present, create from this argument. If it’s a dict, create from its values just as from the kwargs. Otherwise, it should be a ModelExport object, and create by adding it.

  • kwargs – Name/value pairs to create a ModelExport object. Accepted names and default values are in the ModelExport.

Raises:

KeyError – If the name of the Pyomo object is the same as an existing one, i.e. refuse to overwrite.

add_option(name: str, **kwargs) ModelOption[source]

Add an ‘option’ to the flowsheet that can be displayed and manipulated from the UI.

Constructs a ModelOption instance with provided args and adds it to the dict of options, keyed by its name.

Parameters:
  • name – Name of option (internal, for accessing the option)

  • kwargs – Fields of ModelOption

from_csv(file: str | Path, flowsheet)[source]

Load multiple exports from the given CSV file.

CSV file format rules:

  • Always use a header row. The names are case-insensitive, order is not important. The ‘name’, ‘obj’, and ‘ui_units’ columns are required.

  • Columns names should match the non-computed names in ModelExport. See .add() for a list.

  • The object to export should be in a column named ‘obj’, prefixed with ‘fs.’

  • For units, use Pyomo units module as ‘units’, e.g., ‘mg/L’ is units.mg / units.L

For example:

name,obj,description,ui_units,display_units,rounding,is_input,input_category,is_output,output_category
Leach liquid feed rate,fs.leach_liquid_feed.flow_vol[0],Leach liquid feed volumetric flow rate,units.L/units.hour,L/h,2,TRUE,Liquid feed,FALSE,
Leach liquid feed H,"fs.leach_liquid_feed.conc_mass_comp[0,'H']",Leach liquid feed hydrogen mass composition,units.mg/units.L,mg/L,3,TRUE,Liquid feed,FALSE,
.......etc.......
Parameters:
  • file – Filename or path. If not an absolute path, start from the directory of the caller’s file.

  • flowsheet – Flowsheet used to evaluate the exported objects.

Returns:

Number of exports added

Return type:

int

Raises:
  • IOError – if input file doesn’t exist

  • ValueError – Invalid data in input file (error message will have details)

model_computed_fields: ClassVar[dict[str, ComputedFieldInfo]] = {}

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[dict[str, FieldInfo]] = {'build_options': FieldInfo(annotation=Dict[str, ModelOption], required=False, default={}), 'description': FieldInfo(annotation=Union[NoneType, str], required=False, default='', validate_default=True), 'dof': FieldInfo(annotation=int, required=False, default=0), 'exports': FieldInfo(annotation=Dict[str, ModelExport], required=False, default={}), 'm': FieldInfo(annotation=object, required=False, default=None, exclude=True), 'name': FieldInfo(annotation=Union[NoneType, str], required=False, default='', validate_default=True), 'obj': FieldInfo(annotation=object, required=False, default=None, exclude=True), 'requires_idaes_solver': FieldInfo(annotation=bool, required=False, default=False), 'sweep_results': FieldInfo(annotation=Union[NoneType, dict], required=False, default={}), 'version': FieldInfo(annotation=int, required=False, default=2)}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].

This replaces Model.__fields__ from Pydantic V1.

to_csv(output: TextIOBase | Path | str | None = None) int[source]

Write wrapped objects as CSV.

Parameters:

output – Where to write CSV file. Can be a stream, path, or filename.

Returns:

Number of objects written into file.

Raises:

IOError – If path is given, and not writable

class watertap.ui.fsapi.FlowsheetInterface(fs: FlowsheetExport | None = None, do_build: Callable | None = None, do_export: Callable | None = None, do_solve: Callable | None = None, get_diagram: Callable | None = None, category: FlowsheetCategory | None = None, custom_do_param_sweep_kwargs: Dict | None = None, **kwargs)[source]

Bases: object

Interface between users, UI developers, and flowsheet models.

class MissingObject(key, name)

Bases: tuple

Type of item in list MissingObjectError.missing. key is the unique key assigned to the variable, name is the variable name in the flowsheet

key

Alias for field number 0

name

Alias for field number 1

exception MissingObjectError(missing)[source]

Bases: Exception

Error returned if data in load refers to a variable not found in the target object.

Use the .missing attribute of the error object to get the list of MissingObjects.

__init__(missing)[source]
UI_HOOK = 'export_to_ui'

Function to look for in modules. See find().

__init__(fs: FlowsheetExport | None = None, do_build: Callable | None = None, do_export: Callable | None = None, do_solve: Callable | None = None, get_diagram: Callable | None = None, category: FlowsheetCategory | None = None, custom_do_param_sweep_kwargs: Dict | None = None, **kwargs)[source]

Constructor.

Parameters:
  • fs – An existing wrapper to a flowsheet object. If this is not provided, then one will be constructed by passing the keyword arguments to the built-in pydantic model_validate() method of FlowsheetExport.

  • do_build – Function to call to build the flowsheet. It should build the flowsheet model and return the FlowsheetBlock, which is typically the fs attribute of the model object. Required

  • do_export – Function to call to export variables after the model is built. This will be called automatically by build(). Required

  • do_solve – Function to solve the model. It should return the result that the solver itself returns. Required

  • custom_do_param_sweep_kwargs – Option for setting up parallel solver using custom solve function.

  • **kwargs – See fs arg. If the fs arg is provided, these are ignored.

add_action(action_name: str, action_func: Callable)[source]

Add an action for the flowsheet.

Parameters:
  • action_name – Name of the action to take (see Actions)

  • action_func – Function to call for the action

Returns:

None

build(**kwargs)[source]

Build flowsheet

Parameters:

**kwargs – User-defined values

Returns:

None

Raises:

RuntimeError – If the build fails

dict() Dict[source]

Serialize.

Returns:

Serialized contained FlowsheetExport object

export_values()[source]

Copy current values in underlying Pyomo model into exported model.

Side-effects:

Attribute fs_exp is modified.

classmethod from_installed_packages(group_name: str = 'watertap.flowsheets') Dict[str, FlowsheetInterface][source]

Get all flowsheet interfaces defined as entry points within the Python packages installed in the environment.

This uses the importlib.metadata.entry_points() function to fetch the list of flowsheets declared as part of a Python package distribution’s entry points under the group group_name.

To set up a flowsheet interface for discovery, locate your Python package distribution’s file (normally setup.py, pyproject.toml, or equivalent) and add an entry in the entry_points section.

For example, to add a flowsheet defined in watertap/flowsheets/flowsheets/my_flowsheet.py so that it can be discovered with the name my_flowsheet wherever the watertap package is installed, the following should be added to WaterTAP’s setup.py:

setup(
    name="watertap",
    # other setup() sections
    entry_points={
        "watertap.flowsheets": [
             # other flowsheet entry points
             "my_flowsheet = watertap.flowsheets.flowsheets.my_flowsheet",
        ]
    }
)
Parameters:

group_name – The entry_points group from which the flowsheet interface modules will be populated.

Returns:

Mapping with keys the module names and values FlowsheetInterface objects

classmethod from_module(module: str | module) FlowsheetInterface | None[source]

Get a a flowsheet interface for module.

Parameters:

module – The module

Returns:

A flowsheet interface or None if it failed

get_action(name: str) Callable | None[source]

Get the function for an add()-ed action.

Parameters:

name – Name of the action (see Actions)

Returns:

Function for this action

Raises:

KeyError, if no such action is defined

get_diagram(**kwargs)[source]

Return diagram image name.

Parameters:

**kwargs – User-defined values

Returns:

Return image file name if get_diagram function is callable. Otherwise, return none

load(data: Dict)[source]

Load values from the data into corresponding variables in this instance’s FlowsheetObject.

Parameters:

data – The input flowsheet (probably deserialized from JSON)

run_action(name, **kwargs)[source]

Run the named action.

select_option(option_name: str, new_option: str)[source]

Update flowsheet with selected option.

Parameters:
  • data – The input flowsheet

  • option_name – Name of selected option

Returns:

None

solve(**kwargs)[source]

Solve flowsheet.

Parameters:

**kwargs – User-defined values

Returns:

Return value of the underlying solve function

Raises:

RuntimeError – if the solver did not terminate in an optimal solution

class watertap.ui.fsapi.ModelExport(*, obj: object | None = None, name: str = '', value: float = 0.0, ui_units: object = None, display_units: str = '', rounding: float = 0, description: str = '', is_input: bool = True, is_output: bool = True, is_readonly: None | bool = None, input_category: str | None = None, output_category: str | None = None, chart_type: str | None = None, chart_group: str | None = None, obj_key: None | str = None, fixed: bool = True, lb: None | float = 0.0, ub: None | float = 0.0, num_samples: int = 2, has_bounds: bool = True, is_sweep: bool = False)[source]

Bases: BaseModel

A variable, expression, or parameter.

model_computed_fields: ClassVar[dict[str, ComputedFieldInfo]] = {}

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[dict[str, FieldInfo]] = {'chart_group': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'chart_type': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'description': FieldInfo(annotation=str, required=False, default=''), 'display_units': FieldInfo(annotation=str, required=False, default=''), 'fixed': FieldInfo(annotation=bool, required=False, default=True), 'has_bounds': FieldInfo(annotation=bool, required=False, default=True), 'input_category': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'is_input': FieldInfo(annotation=bool, required=False, default=True), 'is_output': FieldInfo(annotation=bool, required=False, default=True), 'is_readonly': FieldInfo(annotation=Union[NoneType, bool], required=False, default=None, validate_default=True), 'is_sweep': FieldInfo(annotation=bool, required=False, default=False), 'lb': FieldInfo(annotation=Union[NoneType, float], required=False, default=0.0), 'name': FieldInfo(annotation=str, required=False, default=''), 'num_samples': FieldInfo(annotation=int, required=False, default=2), 'obj': FieldInfo(annotation=Union[object, NoneType], required=False, default=None, exclude=True), 'obj_key': FieldInfo(annotation=Union[NoneType, str], required=False, default=None, validate_default=True), 'output_category': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'rounding': FieldInfo(annotation=float, required=False, default=0), 'ub': FieldInfo(annotation=Union[NoneType, float], required=False, default=0.0), 'ui_units': FieldInfo(annotation=object, required=False, default=None, exclude=True), 'value': FieldInfo(annotation=float, required=False, default=0.0)}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].

This replaces Model.__fields__ from Pydantic V1.

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self – The BaseModel instance.

  • context – The context.

class watertap.ui.fsapi.ModelOption(*, name: str, category: str = 'Build Options', display_name: None | str = None, description: None | str = None, display_values: List[Any] = [], values_allowed: str | List[Any], min_val: None | int | float = None, max_val: None | int | float = None, value: Any = None)[source]

Bases: BaseModel

An option for building/running the model.

model_computed_fields: ClassVar[dict[str, ComputedFieldInfo]] = {}

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[dict[str, FieldInfo]] = {'category': FieldInfo(annotation=str, required=False, default='Build Options'), 'description': FieldInfo(annotation=Union[NoneType, str], required=False, default=None, validate_default=True), 'display_name': FieldInfo(annotation=Union[NoneType, str], required=False, default=None, validate_default=True), 'display_values': FieldInfo(annotation=List[Any], required=False, default=[]), 'max_val': FieldInfo(annotation=Union[NoneType, int, float], required=False, default=None), 'min_val': FieldInfo(annotation=Union[NoneType, int, float], required=False, default=None), 'name': FieldInfo(annotation=str, required=True), 'value': FieldInfo(annotation=Any, required=False, default=None), 'values_allowed': FieldInfo(annotation=Union[str, List[Any]], required=True)}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].

This replaces Model.__fields__ from Pydantic V1.

exception watertap.ui.fsapi.UnsupportedObjType(obj: Any, supported: Optional = None)[source]

Bases: TypeError

__init__(obj: Any, supported: Optional = None)[source]

Module contents