def test_scaling(self, coag_obj): model = coag_obj # Set some scaling factors and look for 'bad' scaling model.fs.properties.set_default_scaling("flow_mass_phase_comp", 1, index=("Liq", "H2O")) model.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "TSS")) model.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "TDS")) model.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e3, index=("Liq", "Sludge")) iscale.calculate_scaling_factors(model.fs) # check that all variables have scaling factors unscaled_var_list = list(iscale.unscaled_variables_generator(model)) assert len(unscaled_var_list) == 0 # check that all constraints have been scaled unscaled_constraint_list = list( iscale.unscaled_constraints_generator(model)) assert len(unscaled_constraint_list) == 0 # check if any variables are badly scaled badly_scaled_var_values = { var.name: val for (var, val) in iscale.badly_scaled_var_generator( model, large=1e2, small=1e-2) } assert not badly_scaled_var_values
def test_full_auto_scaling_mbtype_element(): m = pyo.ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": True, "time_units": pyo.units.s}) m.fs.pp = PhysicalParameterTestBlock() m.fs.rp = ReactionParameterTestBlock(default={"property_package": m.fs.pp}) m.fs.cv = ControlVolume1DBlock( default={ "property_package": m.fs.pp, "reaction_package": m.fs.rp, "transformation_method": "dae.finite_difference", "transformation_scheme": "BACKWARD", "finite_elements": 10 }) m.fs.cv.add_geometry() m.fs.cv.add_state_blocks(has_phase_equilibrium=False) m.fs.cv.add_reaction_blocks(has_equilibrium=False) m.fs.cv.add_total_element_balances(has_mass_transfer=True) m.fs.cv.apply_transformation() m.discretizer = pyo.TransformationFactory('dae.finite_difference') m.discretizer.apply_to(m, nfe=3, wrt=m.fs.time, scheme="BACKWARD") iscale.calculate_scaling_factors(m) # check that all variables have scaling factors unscaled_var_list = list(iscale.unscaled_variables_generator(m)) assert len(unscaled_var_list) == 0 # check that all constraints have been scaled unscaled_constraint_list = list(iscale.unscaled_constraints_generator(m)) assert len(unscaled_constraint_list) == 0
def test_scaling(model3): m = model3 metadata = m.fs.properties.get_metadata().properties for v_name in metadata: getattr(m.fs.stream[0], v_name) calculate_scaling_factors(m) # check that all variables have scaling factors unscaled_var_list = list(unscaled_variables_generator(m)) [print(i) for i in unscaled_var_list] assert len(unscaled_var_list) == 0 # check if any variables are badly scaled badly_scaled_var_list = list(badly_scaled_var_generator(m)) assert len(badly_scaled_var_list) == 0 # check that all constraints have been scaled unscaled_constraint_list = list(unscaled_constraints_generator(m)) [print(i) for i in unscaled_constraint_list] assert len(unscaled_constraint_list) == 0 # m.fs.stream[0].scaling_factor.display() for j in m.fs.properties.config.solute_list: assert get_scaling_factor(m.fs.stream[0].mw_comp[j]) is not None assert (get_scaling_factor(m.fs.stream[0].diffus_phase_comp["Liq", j]) is not None) assert (get_scaling_factor(m.fs.stream[0].act_coeff_phase_comp["Liq", j]) is not None) assert get_scaling_factor( m.fs.stream[0].dens_mass_phase["Liq"]) is not None assert get_scaling_factor(m.fs.stream[0].visc_d_phase["Liq"]) is not None
def test_scaling(self, coag_obj_wo_chems): model = coag_obj_wo_chems # Set some scaling factors and look for 'bad' scaling model.fs.properties.set_default_scaling('flow_mass_phase_comp', 1, index=('Liq', 'H2O')) model.fs.properties.set_default_scaling('flow_mass_phase_comp', 1e2, index=('Liq', 'TSS')) model.fs.properties.set_default_scaling('flow_mass_phase_comp', 1e2, index=('Liq', 'TDS')) model.fs.properties.set_default_scaling('flow_mass_phase_comp', 1e2, index=('Liq', 'Sludge')) #iscale.set_scaling_factor(model.fs.unit.tss_loss_rate, 100) iscale.calculate_scaling_factors(model.fs) # check that all variables have scaling factors unscaled_var_list = list(iscale.unscaled_variables_generator(model)) assert len(unscaled_var_list) == 0 # check if any variables are badly scaled badly_scaled_var_values = { var.name: val for (var, val) in iscale.badly_scaled_var_generator( model, large=1e2, small=1e-2) } print(iscale.get_scaling_factor(model.fs.unit.tss_loss_rate)) assert not badly_scaled_var_values
def test_scaling(self, coag_obj_wo_chems): model = coag_obj_wo_chems # Set some scaling factors and look for 'bad' scaling model.fs.properties.set_default_scaling("flow_mass_phase_comp", 1, index=("Liq", "H2O")) model.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "TSS")) model.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "TDS")) model.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "Sludge")) # Here we are skipping setting scaling factors for performance to test the # effectiveness of the defaults AND get better test coverage iscale.calculate_scaling_factors(model.fs) # check that all variables have scaling factors unscaled_var_list = list(iscale.unscaled_variables_generator(model)) assert len(unscaled_var_list) == 0 # check if any variables are badly scaled badly_scaled_var_values = { var.name: val for (var, val) in iscale.badly_scaled_var_generator( model, large=1e2, small=1e-2) } print(iscale.get_scaling_factor(model.fs.unit.tss_loss_rate)) assert not badly_scaled_var_values
def test_default_scaling(self, coag_obj_fail): model = coag_obj_fail model.fs.stream = model.fs.properties.build_state_block([0], default={}) # call scaling without setting defaults iscale.calculate_scaling_factors(model.fs) # check that all variables have scaling factors unscaled_var_list = list(iscale.unscaled_variables_generator(model)) assert len(unscaled_var_list) == 0 # check that all constraints have been scaled unscaled_constraint_list = list( iscale.unscaled_constraints_generator(model)) assert len(unscaled_constraint_list) == 0 # check if any variables are badly scaled badly_scaled_var_values = { var.name: val for (var, val) in iscale.badly_scaled_var_generator( model, large=1e2, small=1e-2) } assert not badly_scaled_var_values
def test_calculate_scaling(self, unit_frame): m = unit_frame 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', 'Na')) m.fs.properties.set_default_scaling('flow_mass_phase_comp', 1e4, index=('Liq', 'Ca')) m.fs.properties.set_default_scaling('flow_mass_phase_comp', 1e3, index=('Liq', 'Mg')) m.fs.properties.set_default_scaling('flow_mass_phase_comp', 1e3, index=('Liq', 'SO4')) m.fs.properties.set_default_scaling('flow_mass_phase_comp', 1e2, index=('Liq', 'Cl')) calculate_scaling_factors(m) # check that all variables have scaling factors unscaled_var_list = list(unscaled_variables_generator(m)) assert len(unscaled_var_list) == 0 # check that all constraints have been scaled unscaled_constraint_list = list(unscaled_constraints_generator(m)) assert len(unscaled_constraint_list) == 0
def test_calculate_scaling(self, unit_frame): m = unit_frame 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", "Na")) m.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e4, index=("Liq", "Ca")) m.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e3, index=("Liq", "Mg")) m.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e3, index=("Liq", "SO4")) m.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "Cl")) calculate_scaling_factors(m) # check that all variables have scaling factors unscaled_var_list = list(unscaled_variables_generator(m)) assert len(unscaled_var_list) == 0 # check that all constraints have been scaled unscaled_constraint_list = list(unscaled_constraints_generator(m)) assert len(unscaled_constraint_list) == 0
def check_scaling(m, scale_func=None, **kwargs): if scale_func is not None: scale_func(m, **kwargs) calculate_scaling_factors(m) # scale arcs # check all variables have scaling factors unscaled_var_list = list(unscaled_variables_generator(m)) # for v in unscaled_var_list: # print(v.name) assert len(unscaled_var_list) == 0
def test_calculate_scaling(self, NF_frame): m = NF_frame calculate_scaling_factors(m) # check that all variables have scaling factors unscaled_var_list = list(unscaled_variables_generator(m)) assert len(unscaled_var_list) == 0 # check that all constraints have been scaled unscaled_constraint_list = list(unscaled_constraints_generator(m)) assert len(unscaled_constraint_list) == 0
def test_calculate_scaling(self, unit_frame): m = unit_frame calculate_scaling_factors(m) # check that all variables have scaling factors unscaled_var_list = list( unscaled_variables_generator(m.fs.unit, include_fixed=True)) assert len(unscaled_var_list) == 0 # check that all constraints have been scaled unscaled_constraint_list = list(unscaled_constraints_generator(m)) assert len(unscaled_constraint_list) == 0
def test_calculate_scaling(self, RO_frame): m = RO_frame 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', 'NaCl')) calculate_scaling_factors(m) # check that all variables have scaling factors unscaled_var_list = list(unscaled_variables_generator(m)) assert len(unscaled_var_list) == 0 for _ in badly_scaled_var_generator(m): assert False
def test_full_auto_scaling_dynamic(): m = pyo.ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": True, "time_units": pyo.units.s}) m.fs.pp = PhysicalParameterTestBlock() m.fs.rp = ReactionParameterTestBlock(default={"property_package": m.fs.pp}) m.fs.cv = ControlVolume1DBlock( default={ "property_package": m.fs.pp, "reaction_package": m.fs.rp, "transformation_method": "dae.finite_difference", "transformation_scheme": "BACKWARD", "finite_elements": 10 }) m.fs.cv.add_geometry() m.fs.cv.add_state_blocks(has_phase_equilibrium=True) m.fs.cv.add_reaction_blocks(has_equilibrium=True) m.fs.cv.add_material_balances( balance_type=MaterialBalanceType.componentTotal, has_rate_reactions=True, has_equilibrium_reactions=True, has_phase_equilibrium=True, has_mass_transfer=True) m.fs.cv.add_energy_balances(balance_type=EnergyBalanceType.enthalpyTotal, has_heat_of_reaction=True, has_heat_transfer=True, has_work_transfer=True, has_enthalpy_transfer=True) m.fs.cv.add_momentum_balances( balance_type=MomentumBalanceType.pressureTotal, has_pressure_change=True) m.fs.cv.apply_transformation() m.discretizer = pyo.TransformationFactory('dae.finite_difference') m.discretizer.apply_to(m, nfe=3, wrt=m.fs.time, scheme="BACKWARD") iscale.calculate_scaling_factors(m) # check that all variables have scaling factors unscaled_var_list = list(iscale.unscaled_variables_generator(m)) # Unscaled variables are: # rate_reaction_extent (2 reactions, 44 time & space points) # equilibrium_reaction_extent (2 reactions, 44 time & space points) assert len(unscaled_var_list) == 176 # check that all constraints have been scaled unscaled_constraint_list = list(iscale.unscaled_constraints_generator(m)) assert len(unscaled_constraint_list) == 0
def test_scaling(self, coag_obj_w_chems): model = coag_obj_w_chems # Set some scaling factors and look for 'bad' scaling model.fs.properties.set_default_scaling("flow_mass_phase_comp", 1, index=("Liq", "H2O")) model.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "TSS")) model.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "TDS")) model.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e2, index=("Liq", "Sludge")) # set scaling factors for performance iscale.set_scaling_factor(model.fs.unit.rapid_mixing_retention_time, 1e-1) iscale.set_scaling_factor(model.fs.unit.num_rapid_mixing_basins, 1) iscale.set_scaling_factor(model.fs.unit.rapid_mixing_vel_grad, 1e-2) iscale.set_scaling_factor(model.fs.unit.floc_retention_time, 1e-3) iscale.set_scaling_factor(model.fs.unit.single_paddle_length, 1) iscale.set_scaling_factor(model.fs.unit.single_paddle_width, 1) iscale.set_scaling_factor(model.fs.unit.paddle_rotational_speed, 10) iscale.set_scaling_factor(model.fs.unit.paddle_drag_coef, 1) iscale.set_scaling_factor(model.fs.unit.vel_fraction, 1) iscale.set_scaling_factor(model.fs.unit.num_paddle_wheels, 1) iscale.set_scaling_factor(model.fs.unit.num_paddles_per_wheel, 1) iscale.calculate_scaling_factors(model.fs) # check that all variables have scaling factors unscaled_var_list = list(iscale.unscaled_variables_generator(model)) assert len(unscaled_var_list) == 0 # check if any variables are badly scaled badly_scaled_var_values = { var.name: val for (var, val) in iscale.badly_scaled_var_generator( model, large=1e2, small=1e-2) } assert not badly_scaled_var_values
def test_scaling(self, frame): m = frame set_scaling_factor(m.fs.stream[0].flow_mass_phase_comp['Liq', 'H2O'], 1) set_scaling_factor(m.fs.stream[0].flow_mass_phase_comp['Liq', 'TDS'], 1e2) calculate_scaling_factors(m.fs) # check that all variables have scaling factors unscaled_var_list = list(unscaled_variables_generator(m)) assert len(unscaled_var_list) == 0 # check that all constraints have been scaled unscaled_constraint_list = list(unscaled_constraints_generator(m)) assert len(unscaled_constraint_list) == 0 # check if any variables are badly scaled badly_scaled_var_list = list(badly_scaled_var_generator(m)) assert len(badly_scaled_var_list) == 0
def test_calculate_scaling(self, NF_frame): m = NF_frame m.fs.properties.set_default_scaling("flow_mol_phase_comp", 1e5, index=("Liq", "Ca_2+")) m.fs.properties.set_default_scaling("flow_mol_phase_comp", 1e5, index=("Liq", "SO4_2-")) calculate_scaling_factors(m) # check that all variables have scaling factors unscaled_var_list = list(unscaled_variables_generator(m.fs.unit)) assert len(unscaled_var_list) == 0 badly_scaled_var_lst = list( badly_scaled_var_generator(m, include_fixed=True)) assert len(unscaled_var_list) == 0
def test_full_auto_scaling(): m = pyo.ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.pp = PhysicalParameterTestBlock() m.fs.rp = ReactionParameterTestBlock(default={"property_package": m.fs.pp}) m.fs.cv = ControlVolume0DBlock(default={ "property_package": m.fs.pp, "reaction_package": m.fs.rp}) m.fs.cv.add_geometry() m.fs.cv.add_state_blocks(has_phase_equilibrium=True) m.fs.cv.add_reaction_blocks(has_equilibrium=True) m.fs.cv.add_material_balances( balance_type=MaterialBalanceType.componentTotal, has_rate_reactions=True, has_equilibrium_reactions=True, has_phase_equilibrium=True, has_mass_transfer=True) m.fs.cv.add_energy_balances( balance_type=EnergyBalanceType.enthalpyTotal, has_heat_of_reaction=True, has_heat_transfer=True, has_work_transfer=True, has_enthalpy_transfer=True) m.fs.cv.add_momentum_balances( balance_type=MomentumBalanceType.pressureTotal, has_pressure_change=True) iscale.calculate_scaling_factors(m) # check that all variables have scaling factors unscaled_var_list = list(iscale.unscaled_variables_generator(m)) # Unscaled variables are: # rate_reaction_extent (2 reactions) # equilibrium_reaction_extent (2 reactions) assert len(unscaled_var_list) == 4 # check that all constraints have been scaled unscaled_constraint_list = list(iscale.unscaled_constraints_generator(m)) assert len(unscaled_constraint_list) == 0
def test_calculate_scaling(self, Pump_frame): m = Pump_frame 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')) calculate_scaling_factors(m) if get_scaling_factor( m.fs.unit.ratioP ) is None: # if IDAES hasn't specified a scaling factor set_scaling_factor(m.fs.unit.ratioP, 1) # check that all variables have scaling factors unscaled_var_list = list(unscaled_variables_generator(m)) assert len(unscaled_var_list) == 0 # check that all constraints have been scaled unscaled_constraint_list = list(unscaled_constraints_generator(m)) assert len(unscaled_constraint_list) == 0
def test_scaling(self, frame_stateblock): m = frame_stateblock calculate_scaling_factors(m.fs.stream[0]) # check that all variables have scaling factors unscaled_var_list = list(unscaled_variables_generator(m.fs.stream[0])) if len(unscaled_var_list) != 0: unscaled_var_name_list = [v.name for v in unscaled_var_list] raise PropertyAttributeError( "The following variable(s) are unscaled: {lst}".format( lst=unscaled_var_name_list)) # check that all constraints have been scaled unscaled_constraint_list = list( unscaled_constraints_generator(m.fs.stream[0])) if len(unscaled_constraint_list) != 0: unscaled_constraint_name_list = [ c.name for c in unscaled_constraint_list ] raise PropertyAttributeError( "The following constraint(s) are unscaled: {lst}".format( lst=unscaled_constraint_name_list))
def test_calculate_scaling(self, Crystallizer_frame): m = Crystallizer_frame m.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e-1, index=("Liq", "H2O")) m.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e-1, index=("Liq", "NaCl")) m.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e-1, index=("Vap", "H2O")) m.fs.properties.set_default_scaling("flow_mass_phase_comp", 1e-1, index=("Sol", "NaCl")) calculate_scaling_factors(m) # check that all variables have scaling factors unscaled_var_list = list(unscaled_variables_generator(m)) assert len(unscaled_var_list) == 0 for _ in badly_scaled_var_generator(m): assert False
def test_find_unscaled_vars_and_constraints(): m = pyo.ConcreteModel() m.b = pyo.Block() m.x = pyo.Var(initialize=1e6) m.y = pyo.Var(initialize=1e-8) m.z = pyo.Var(initialize=1e-20) m.c1 = pyo.Constraint(expr=m.x == 0) m.c2 = pyo.Constraint(expr=m.y == 0) m.b.w = pyo.Var([1, 2, 3], initialize=1e10) m.b.c1 = pyo.Constraint(expr=m.b.w[1] == 0) m.b.c2 = pyo.Constraint(expr=m.b.w[2] == 0) m.c3 = pyo.Constraint(expr=m.z == 0) sc.set_scaling_factor(m.x, 1) sc.set_scaling_factor(m.b.w[1], 2) sc.set_scaling_factor(m.c1, 1) sc.set_scaling_factor(m.b.c1, 1) sc.constraint_scaling_transform(m.c3, 1) a = [id(v) for v in sc.unscaled_variables_generator(m)] # Make sure we pick up the right variales assert id(m.x) not in a assert id(m.y) in a assert id(m.z) in a assert id(m.b.w[1]) not in a assert id(m.b.w[2]) in a assert id(m.b.w[3]) in a assert len(a) == 4 #make sure we didn't pick up any other random stuff a = [id(v) for v in sc.unscaled_constraints_generator(m)] assert id(m.c1) not in a assert id(m.b.c1) not in a assert id(m.c2) in a assert id(m.b.c2) in a assert id(m.c3) not in a assert len(a) == 2 #make sure we didn't pick up any other random stuff
def test_Pdrop_calculation(self): """ Testing 0D-RO with PressureChangeType.calculated option. """ m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = props.NaClParameterBlock() m.fs.unit = ReverseOsmosis0D( default={ "property_package": m.fs.properties, "has_pressure_change": True, "concentration_polarization_type": ConcentrationPolarizationType.calculated, "mass_transfer_coefficient": MassTransferCoefficient.calculated, "pressure_change_type": PressureChangeType.calculated }) # fully specify system feed_flow_mass = 1 feed_mass_frac_NaCl = 0.035 feed_mass_frac_H2O = 1 - feed_mass_frac_NaCl feed_pressure = 50e5 feed_temperature = 273.15 + 25 membrane_area = 50 length = 20 A = 4.2e-12 B = 3.5e-8 pressure_atmospheric = 101325 m.fs.unit.inlet.flow_mass_phase_comp[0, 'Liq', 'NaCl'].fix( feed_flow_mass * feed_mass_frac_NaCl) 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) m.fs.unit.inlet.temperature[0].fix(feed_temperature) m.fs.unit.area.fix(membrane_area) m.fs.unit.A_comp.fix(A) m.fs.unit.B_comp.fix(B) m.fs.unit.permeate.pressure[0].fix(pressure_atmospheric) m.fs.unit.channel_height.fix(0.002) m.fs.unit.spacer_porosity.fix(0.75) m.fs.unit.length.fix(length) # test statistics assert number_variables(m) == 115 assert number_total_constraints(m) == 86 assert number_unused_variables( m) == 0 # vars from property package parameters # test degrees of freedom assert degrees_of_freedom(m) == 0 # test 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', 'NaCl')) calculate_scaling_factors(m) # check that all variables have scaling factors. # TODO: see aforementioned TODO on revisiting scaling and associated testing for property models. unscaled_var_list = list( unscaled_variables_generator(m.fs.unit, include_fixed=True)) assert len(unscaled_var_list) == 0 # check that all constraints have been scaled unscaled_constraint_list = list(unscaled_constraints_generator(m)) assert len(unscaled_constraint_list) == 0 # test initialization initialization_tester(m) # test variable scaling badly_scaled_var_lst = list(badly_scaled_var_generator(m)) assert badly_scaled_var_lst == [] # test solve solver.options = {'nlp_scaling_method': 'user-scaling'} results = solver.solve(m, tee=True) # Check for optimal solution assert results.solver.termination_condition == \ TerminationCondition.optimal assert results.solver.status == SolverStatus.ok # test solution assert (pytest.approx(-9.173e5, rel=1e-3) == value(m.fs.unit.deltaP[0])) assert (pytest.approx(1.904e-3, rel=1e-3) == value( m.fs.unit.flux_mass_phase_comp_avg[0, 'Liq', 'H2O'])) assert (pytest.approx(1.727e-6, rel=1e-3) == value( m.fs.unit.flux_mass_phase_comp_avg[0, 'Liq', 'NaCl'])) assert (pytest.approx(0.0952, rel=1e-3) == value( m.fs.unit.properties_permeate[0].flow_mass_phase_comp['Liq', 'H2O'])) assert (pytest.approx(8.637e-5, rel=1e-3) == value( m.fs.unit.properties_permeate[0].flow_mass_phase_comp['Liq', 'NaCl'])) assert (pytest.approx(35.751, rel=1e-3) == value( m.fs.unit.feed_side.properties_in[0].conc_mass_phase_comp['Liq', 'NaCl'])) assert (pytest.approx(53.561, rel=1e-3) == value( m.fs.unit.feed_side.properties_interface_in[0]. conc_mass_phase_comp['Liq', 'NaCl'])) assert (pytest.approx(39.524, rel=1e-3) == value( m.fs.unit.feed_side.properties_out[0].conc_mass_phase_comp['Liq', 'NaCl']) ) assert (pytest.approx( 46.958, rel=1e-3 ) == # TODO: expected this value to be higher than interface concentration at inlet, but bypassing for now- has to do with pressure drop value(m.fs.unit.feed_side.properties_interface_out[0]. conc_mass_phase_comp['Liq', 'NaCl']))
def test_CP_calculation_with_kf_fixed(self): """ Testing 0D-RO with ConcentrationPolarizationType.calculated option enabled. This option makes use of an alternative constraint for the feed-side, membrane-interface concentration. Additionally, two more variables are created when this option is enabled: Kf - feed-channel mass transfer coefficients at the channel inlet and outlet. """ m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = props.NaClParameterBlock() m.fs.unit = ReverseOsmosis0D(default={ "property_package": m.fs.properties, "has_pressure_change": True, "concentration_polarization_type": ConcentrationPolarizationType.calculated, "mass_transfer_coefficient": MassTransferCoefficient.fixed}) # fully specify system feed_flow_mass = 1 feed_mass_frac_NaCl = 0.035 feed_pressure = 50e5 feed_temperature = 273.15 + 25 membrane_pressure_drop = 3e5 membrane_area = 50 A = 4.2e-12 B = 3.5e-8 pressure_atmospheric = 101325 kf = 2e-5 feed_mass_frac_H2O = 1 - feed_mass_frac_NaCl m.fs.unit.inlet.flow_mass_phase_comp[0, 'Liq', 'NaCl'].fix( feed_flow_mass * feed_mass_frac_NaCl) 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) m.fs.unit.inlet.temperature[0].fix(feed_temperature) m.fs.unit.deltaP.fix(-membrane_pressure_drop) m.fs.unit.area.fix(membrane_area) m.fs.unit.A_comp.fix(A) m.fs.unit.B_comp.fix(B) m.fs.unit.permeate.pressure[0].fix(pressure_atmospheric) m.fs.unit.Kf[0, 0., 'NaCl'].fix(kf) m.fs.unit.Kf[0, 1., 'NaCl'].fix(kf) # test statistics assert number_variables(m) == 125 assert number_total_constraints(m) == 96 assert number_unused_variables(m) == 7 # vars from property package parameters # test degrees of freedom assert degrees_of_freedom(m) == 0 # test 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', 'NaCl')) calculate_scaling_factors(m) # check that all variables have scaling factors. # TODO: Setting the "include_fixed" arg as True reveals # unscaled vars that weren't being accounted for previously. However, calling the whole block (i.e., # m) shows that several NaCl property parameters are unscaled. For now, we are just interested in ensuring # unit variables are scaled (hence, calling m.fs.unit) but might need to revisit scaling and associated # testing for property models. unscaled_var_list = list(unscaled_variables_generator(m.fs.unit, include_fixed=True)) assert len(unscaled_var_list) == 0 # # test initialization initialization_tester(m, fail_on_warning=True) # test variable scaling badly_scaled_var_lst = list(badly_scaled_var_generator(m)) assert badly_scaled_var_lst == [] # test solve results = solver.solve(m) # Check for optimal solution assert_optimal_termination(results) # test solution assert (pytest.approx(3.815e-3, rel=1e-3) == value(m.fs.unit.flux_mass_phase_comp_avg[0, 'Liq', 'H2O'])) assert (pytest.approx(1.668e-6, rel=1e-3) == value(m.fs.unit.flux_mass_phase_comp_avg[0, 'Liq', 'NaCl'])) assert (pytest.approx(0.1908, rel=1e-3) == value(m.fs.unit.mixed_permeate[0].flow_mass_phase_comp['Liq', 'H2O'])) assert (pytest.approx(8.337e-5, rel=1e-3) == value(m.fs.unit.mixed_permeate[0].flow_mass_phase_comp['Liq', 'NaCl'])) assert (pytest.approx(46.07, rel=1e-3) == value(m.fs.unit.feed_side.properties_interface[0, 0.].conc_mass_phase_comp['Liq', 'NaCl'])) assert (pytest.approx(44.34, rel=1e-3) == value(m.fs.unit.feed_side.properties_out[0].conc_mass_phase_comp['Liq', 'NaCl'])) assert (pytest.approx(50.20, rel=1e-3) == value(m.fs.unit.feed_side.properties_interface[0, 1.].conc_mass_phase_comp['Liq', 'NaCl']))
def test_Pdrop_fixed_per_unit_length(self): """ Testing 0D-RO with PressureChangeType.fixed_per_unit_length option. """ m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = props.NaClParameterBlock() m.fs.unit = ReverseOsmosis0D(default={ "property_package": m.fs.properties, "has_pressure_change": True, "concentration_polarization_type": ConcentrationPolarizationType.calculated, "mass_transfer_coefficient": MassTransferCoefficient.calculated, "pressure_change_type": PressureChangeType.fixed_per_unit_length}) # fully specify system feed_flow_mass = 1 feed_mass_frac_NaCl = 0.035 feed_mass_frac_H2O = 1 - feed_mass_frac_NaCl feed_pressure = 50e5 feed_temperature = 273.15 + 25 membrane_area = 50 length = 20 A = 4.2e-12 B = 3.5e-8 pressure_atmospheric = 101325 membrane_pressure_drop = 3e5 m.fs.unit.inlet.flow_mass_phase_comp[0, 'Liq', 'NaCl'].fix( feed_flow_mass * feed_mass_frac_NaCl) 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) m.fs.unit.inlet.temperature[0].fix(feed_temperature) m.fs.unit.area.fix(membrane_area) m.fs.unit.A_comp.fix(A) m.fs.unit.B_comp.fix(B) m.fs.unit.permeate.pressure[0].fix(pressure_atmospheric) m.fs.unit.channel_height.fix(0.002) m.fs.unit.spacer_porosity.fix(0.75) m.fs.unit.length.fix(length) m.fs.unit.dP_dx.fix(-membrane_pressure_drop / length) # test statistics assert number_variables(m) == 142 assert number_total_constraints(m) == 112 assert number_unused_variables(m) == 0 # test degrees of freedom assert degrees_of_freedom(m) == 0 # test 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', 'NaCl')) calculate_scaling_factors(m) # check that all variables have scaling factors. # TODO: see aforementioned TODO on revisiting scaling and associated testing for property models. unscaled_var_list = list(unscaled_variables_generator(m.fs.unit, include_fixed=True)) assert len(unscaled_var_list) == 0 # test initialization initialization_tester(m, fail_on_warning=True) # test variable scaling badly_scaled_var_lst = list(badly_scaled_var_generator(m)) assert badly_scaled_var_lst == [] # test solve results = solver.solve(m, tee=True) # Check for optimal solution assert_optimal_termination(results) # test solution assert (pytest.approx(-3.000e5, rel=1e-3) == value(m.fs.unit.deltaP[0])) assert (pytest.approx(4.562e-3, rel=1e-3) == value(m.fs.unit.flux_mass_phase_comp_avg[0, 'Liq', 'H2O'])) assert (pytest.approx(1.593e-6, rel=1e-3) == value(m.fs.unit.flux_mass_phase_comp_avg[0, 'Liq', 'NaCl'])) assert (pytest.approx(0.2281, rel=1e-3) == value(m.fs.unit.mixed_permeate[0].flow_mass_phase_comp['Liq', 'H2O'])) assert (pytest.approx(7.963e-5, rel=1e-3) == value(m.fs.unit.mixed_permeate[0].flow_mass_phase_comp['Liq', 'NaCl'])) assert (pytest.approx(41.96, rel=1e-3) == value(m.fs.unit.feed_side.properties_interface[0,0.].conc_mass_phase_comp['Liq', 'NaCl'])) assert (pytest.approx(46.57, rel=1e-3) == value(m.fs.unit.feed_side.properties_out[0].conc_mass_phase_comp['Liq', 'NaCl'])) assert (pytest.approx(49.94, rel=1e-3) == value(m.fs.unit.feed_side.properties_interface[0, 1.].conc_mass_phase_comp['Liq', 'NaCl']))
def test_Pdrop_calculation(self): """Testing 0D-RO with PressureChangeType.calculated option.""" m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = props.NaClParameterBlock() m.fs.unit = ReverseOsmosis0D( default={ "property_package": m.fs.properties, "has_pressure_change": True, "concentration_polarization_type": ConcentrationPolarizationType.calculated, "mass_transfer_coefficient": MassTransferCoefficient.calculated, "pressure_change_type": PressureChangeType.calculated, }) # fully specify system feed_flow_mass = 1 / 3.6 feed_mass_frac_NaCl = 0.035 feed_mass_frac_H2O = 1 - feed_mass_frac_NaCl feed_pressure = 70e5 feed_temperature = 273.15 + 25 membrane_area = 19 A = 4.2e-12 B = 3.5e-8 pressure_atmospheric = 101325 m.fs.unit.inlet.flow_mass_phase_comp[0, "Liq", "NaCl"].fix( feed_flow_mass * feed_mass_frac_NaCl) 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) m.fs.unit.inlet.temperature[0].fix(feed_temperature) m.fs.unit.area.fix(membrane_area) m.fs.unit.A_comp.fix(A) m.fs.unit.B_comp.fix(B) m.fs.unit.permeate.pressure[0].fix(pressure_atmospheric) m.fs.unit.channel_height.fix(0.001) m.fs.unit.spacer_porosity.fix(0.97) m.fs.unit.length.fix(16) # test statistics assert number_variables(m) == 147 assert number_total_constraints(m) == 118 assert number_unused_variables( m) == 0 # vars from property package parameters # test degrees of freedom assert degrees_of_freedom(m) == 0 # test 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", "NaCl")) calculate_scaling_factors(m) # check that all variables have scaling factors. # TODO: see aforementioned TODO on revisiting scaling and associated testing for property models. unscaled_var_list = list( unscaled_variables_generator(m.fs.unit, include_fixed=True)) assert len(unscaled_var_list) == 0 # test initialization initialization_tester(m, fail_on_warning=True) # test variable scaling badly_scaled_var_lst = list(badly_scaled_var_generator(m)) assert badly_scaled_var_lst == [] # test solve results = solver.solve(m, tee=True) # Check for optimal solution assert_optimal_termination(results) # test solution assert pytest.approx(-1.661e5, rel=1e-3) == value(m.fs.unit.deltaP[0]) assert pytest.approx(-1.038e4, rel=1e-3) == value(m.fs.unit.deltaP[0] / m.fs.unit.length) assert pytest.approx(395.8, rel=1e-3) == value(m.fs.unit.N_Re[0, 0.0]) assert pytest.approx(0.2361, rel=1e-3) == value(m.fs.unit.velocity[0, 0.0]) assert pytest.approx(191.1, rel=1e-3) == value(m.fs.unit.N_Re[0, 1.0]) assert pytest.approx(0.1187, rel=1e-3) == value(m.fs.unit.velocity[0, 1.0]) assert pytest.approx(7.089e-3, rel=1e-3) == value( m.fs.unit.flux_mass_phase_comp_avg[0, "Liq", "H2O"]) assert pytest.approx(2.188e-6, rel=1e-3) == value( m.fs.unit.flux_mass_phase_comp_avg[0, "Liq", "NaCl"]) assert pytest.approx(0.1347, rel=1e-3) == value( m.fs.unit.mixed_permeate[0].flow_mass_phase_comp["Liq", "H2O"]) assert pytest.approx(4.157e-5, rel=1e-3) == value( m.fs.unit.mixed_permeate[0].flow_mass_phase_comp["Liq", "NaCl"]) assert pytest.approx(50.08, rel=1e-3) == value( m.fs.unit.feed_side.properties_interface[ 0, 0.0].conc_mass_phase_comp["Liq", "NaCl"]) assert pytest.approx(70.80, rel=1e-3) == value( m.fs.unit.feed_side.properties_out[0].conc_mass_phase_comp["Liq", "NaCl"]) assert pytest.approx(76.32, rel=1e-3) == value( m.fs.unit.feed_side.properties_interface[ 0, 1.0].conc_mass_phase_comp["Liq", "NaCl"])