Skip to content

Commit

Permalink
Merge branch 'main' into idaes-2.1
Browse files Browse the repository at this point in the history
  • Loading branch information
lbianchi-lbl authored May 25, 2023
2 parents 4b2aa5a + 5facc1c commit b4800e0
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def build(self):
self.phase_list,
self.component_list,
mutable=True,
initialize={("Liq", "H2O"): 1e-3, ("Liq", "oil"): 3.5e-3},
initialize={("Liq", "H2O"): 1e-3, ("Liq", "oil"): 3.56e-3},
units=units.kg * units.m**-1 * units.s**-1,
doc="Dynamic viscosity",
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def configure(self):
}
self.default_solution = {
("visc_d_phase_comp", ("Liq", "H2O")): 1e-3,
("visc_d_phase_comp", ("Liq", "oil")): 3.5e-3,
("visc_d_phase_comp", ("Liq", "oil")): 3.56e-3,
("dens_mass_phase_comp", ("Liq", "H2O")): 1e3,
("dens_mass_phase_comp", ("Liq", "oil")): 780,
("mass_frac_phase_comp", ("Liq", "H2O")): 0.990099,
Expand Down Expand Up @@ -66,7 +66,7 @@ def configure(self):
}
self.regression_solution = {
("visc_d_phase_comp", ("Liq", "H2O")): 1e-3,
("visc_d_phase_comp", ("Liq", "oil")): 3.5e-3,
("visc_d_phase_comp", ("Liq", "oil")): 3.56e-3,
("dens_mass_phase_comp", ("Liq", "H2O")): 1e3,
("dens_mass_phase_comp", ("Liq", "oil")): 780,
("mass_frac_phase_comp", ("Liq", "H2O")): 0.5,
Expand Down
35 changes: 35 additions & 0 deletions watertap/tools/parameter_sweep/parameter_sweep.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import pyomo.environ as pyo
import warnings
import copy
import requests
import time

from abc import abstractmethod, ABC
from idaes.core.solvers import get_solver
Expand Down Expand Up @@ -125,6 +127,24 @@ class _ParameterSweepBase(ABC):
),
)

CONFIG.declare(
"publish_progress",
ConfigValue(
default=False,
domain=bool,
description="Boolean to decide whether information about how many iterations of the parameter sweep have completed should be sent.",
),
)

CONFIG.declare(
"publish_address",
ConfigValue(
default="http://localhost:8888",
domain=str,
description="Address to which the parameter sweep progress will be sent.",
),
)

def __init__(
self,
**options,
Expand Down Expand Up @@ -160,6 +180,18 @@ def _assign_variable_names(model, outputs):
exprs[output_name] = _pyo_obj
outputs[output_name] = exprs[output_name]

def _publish_updates(self, iteration, solve_status, solve_time):

if self.config.publish_progress:
publish_dict = {
"worker_number": self.comm.Get_rank(),
"iteration": iteration,
"solve_status": solve_status,
"solve_time": solve_time,
}

return requests.put(self.config.publish_address, data=publish_dict)

def _build_combinations(self, d, sampling_type, num_samples):
num_var_params = len(d)

Expand Down Expand Up @@ -561,6 +593,7 @@ def _do_param_sweep(self, model, sweep_params, outputs, local_values):
# ================================================================

for k in range(local_num_cases):
start_time = time.time()
run_successful = self._run_sample(
model,
reinitialize_values,
Expand All @@ -569,7 +602,9 @@ def _do_param_sweep(self, model, sweep_params, outputs, local_values):
sweep_params,
local_output_dict,
)
time_elapsed = time.time() - start_time
local_solve_successful_list.append(run_successful)
self._publish_updates(k, run_successful, time_elapsed)

local_output_dict["solve_successful"] = local_solve_successful_list

Expand Down
10 changes: 10 additions & 0 deletions watertap/tools/parameter_sweep/tests/test_parameter_sweep.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import pytest
import os
import numpy as np
import requests
import pyomo.environ as pyo

from pyomo.environ import value
Expand Down Expand Up @@ -180,6 +181,15 @@ def test_reverse_geom_build_combinations(self):
assert global_combo_array[-1, 1] == pytest.approx(range_B[1])
assert global_combo_array[-1, 2] == pytest.approx(range_C[1])

@pytest.mark.component
def test_status_publishing(self):
ps = ParameterSweep(
publish_progress=True, publish_address="http://localhost:8888"
)

with pytest.raises(requests.exceptions.ConnectionError):
r = ps._publish_updates(1, True, 5.0)

def test_random_build_combinations(self):
ps = ParameterSweep()

Expand Down
2 changes: 2 additions & 0 deletions watertap/ui/fsapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class ModelExport(BaseModel):
lb: Union[None, float] = 0.0
ub: Union[None, float] = 0.0
has_bounds: bool = True
is_sweep: bool = False

class Config:
arbitrary_types_allowed = True
Expand Down Expand Up @@ -429,6 +430,7 @@ def load(self, data: Dict):

dst.obj.fixed = src.fixed
dst.fixed = src.fixed
dst.is_sweep = src.is_sweep

# update bounds
if src.lb is None or src.lb == "":
Expand Down
94 changes: 61 additions & 33 deletions watertap/unit_models/selective_oil_permeation.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
NonNegativeReals,
Reference,
units,
value,
)
from pyomo.common.config import ConfigBlock, ConfigValue, In

Expand Down Expand Up @@ -191,7 +190,7 @@ def build(self):
# Add unit parameters
self.pore_diameter = Param(
mutable=True,
initialize=4e-8,
initialize=4.7e-8,
units=units_meta("length"),
doc="Average membrane pore diameter",
)
Expand Down Expand Up @@ -305,6 +304,22 @@ def build(self):
doc="Effective fraction of membrane being used for oil transfer",
)

self.effective_area_ratio_num = Var(
self.flowsheet().config.time,
initialize=0.1,
bounds=(0.0, None),
units=units.dimensionless,
doc="Effective area ratio numerator",
)

self.effective_area_ratio_den = Var(
self.flowsheet().config.time,
initialize=1,
bounds=(0.0, None),
units=units.dimensionless,
doc="Effective area ratio denominator",
)

self.recovery_frac_oil = Var(
self.flowsheet().config.time,
initialize=0.5,
Expand Down Expand Up @@ -500,49 +515,53 @@ def eq_flux_vol_oil_pure(b, t):
4 / 3
)

def convert_dimensionless(expr, to_units=None):
"""
Given a pyomo expression and desired units, detect the units of the
expression and convert to the desired units, and return only the
numerical value.
"""
return units.convert_value(
value(expr), from_units=units.get_units(expr), to_units=to_units
@self.Constraint(
self.flowsheet().config.time,
doc="Effective area ratio numerator",
)
def eq_effective_area_ratio_num(b, t):
return b.effective_area_ratio_num[t] == (
b.num_constant
* b.feed_side.properties_in[t].vol_frac_phase_comp["Liq", "oil"]
* (
b.feed_side.properties_in[t].visc_d_phase_comp["Liq", "oil"]
* (units.Pa * units.s) ** -1
)
** b.num_mu_exp
* (b.pressure_transmemb_avg[t] * units.Pa**-1) ** b.num_PT_exp
* (b.liquid_velocity_in[t] * (units.m * units.s**-1) ** -1)
** b.num_v_exp
)

@self.Constraint(
self.flowsheet().config.time,
doc="Effective area ratio for oil transfer",
doc="Effective area ratio denominator",
)
def eq_effective_area_ratio(b, t):
return b.effective_area_ratio[
t
] == b.num_constant * b.feed_side.properties_in[t].vol_frac_phase_comp[
"Liq", "oil"
] * convert_dimensionless(
b.feed_side.properties_in[t].visc_d_phase_comp["Liq", "oil"],
to_units=units.Pa * units.s,
) ** b.num_mu_exp * convert_dimensionless(
b.pressure_transmemb_avg[t], to_units=units.Pa
) ** b.num_PT_exp * convert_dimensionless(
b.liquid_velocity_in[t], to_units=units.m * units.s**-1
) ** b.num_v_exp / (
def eq_effective_area_ratio_den(b, t):
return b.effective_area_ratio_den[t] == (
1
+ b.den_constant
* b.feed_side.properties_in[t].vol_frac_phase_comp["Liq", "oil"]
* convert_dimensionless(
b.feed_side.properties_in[t].visc_d_phase_comp["Liq", "oil"],
to_units=units.Pa * units.s,
* (
b.feed_side.properties_in[t].visc_d_phase_comp["Liq", "oil"]
* (units.Pa * units.s) ** -1
)
** b.den_mu_exp
* convert_dimensionless(b.pressure_transmemb_avg[t], to_units=units.Pa)
** b.den_PT_exp
* convert_dimensionless(
b.liquid_velocity_in[t], to_units=units.m * units.s**-1
)
* (b.pressure_transmemb_avg[t] * units.Pa**-1) ** b.den_PT_exp
* (b.liquid_velocity_in[t] * (units.m * units.s**-1) ** -1)
** b.den_v_exp
)

@self.Constraint(
self.flowsheet().config.time,
doc="Effective area ratio for oil transfer",
)
def eq_effective_area_ratio(b, t):
return (
b.effective_area_ratio_num[t]
== b.effective_area_ratio_den[t] * b.effective_area_ratio[t]
)

@self.Constraint(
self.flowsheet().config.time,
doc="Recovery fraction of oil, mass basis",
Expand Down Expand Up @@ -607,6 +626,7 @@ def initialize_build(
else:
state_args[k] = state_dict[k].value

state_args["flow_mass_phase_comp"][("Liq", "H2O")] = 0
self.properties_permeate.initialize(
outlvl=outlvl,
optarg=optarg,
Expand Down Expand Up @@ -641,6 +661,12 @@ def _get_performance_contents(self, time_point=0):
var_dict["Oil volumetric flux"] = self.flux_vol_oil[time_point]
var_dict["Pure oil volumetric flux"] = self.flux_vol_oil_pure[time_point]
var_dict["Effective area ratio"] = self.effective_area_ratio[time_point]
var_dict["Eff. area ratio numerator"] = self.effective_area_ratio_num[
time_point
]
var_dict["Eff. area ratio denominator"] = self.effective_area_ratio_den[
time_point
]
var_dict["Oil recovery"] = self.recovery_frac_oil[time_point]
var_dict["Shell side liquid velocity in"] = self.liquid_velocity_in[time_point]
return {"vars": var_dict, "exprs": expr_dict}
Expand All @@ -661,7 +687,9 @@ def calculate_scaling_factors(self):
iscale.set_scaling_factor(self.area, 1e-1)
iscale.set_scaling_factor(self.flux_vol_oil, 1e9)
iscale.set_scaling_factor(self.flux_vol_oil_pure, 1e6)
iscale.set_scaling_factor(self.effective_area_ratio, 1e2)
iscale.set_scaling_factor(self.effective_area_ratio, 1e1)
iscale.set_scaling_factor(self.effective_area_ratio_num, 1e1)
iscale.set_scaling_factor(self.effective_area_ratio_den, 1)
iscale.set_scaling_factor(self.recovery_frac_oil, 1)
iscale.set_scaling_factor(self.liquid_velocity_in, 1e2)
iscale.set_scaling_factor(
Expand Down
35 changes: 20 additions & 15 deletions watertap/unit_models/tests/test_selective_oil_permeation.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,14 @@ def unit_frame(self):

# fully specify system
m.fs.unit.feed_side.properties_in[0].temperature.fix(298.15) # temp in K
m.fs.unit.feed_side.properties_in[0].pressure.fix(1.48 * units.bar)
# The below feed data corresponds roughly to 3.8 L/min flow with 500 ppm oil
m.fs.unit.feed_side.properties_in[0].pressure.fix(2.52 * units.bar)
m.fs.unit.feed_side.properties_in[0].flow_mass_phase_comp["Liq", "H2O"].fix(
6.3e-2
6.27e-2
) # H2O flow in kg/s
m.fs.unit.feed_side.properties_in[0].flow_mass_phase_comp["Liq", "oil"].fix(
3.2e-5
4.94e-4
) # oil flow in kg/s
m.fs.unit.feed_side.properties_out[0].pressure.fix(1.20 * units.bar)
m.fs.unit.feed_side.properties_out[0].pressure.fix(2.24 * units.bar)
m.fs.unit.area.fix(1.4) # membrane area in m^2
m.fs.unit.properties_permeate[0].pressure.fix(1 * units.bar)

Expand All @@ -108,8 +107,8 @@ def test_build(self, unit_frame):
) # number of state variables for SOP property package
assert isinstance(port, Port)

assert number_variables(m) == 28
assert number_total_constraints(m) == 20
assert number_variables(m) == 30
assert number_total_constraints(m) == 22
assert number_unused_variables(m) == 0
assert_units_consistent(m)

Expand Down Expand Up @@ -192,25 +191,31 @@ def test_conservation(self, unit_frame):
@pytest.mark.component
def test_solution(self, unit_frame):
m = unit_frame
assert pytest.approx(6.1178e-6, rel=1e-3) == value(
assert pytest.approx(3.32237e-4, rel=1e-3) == value(
m.fs.unit.properties_permeate[0].flow_mass_phase_comp["Liq", "oil"]
)
assert pytest.approx(3.4e4, rel=1e-3) == value(
assert pytest.approx(1.38e5, rel=1e-3) == value(
m.fs.unit.pressure_transmemb_avg[0]
)
assert pytest.approx(-2.8e4, rel=1e-3) == value(m.fs.unit.deltaP[0])
assert pytest.approx(5.6024e-9, rel=1e-3) == value(m.fs.unit.flux_vol_oil[0])
assert pytest.approx(6.0346e-7, rel=1e-3) == value(
assert pytest.approx(3.0425e-07, rel=1e-3) == value(m.fs.unit.flux_vol_oil[0])
assert pytest.approx(3.3246e-06, rel=1e-3) == value(
m.fs.unit.flux_vol_oil_pure[0]
)
assert pytest.approx(9.2802e-3, rel=1e-3) == value(
assert pytest.approx(0.091512, rel=1e-3) == value(
m.fs.unit.effective_area_ratio[0]
)
assert pytest.approx(0.19118, rel=1e-3) == value(m.fs.unit.recovery_frac_oil[0])
assert pytest.approx(1.9596e-2, rel=1e-3) == value(
assert pytest.approx(0.10799, rel=1e-3) == value(
m.fs.unit.effective_area_ratio_num[0]
)
assert pytest.approx(1.1801, rel=1e-3) == value(
m.fs.unit.effective_area_ratio_den[0]
)
assert pytest.approx(0.67254, rel=1e-3) == value(m.fs.unit.recovery_frac_oil[0])
assert pytest.approx(0.019687, rel=1e-3) == value(
m.fs.unit.liquid_velocity_in[0]
)
assert pytest.approx(6.1178e-6, rel=1e-3) == value(
assert pytest.approx(3.32237e-4, rel=1e-3) == value(
m.fs.unit.mass_transfer_oil[0]
)

Expand Down

0 comments on commit b4800e0

Please sign in to comment.