def Pump_frame(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = props.SeawaterParameterBlock() m.fs.unit = Pump(default={"property_package": m.fs.properties}) # fully specify system feed_flow_mass = 1 feed_mass_frac_TDS = 0.035 feed_pressure_in = 1e5 feed_pressure_out = 5e5 feed_temperature = 273.15 + 25 efi_pump = 0.75 feed_mass_frac_H2O = 1 - feed_mass_frac_TDS m.fs.unit.inlet.flow_mass_phase_comp[0, "Liq", "TDS"].fix( feed_flow_mass * feed_mass_frac_TDS ) m.fs.unit.inlet.flow_mass_phase_comp[0, "Liq", "H2O"].fix( feed_flow_mass * feed_mass_frac_H2O ) m.fs.unit.inlet.pressure[0].fix(feed_pressure_in) m.fs.unit.inlet.temperature[0].fix(feed_temperature) m.fs.unit.outlet.pressure[0].fix(feed_pressure_out) m.fs.unit.efficiency_pump.fix(efi_pump) return m
def unit_frame(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={'dynamic': False}) m.fs.properties = props.SeawaterParameterBlock() m.fs.unit = PressureExchanger( default={'property_package': m.fs.properties}) # Specify inlet conditions temperature = 25 + 273.15 flow_vol = 1e-3 lowP_mass_frac_TDS = 0.035 lowP_pressure = 101325 highP_mass_frac_TDS = 0.07 highP_pressure = 50e5 m.fs.unit.low_pressure_side.properties_in[0].flow_vol_phase['Liq'].fix( flow_vol) m.fs.unit.low_pressure_side.properties_in[0].mass_frac_phase_comp[ 'Liq', 'TDS'].fix(lowP_mass_frac_TDS) m.fs.unit.low_pressure_side.properties_in[0].pressure.fix( lowP_pressure) m.fs.unit.low_pressure_side.properties_in[0].temperature.fix( temperature) m.fs.unit.high_pressure_side.properties_in[0].flow_vol_phase[ 'Liq'].fix(flow_vol) m.fs.unit.high_pressure_side.properties_in[0].mass_frac_phase_comp[ 'Liq', 'TDS'].fix(highP_mass_frac_TDS) m.fs.unit.high_pressure_side.properties_in[0].pressure.fix( highP_pressure) m.fs.unit.high_pressure_side.properties_in[0].temperature.fix( temperature) # solve inlet conditions and only fix state variables (i.e. unfix flow_vol and mass_frac_phase) results = solver.solve(m.fs.unit.low_pressure_side.properties_in[0]) assert results.solver.termination_condition == TerminationCondition.optimal m.fs.unit.low_pressure_side.properties_in[0].flow_mass_phase_comp[ 'Liq', 'TDS'].fix() m.fs.unit.low_pressure_side.properties_in[0].flow_vol_phase[ 'Liq'].unfix() m.fs.unit.low_pressure_side.properties_in[0].mass_frac_phase_comp[ 'Liq', 'TDS'].unfix() results = solver.solve(m.fs.unit.high_pressure_side.properties_in[0]) assert results.solver.termination_condition == TerminationCondition.optimal m.fs.unit.high_pressure_side.properties_in[0].flow_mass_phase_comp[ 'Liq', 'H2O'].fix() m.fs.unit.high_pressure_side.properties_in[0].flow_mass_phase_comp[ 'Liq', 'TDS'].fix() m.fs.unit.high_pressure_side.properties_in[0].flow_vol_phase[ 'Liq'].unfix() m.fs.unit.high_pressure_side.properties_in[0].mass_frac_phase_comp[ 'Liq', 'TDS'].unfix() # Specify unit efficiency = 0.95 m.fs.unit.efficiency_pressure_exchanger.fix(efficiency) return m
def test_config(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = props.SeawaterParameterBlock() m.fs.unit = PressureExchanger( default={"property_package": m.fs.properties}) # check unit config arguments assert len(m.fs.unit.config) == 7 assert not m.fs.unit.config.dynamic assert not m.fs.unit.config.has_holdup assert m.fs.unit.config.material_balance_type == MaterialBalanceType.useDefault assert m.fs.unit.config.energy_balance_type == EnergyBalanceType.useDefault assert m.fs.unit.config.momentum_balance_type == MomentumBalanceType.pressureTotal assert m.fs.unit.config.property_package is m.fs.properties
def build(m): # Properties m.fs.properties_feed = props_sw.SeawaterParameterBlock() m.fs.properties_vapor = props_w.WaterParameterBlock() # Evaporator m.fs.evaporator = Evaporator( default={ "property_package_feed": m.fs.properties_feed, "property_package_vapor": m.fs.properties_vapor, }) # Compressor m.fs.compressor = Compressor( default={"property_package": m.fs.properties_vapor}) # Connections m.fs.s01 = Arc(source=m.fs.evaporator.outlet_vapor, destination=m.fs.compressor.inlet) m.fs.s02 = Arc(source=m.fs.compressor.outlet, destination=m.fs.evaporator.inlet_condenser) TransformationFactory("network.expand_arcs").apply_to(m)
def test_evaporator(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties_feed = props_sw.SeawaterParameterBlock() m.fs.properties_vapor = props_w.WaterParameterBlock() m.fs.evaporator = Evaporator( default={ "property_package_feed": m.fs.properties_feed, "property_package_vapor": m.fs.properties_vapor, }) # scaling m.fs.properties_feed.set_default_scaling("flow_mass_phase_comp", 1, index=("Liq", "H2O")) m.fs.properties_feed.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "TDS")) m.fs.properties_vapor.set_default_scaling("flow_mass_phase_comp", 1, index=("Vap", "H2O")) m.fs.properties_vapor.set_default_scaling("flow_mass_phase_comp", 1, index=("Liq", "H2O")) iscale.set_scaling_factor(m.fs.evaporator.area, 1e-3) iscale.set_scaling_factor(m.fs.evaporator.U, 1e-3) iscale.set_scaling_factor(m.fs.evaporator.delta_temperature_in, 1e-1) iscale.set_scaling_factor(m.fs.evaporator.delta_temperature_out, 1e-1) iscale.set_scaling_factor(m.fs.evaporator.lmtd, 1e-1) # iscale.set_scaling_factor(m.fs.evaporator.heat_transfer, 1e-6) iscale.calculate_scaling_factors(m) # assert False # state variables # Feed inlet m.fs.evaporator.inlet_feed.flow_mass_phase_comp[0, "Liq", "H2O"].fix(10) m.fs.evaporator.inlet_feed.flow_mass_phase_comp[0, "Liq", "TDS"].fix(0.05) m.fs.evaporator.inlet_feed.temperature[0].fix(273.15 + 50.52) # K m.fs.evaporator.inlet_feed.pressure[0].fix(1e5) # Pa # Condenser inlet m.fs.evaporator.inlet_condenser.flow_mass_phase_comp[0, "Vap", "H2O"].fix(0.5) m.fs.evaporator.inlet_condenser.flow_mass_phase_comp[0, "Liq", "H2O"].fix(1e-8) m.fs.evaporator.inlet_condenser.temperature[0].fix(400) # K m.fs.evaporator.inlet_condenser.pressure[0].fix(0.5e5) # Pa # Evaporator/condenser specifications m.fs.evaporator.outlet_brine.temperature[0].fix(273.15 + 60) m.fs.evaporator.U.fix(1e3) # W/K-m^2 m.fs.evaporator.area.fix(100) # m^2 # check build assert_units_consistent(m) assert degrees_of_freedom(m) == 0 # initialize m.fs.evaporator.initialize() # solve solver = get_solver() results = solver.solve(m, tee=False) assert_optimal_termination(results) # check values, TODO: make a report for the evaporator # m.fs.evaporator.display() vapor_blk = m.fs.evaporator.feed_side.properties_vapor[0] assert vapor_blk.flow_mass_phase_comp["Vap", "H2O"].value == pytest.approx( 0.3540, rel=1e-3) assert m.fs.evaporator.lmtd.value == pytest.approx(12.30, rel=1e-3) assert m.fs.evaporator.feed_side.heat_transfer.value == pytest.approx( 1.230e6, rel=1e-3)
def test_build(): m = ConcreteModel() m.fs = FlowsheetBlock(default={'dynamic': False}) m.fs.properties = props.SeawaterParameterBlock() m.fs.unit = PressureExchanger( default={'property_package': m.fs.properties}) # test ports and state variables port_lst = [ 'low_pressure_inlet', 'low_pressure_outlet', 'high_pressure_inlet', 'high_pressure_outlet' ] port_vars_lst = ['flow_mass_phase_comp', 'pressure', 'temperature'] for port_str in port_lst: assert hasattr(m.fs.unit, port_str) port = getattr(m.fs.unit, port_str) assert len(port.vars) == 3 assert isinstance(port, Port) for var_str in port_vars_lst: assert hasattr(port, var_str) var = getattr(port, var_str) assert isinstance(var, Var) # test unit variables assert hasattr(m.fs.unit, 'efficiency_pressure_exchanger') assert isinstance(m.fs.unit.efficiency_pressure_exchanger, Var) # test unit constraints unit_cons_lst = [ 'eq_pressure_transfer', 'eq_equal_flow_vol', 'eq_equal_low_pressure' ] for c in unit_cons_lst: assert hasattr(m.fs.unit, c) con = getattr(m.fs.unit, c) assert isinstance(con, Constraint) # test control volumes, only terms directly used by pressure exchanger cv_list = ['low_pressure_side', 'high_pressure_side'] cv_var_lst = ['deltaP'] cv_con_lst = ['eq_isothermal_temperature'] cv_exp_lst = ['work'] for cv_str in cv_list: assert hasattr(m.fs.unit, cv_str) cv = getattr(m.fs.unit, cv_str) for cv_var_str in cv_var_lst: cv_var = getattr(cv, cv_var_str) assert isinstance(cv_var, Var) for cv_con_str in cv_con_lst: cv_con = getattr(cv, cv_con_str) assert isinstance(cv_con, Constraint) for cv_exp_str in cv_exp_lst: cv_exp = getattr(cv, cv_exp_str) assert isinstance(cv_exp, Expression) # test state blocks, only terms directly used by pressure exchanger cv_stateblock_lst = ['properties_in', 'properties_out'] stateblock_var_lst = ['pressure', 'temperature'] stateblock_exp_lst = ['flow_vol'] for cv_str in cv_list: cv = getattr(m.fs.unit, cv_str) for cv_sb_str in cv_stateblock_lst: assert hasattr(cv, cv_sb_str) cv_sb = getattr(cv, cv_sb_str) for sb_var_str in stateblock_var_lst: assert hasattr(cv_sb[0], sb_var_str) sb_var = getattr(cv_sb[0], sb_var_str) assert isinstance(sb_var, Var) for sb_exp_str in stateblock_exp_lst: assert hasattr(cv_sb[0], sb_exp_str) sb_exp = getattr(cv_sb[0], sb_exp_str) assert isinstance(sb_exp, Expression) # test statistics assert number_variables(m.fs.unit) == 39 assert number_total_constraints(m.fs.unit) == 31 assert number_unused_variables(m.fs.unit) == 0
def test_heat_exchanger(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = props.SeawaterParameterBlock() m.fs.unit = HeatExchanger( default={ "hot_side_name": "hot", "cold_side_name": "cold", "hot": { "property_package": m.fs.properties }, "cold": { "property_package": m.fs.properties }, "delta_temperature_callback": delta_temperature_chen_callback, "flow_pattern": HeatExchangerFlowPattern.countercurrent, }) # scaling m.fs.properties.set_default_scaling("flow_mass_phase_comp", 1, index=("Liq", "H2O")) m.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "TDS")) iscale.set_scaling_factor(m.fs.unit.hot.heat, 1e-3) iscale.set_scaling_factor(m.fs.unit.cold.heat, 1e-3) iscale.set_scaling_factor(m.fs.unit.overall_heat_transfer_coefficient, 1e-3) iscale.set_scaling_factor(m.fs.unit.area, 1) iscale.calculate_scaling_factors(m) # ---specifications--- # state variables m.fs.unit.hot_inlet.flow_mass_phase_comp[0, "Liq", "H2O"].fix(1) m.fs.unit.hot_inlet.flow_mass_phase_comp[0, "Liq", "TDS"].fix(0.01) m.fs.unit.hot_inlet.temperature[0].fix(350) m.fs.unit.hot_inlet.pressure[0].fix(2e5) m.fs.unit.cold_inlet.flow_mass_phase_comp[0, "Liq", "H2O"].fix(0.5) m.fs.unit.cold_inlet.flow_mass_phase_comp[0, "Liq", "TDS"].fix(0.01) m.fs.unit.cold_inlet.temperature[0].fix(298) m.fs.unit.cold_inlet.pressure[0].fix(2e5) m.fs.unit.area.fix(5) m.fs.unit.overall_heat_transfer_coefficient.fix(1000) # solving assert_units_consistent(m) degrees_of_freedom(m) m.fs.unit.initialize() solver = get_solver() results = solver.solve(m, tee=False) assert_optimal_termination(results) report_io = StringIO() m.fs.unit.report(ostream=report_io) output = """ ==================================================================================== Unit : fs.unit Time: 0.0 ------------------------------------------------------------------------------------ Unit Performance Variables: Key : Value : Fixed : Bounds HX Area : 5.0000 : True : (0, None) HX Coefficient : 1000.0 : True : (0, None) Heat Duty : 89050. : False : (None, None) Expressions: Key : Value Delta T Driving : 17.810 Delta T In : 9.2239 Delta T Out : 30.689 ------------------------------------------------------------------------------------ Stream Table Hot Inlet Hot Outlet Cold Inlet Cold Outlet flow_mass_phase_comp ('Liq', 'H2O') 1.0000 1.0000 0.50000 0.50000 flow_mass_phase_comp ('Liq', 'TDS') 0.010000 0.010000 0.010000 0.010000 temperature 350.00 328.69 298.00 340.78 pressure 2.0000e+05 2.0000e+05 2.0000e+05 2.0000e+05 ==================================================================================== """ assert output == report_io.getvalue()
def build_prop(m, base="TDS"): """ Builds a property package for the specified base. Includes default scaling. Bases include: 'TDS', 'ion', 'salt'. """ if base == "TDS": m.fs.prop_TDS = seawater_prop_pack.SeawaterParameterBlock() m.fs.prop_TDS.set_default_scaling("flow_mass_phase_comp", 1, index=("Liq", "H2O")) m.fs.prop_TDS.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "TDS")) elif base == "ion": m.fs.prop_ion = seawater_ion_prop_pack.PropParameterBlock() m.fs.prop_ion.set_default_scaling("flow_mass_phase_comp", 1, index=("Liq", "H2O")) m.fs.prop_ion.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "Na")) m.fs.prop_ion.set_default_scaling("flow_mass_phase_comp", 1e4, index=("Liq", "Ca")) m.fs.prop_ion.set_default_scaling("flow_mass_phase_comp", 1e3, index=("Liq", "Mg")) m.fs.prop_ion.set_default_scaling("flow_mass_phase_comp", 1e3, index=("Liq", "SO4")) m.fs.prop_ion.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "Cl")) elif base == "salt": m.fs.prop_salt = seawater_salt_prop_pack.PropParameterBlock() m.fs.prop_salt.set_default_scaling("flow_mass_phase_comp", 1, index=("Liq", "H2O")) m.fs.prop_salt.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "NaCl")) m.fs.prop_salt.set_default_scaling("flow_mass_phase_comp", 1e3, index=("Liq", "CaSO4")) m.fs.prop_salt.set_default_scaling("flow_mass_phase_comp", 1e3, index=("Liq", "MgSO4")) m.fs.prop_salt.set_default_scaling("flow_mass_phase_comp", 1e3, index=("Liq", "MgCl2")) elif base == "eNRTL": m.fs.prop_eNRTL = GenericParameterBlock( default=entrl_config_FpcTP.configuration) # default scaling in config file else: raise ValueError( "Unexpected property base {base} provided to build_prop" "".format(base=base))
def build_prop(m, base='TDS'): """ Builds a property package for the specified base. Includes default scaling. Bases include: 'TDS', 'ion', 'salt'. """ if base == 'TDS': m.fs.prop_TDS = seawater_prop_pack.SeawaterParameterBlock() m.fs.prop_TDS.set_default_scaling('flow_mass_phase_comp', 1, index=('Liq', 'H2O')) m.fs.prop_TDS.set_default_scaling('flow_mass_phase_comp', 1e2, index=('Liq', 'TDS')) elif base == 'ion': m.fs.prop_ion = seawater_ion_prop_pack.PropParameterBlock() m.fs.prop_ion.set_default_scaling('flow_mass_phase_comp', 1, index=('Liq', 'H2O')) m.fs.prop_ion.set_default_scaling('flow_mass_phase_comp', 1e2, index=('Liq', 'Na')) m.fs.prop_ion.set_default_scaling('flow_mass_phase_comp', 1e4, index=('Liq', 'Ca')) m.fs.prop_ion.set_default_scaling('flow_mass_phase_comp', 1e3, index=('Liq', 'Mg')) m.fs.prop_ion.set_default_scaling('flow_mass_phase_comp', 1e3, index=('Liq', 'SO4')) m.fs.prop_ion.set_default_scaling('flow_mass_phase_comp', 1e2, index=('Liq', 'Cl')) elif base == 'salt': m.fs.prop_salt = seawater_salt_prop_pack.PropParameterBlock() m.fs.prop_salt.set_default_scaling('flow_mass_phase_comp', 1, index=('Liq', 'H2O')) m.fs.prop_salt.set_default_scaling('flow_mass_phase_comp', 1e2, index=('Liq', 'NaCl')) m.fs.prop_salt.set_default_scaling('flow_mass_phase_comp', 1e3, index=('Liq', 'CaSO4')) m.fs.prop_salt.set_default_scaling('flow_mass_phase_comp', 1e3, index=('Liq', 'MgSO4')) m.fs.prop_salt.set_default_scaling('flow_mass_phase_comp', 1e3, index=('Liq', 'MgCl2')) elif base == 'eNRTL': m.fs.prop_eNRTL = GenericParameterBlock( default=entrl_config_FpcTP.configuration) # default scaling in config file else: raise ValueError( 'Unexpected property base {base} provided to build_prop' ''.format(base=base))
def test_heat_exchanger(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = props.SeawaterParameterBlock() m.fs.unit = HeatExchanger( default={ "hot_side_name": "hot", "cold_side_name": "cold", "hot": { "property_package": m.fs.properties }, "cold": { "property_package": m.fs.properties }, "delta_temperature_callback": delta_temperature_chen_callback, "flow_pattern": HeatExchangerFlowPattern.countercurrent, }) # scaling m.fs.properties.set_default_scaling("flow_mass_phase_comp", 1, index=("Liq", "H2O")) m.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "TDS")) iscale.set_scaling_factor(m.fs.unit.hot.heat, 1e-3) iscale.set_scaling_factor(m.fs.unit.cold.heat, 1e-3) iscale.set_scaling_factor(m.fs.unit.overall_heat_transfer_coefficient, 1e-3) iscale.set_scaling_factor(m.fs.unit.area, 1) iscale.calculate_scaling_factors(m) # ---specifications--- # state variables m.fs.unit.hot_inlet.flow_mass_phase_comp[0, "Liq", "H2O"].fix(1) m.fs.unit.hot_inlet.flow_mass_phase_comp[0, "Liq", "TDS"].fix(0.01) m.fs.unit.hot_inlet.temperature[0].fix(350) m.fs.unit.hot_inlet.pressure[0].fix(2e5) m.fs.unit.cold_inlet.flow_mass_phase_comp[0, "Liq", "H2O"].fix(0.5) m.fs.unit.cold_inlet.flow_mass_phase_comp[0, "Liq", "TDS"].fix(0.01) m.fs.unit.cold_inlet.temperature[0].fix(298) m.fs.unit.cold_inlet.pressure[0].fix(2e5) m.fs.unit.area.fix(5) m.fs.unit.overall_heat_transfer_coefficient.fix(1000) # solving assert_units_consistent(m) degrees_of_freedom(m) m.fs.unit.initialize() solver = get_solver() results = solver.solve(m, tee=False) assert_optimal_termination(results) assert pytest.approx(89050.0, rel=1e-4) == value(m.fs.unit.heat_duty[0]) assert pytest.approx(1.0, rel=1e-4) == value( m.fs.unit.hot_outlet.flow_mass_phase_comp[0, "Liq", "H2O"]) assert pytest.approx(0.01, rel=1e-4) == value( m.fs.unit.hot_outlet.flow_mass_phase_comp[0, "Liq", "TDS"]) assert pytest.approx(328.69, rel=1e-4) == value( m.fs.unit.hot_outlet.temperature[0]) assert pytest.approx(2.0e5, rel=1e-4) == value(m.fs.unit.hot_outlet.pressure[0]) assert pytest.approx(0.5, rel=1e-4) == value( m.fs.unit.cold_outlet.flow_mass_phase_comp[0, "Liq", "H2O"]) assert pytest.approx(0.01, rel=1e-4) == value( m.fs.unit.cold_outlet.flow_mass_phase_comp[0, "Liq", "TDS"]) assert pytest.approx(340.78, rel=1e-4) == value( m.fs.unit.cold_outlet.temperature[0]) assert pytest.approx(2.0e5, rel=1e-4) == value(m.fs.unit.cold_outlet.pressure[0]) m.fs.unit.report()
def build(erd_type=None): # flowsheet set up m = ConcreteModel() m.db = Database() m.erd_type = erd_type m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.prop_prtrt = prop_ZO.WaterParameterBlock( default={"solute_list": ["tds", "tss"]} ) density = 1023.5 * pyunits.kg / pyunits.m**3 m.fs.prop_prtrt.dens_mass_default = density m.fs.prop_psttrt = prop_ZO.WaterParameterBlock(default={"solute_list": ["tds"]}) m.fs.prop_desal = prop_SW.SeawaterParameterBlock() # block structure prtrt = m.fs.pretreatment = Block() desal = m.fs.desalination = Block() psttrt = m.fs.posttreatment = Block() # unit models m.fs.feed = FeedZO(default={"property_package": m.fs.prop_prtrt}) # pretreatment prtrt.intake = SWOnshoreIntakeZO(default={"property_package": m.fs.prop_prtrt}) prtrt.ferric_chloride_addition = ChemicalAdditionZO( default={ "property_package": m.fs.prop_prtrt, "database": m.db, "process_subtype": "ferric_chloride", } ) prtrt.chlorination = ChlorinationZO( default={"property_package": m.fs.prop_prtrt, "database": m.db} ) prtrt.static_mixer = StaticMixerZO( default={"property_package": m.fs.prop_prtrt, "database": m.db} ) prtrt.storage_tank_1 = StorageTankZO( default={"property_package": m.fs.prop_prtrt, "database": m.db} ) prtrt.media_filtration = MediaFiltrationZO( default={"property_package": m.fs.prop_prtrt, "database": m.db} ) prtrt.backwash_handling = BackwashSolidsHandlingZO( default={"property_package": m.fs.prop_prtrt, "database": m.db} ) prtrt.anti_scalant_addition = ChemicalAdditionZO( default={ "property_package": m.fs.prop_prtrt, "database": m.db, "process_subtype": "anti-scalant", } ) prtrt.cartridge_filtration = CartridgeFiltrationZO( default={"property_package": m.fs.prop_prtrt, "database": m.db} ) # desalination desal.P1 = Pump(default={"property_package": m.fs.prop_desal}) desal.RO = ReverseOsmosis0D( default={ "property_package": m.fs.prop_desal, "has_pressure_change": True, "pressure_change_type": PressureChangeType.calculated, "mass_transfer_coefficient": MassTransferCoefficient.calculated, "concentration_polarization_type": ConcentrationPolarizationType.calculated, } ) desal.RO.width.setub(5000) desal.RO.area.setub(20000) if erd_type == "pressure_exchanger": desal.S1 = Separator( default={"property_package": m.fs.prop_desal, "outlet_list": ["P1", "PXR"]} ) desal.M1 = Mixer( default={ "property_package": m.fs.prop_desal, "momentum_mixing_type": MomentumMixingType.equality, # booster pump will match pressure "inlet_list": ["P1", "P2"], } ) desal.PXR = PressureExchanger(default={"property_package": m.fs.prop_desal}) desal.P2 = Pump(default={"property_package": m.fs.prop_desal}) elif erd_type == "pump_as_turbine": desal.ERD = EnergyRecoveryDevice(default={"property_package": m.fs.prop_desal}) else: raise ConfigurationError( "erd_type was {}, but can only " "be pressure_exchanger or pump_as_turbine" "".format(erd_type) ) # posttreatment psttrt.storage_tank_2 = StorageTankZO( default={"property_package": m.fs.prop_psttrt, "database": m.db} ) psttrt.uv_aop = UVAOPZO( default={ "property_package": m.fs.prop_psttrt, "database": m.db, "process_subtype": "hydrogen_peroxide", } ) psttrt.co2_addition = CO2AdditionZO( default={"property_package": m.fs.prop_psttrt, "database": m.db} ) psttrt.lime_addition = ChemicalAdditionZO( default={ "property_package": m.fs.prop_psttrt, "database": m.db, "process_subtype": "lime", } ) psttrt.storage_tank_3 = StorageTankZO( default={"property_package": m.fs.prop_psttrt, "database": m.db} ) # product and disposal m.fs.municipal = MunicipalDrinkingZO( default={"property_package": m.fs.prop_psttrt, "database": m.db} ) m.fs.landfill = LandfillZO( default={"property_package": m.fs.prop_prtrt, "database": m.db} ) m.fs.disposal = Product(default={"property_package": m.fs.prop_desal}) # translator blocks m.fs.tb_prtrt_desal = Translator( default={ "inlet_property_package": m.fs.prop_prtrt, "outlet_property_package": m.fs.prop_desal, } ) @m.fs.tb_prtrt_desal.Constraint(["H2O", "tds"]) def eq_flow_mass_comp(blk, j): if j == "tds": jj = "TDS" else: jj = j return ( blk.properties_in[0].flow_mass_comp[j] == blk.properties_out[0].flow_mass_phase_comp["Liq", jj] ) m.fs.tb_desal_psttrt = Translator( default={ "inlet_property_package": m.fs.prop_desal, "outlet_property_package": m.fs.prop_psttrt, } ) @m.fs.tb_desal_psttrt.Constraint(["H2O", "TDS"]) def eq_flow_mass_comp(blk, j): if j == "TDS": jj = "tds" else: jj = j return ( blk.properties_in[0].flow_mass_phase_comp["Liq", j] == blk.properties_out[0].flow_mass_comp[jj] ) # connections m.fs.s_feed = Arc(source=m.fs.feed.outlet, destination=prtrt.intake.inlet) prtrt.s01 = Arc( source=prtrt.intake.outlet, destination=prtrt.ferric_chloride_addition.inlet ) prtrt.s02 = Arc( source=prtrt.ferric_chloride_addition.outlet, destination=prtrt.chlorination.inlet, ) prtrt.s03 = Arc( source=prtrt.chlorination.treated, destination=prtrt.static_mixer.inlet ) prtrt.s04 = Arc( source=prtrt.static_mixer.outlet, destination=prtrt.storage_tank_1.inlet ) prtrt.s05 = Arc( source=prtrt.storage_tank_1.outlet, destination=prtrt.media_filtration.inlet ) prtrt.s06 = Arc( source=prtrt.media_filtration.byproduct, destination=prtrt.backwash_handling.inlet, ) prtrt.s07 = Arc( source=prtrt.media_filtration.treated, destination=prtrt.anti_scalant_addition.inlet, ) prtrt.s08 = Arc( source=prtrt.anti_scalant_addition.outlet, destination=prtrt.cartridge_filtration.inlet, ) m.fs.s_prtrt_tb = Arc( source=prtrt.cartridge_filtration.treated, destination=m.fs.tb_prtrt_desal.inlet ) m.fs.s_landfill = Arc( source=prtrt.backwash_handling.byproduct, destination=m.fs.landfill.inlet ) if erd_type == "pressure_exchanger": m.fs.s_tb_desal = Arc( source=m.fs.tb_prtrt_desal.outlet, destination=desal.S1.inlet ) desal.s01 = Arc(source=desal.S1.P1, destination=desal.P1.inlet) desal.s02 = Arc(source=desal.P1.outlet, destination=desal.M1.P1) desal.s03 = Arc(source=desal.M1.outlet, destination=desal.RO.inlet) desal.s04 = Arc( source=desal.RO.retentate, destination=desal.PXR.high_pressure_inlet ) desal.s05 = Arc(source=desal.S1.PXR, destination=desal.PXR.low_pressure_inlet) desal.s06 = Arc( source=desal.PXR.low_pressure_outlet, destination=desal.P2.inlet ) desal.s07 = Arc(source=desal.P2.outlet, destination=desal.M1.P2) m.fs.s_disposal = Arc( source=desal.PXR.high_pressure_outlet, destination=m.fs.disposal.inlet ) elif erd_type == "pump_as_turbine": m.fs.s_tb_desal = Arc( source=m.fs.tb_prtrt_desal.outlet, destination=desal.P1.inlet ) desal.s01 = Arc(source=desal.P1.outlet, destination=desal.RO.inlet) desal.s02 = Arc(source=desal.RO.retentate, destination=desal.ERD.inlet) m.fs.s_disposal = Arc(source=desal.ERD.outlet, destination=m.fs.disposal.inlet) m.fs.s_desal_tb = Arc( source=desal.RO.permeate, destination=m.fs.tb_desal_psttrt.inlet ) m.fs.s_tb_psttrt = Arc( source=m.fs.tb_desal_psttrt.outlet, destination=psttrt.storage_tank_2.inlet ) psttrt.s01 = Arc( source=psttrt.storage_tank_2.outlet, destination=psttrt.uv_aop.inlet ) psttrt.s02 = Arc( source=psttrt.uv_aop.treated, destination=psttrt.co2_addition.inlet ) psttrt.s03 = Arc( source=psttrt.co2_addition.outlet, destination=psttrt.lime_addition.inlet ) psttrt.s04 = Arc( source=psttrt.lime_addition.outlet, destination=psttrt.storage_tank_3.inlet ) m.fs.s_municipal = Arc( source=psttrt.storage_tank_3.outlet, destination=m.fs.municipal.inlet ) TransformationFactory("network.expand_arcs").apply_to(m) # scaling # set default property values m.fs.prop_desal.set_default_scaling( "flow_mass_phase_comp", 1e-3, index=("Liq", "H2O") ) m.fs.prop_desal.set_default_scaling( "flow_mass_phase_comp", 1e-1, index=("Liq", "TDS") ) # set unit model values iscale.set_scaling_factor(desal.P1.control_volume.work, 1e-5) iscale.set_scaling_factor(desal.RO.area, 1e-4) if erd_type == "pressure_exchanger": iscale.set_scaling_factor(desal.P2.control_volume.work, 1e-5) iscale.set_scaling_factor(desal.PXR.low_pressure_side.work, 1e-5) iscale.set_scaling_factor(desal.PXR.high_pressure_side.work, 1e-5) elif erd_type == "pump_as_turbine": iscale.set_scaling_factor(desal.ERD.control_volume.work, 1e-5) # calculate and propagate scaling factors iscale.calculate_scaling_factors(m) return m