def test_find_badly_scaled_vars(): m = pyo.ConcreteModel() m.x = pyo.Var(initialize=1e6) m.y = pyo.Var(initialize=1e-8) m.z = pyo.Var(initialize=1e-20) m.b = pyo.Block() m.b.w = pyo.Var(initialize=1e10) a = [id(v) for v, sv in sc.badly_scaled_var_generator(m)] assert id(m.x) in a assert id(m.y) in a assert id(m.b.w) in a assert id(m.z) not in a m.scaling_factor = pyo.Suffix(direction=pyo.Suffix.EXPORT) m.b.scaling_factor = pyo.Suffix(direction=pyo.Suffix.EXPORT) m.scaling_factor[m.x] = 1e-6 m.scaling_factor[m.y] = 1e6 m.scaling_factor[m.z] = 1 m.b.scaling_factor[m.b.w] = 1e-5 a = [id(v) for v, sv in sc.badly_scaled_var_generator(m)] assert id(m.x) not in a assert id(m.y) not in a assert id(m.b.w) in a assert id(m.z) not in a
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_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_equilibrium(self, equilibrium_config): model = equilibrium_config # Call scaling factor helper functions _set_equ_rxn_scaling(model.fs.unit, reaction_config) _set_mat_bal_scaling_FpcTP(model.fs.unit) _set_ene_bal_scaling(model.fs.unit) iscale.calculate_scaling_factors(model.fs.unit) assert isinstance(model.fs.unit.control_volume.scaling_factor, Suffix) assert isinstance( model.fs.unit.control_volume.properties_out[0.0].scaling_factor, Suffix) assert isinstance( model.fs.unit.control_volume.properties_in[0.0].scaling_factor, Suffix) # When using equilibrium reactions, there are another set of scaling factors calculated assert isinstance( model.fs.unit.control_volume.reactions[0.0].scaling_factor, Suffix) # 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=1e4, small=1e-2) } 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')) #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): 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_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_state(self): self.configure_class() # create model m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = self.prop_pack() m.fs.stream = m.fs.properties.build_state_block( [0], default=self.param_args) # set default scaling for (v_str, ind), sf in self.scaling_args.items(): m.fs.properties.set_default_scaling(v_str, sf, index=ind) # touch all properties in var_args for (v_name, ind), val in self.var_args.items(): getattr(m.fs.stream[0], v_name) # scale model calculate_scaling_factors(m) # calculate state results = m.fs.stream.calculate_state(var_args=self.var_args, solver=self.solver, optarg=self.optarg) assert_optimal_termination(results) # check results for (v_name, ind), val in self.state_solution.items(): var = getattr(m.fs.stream[0], v_name)[ind] # relative tolerance doesn't mean anything for 0-valued things if val == 0: if not pytest.approx(val, abs=1.0e-08) == value(var): raise PropertyValueError( "Variable {v_name} with index {ind} is expected to have a value of {val} +/- 1.0e-08, but it " "has a value of {val_t}. \nUpdate state_solution in the configure function " "that sets up the PropertyCalculateStateTest".format( v_name=v_name, ind=ind, val=val, val_t=value(var))) elif not pytest.approx(val, rel=1e-3) == value(var): raise PropertyValueError( "Variable {v_name} with index {ind} is expected to have a value of {val} +/- 0.1%, but it " "has a value of {val_t}. \nUpdate state_solution in the configure function " "that sets up the PropertyCalculateStateTest".format( v_name=v_name, ind=ind, val=val, val_t=value(var))) # check if any variables are badly scaled lst = [] for (var, val) in badly_scaled_var_generator(m, large=1e2, small=1e-2, zero=1e-8): lst.append((var.name, val)) print(var.name, var.value) if lst: raise PropertyValueError( "The following variable(s) are poorly scaled: {lst}".format( lst=lst))
def test_solve(self, electrodialysis_cell3): m = electrodialysis_cell3 # run solver and check for optimal solution results = solver.solve(m) assert_optimal_termination(results) badly_scaled_var_values = { var.name: val for (var, val) in iscale.badly_scaled_var_generator(m) } assert not badly_scaled_var_values
def test_badly_scaled(self, frame_stateblock): m = frame_stateblock badly_scaled_var_list = list( badly_scaled_var_generator(m, large=1e2, small=1e-2, zero=1e-8)) if len(badly_scaled_var_list) != 0: lst = [] for (var, val) in badly_scaled_var_list: lst.append((var.name, val)) raise PropertyValueError( "The following variable(s) are poorly scaled: {lst}".format( lst=lst))
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_solve(self, coag_obj_wo_chems): model = coag_obj_wo_chems # first, check to make sure that after initialized, the scaling is still good 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 # run solver and check for optimal solution results = solver.solve(model) assert_optimal_termination(results)
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_initialization_scaling(self, electrodialysis_cell2): m = electrodialysis_cell2 # set default scaling for state vars m.fs.properties.set_default_scaling("flow_mol_phase_comp", 1e2, index=("Liq", "H2O")) m.fs.properties.set_default_scaling("flow_mol_phase_comp", 1e4, index=("Liq", "Na_+")) m.fs.properties.set_default_scaling("flow_mol_phase_comp", 1e4, index=("Liq", "Cl_-")) iscale.calculate_scaling_factors(m.fs) initialization_tester(m) badly_scaled_var_values = { var.name: val for (var, val) in iscale.badly_scaled_var_generator(m) } assert not badly_scaled_var_values # check to make sure DOF does not change assert degrees_of_freedom(m) == 0
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_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_seawater_data(): m = ConcreteModel() m.fs = FlowsheetBlock(default={'dynamic': False}) m.fs.properties = DSPMDEParameterBlock( default={ "solute_list": ["Ca_2+", "SO4_2-", "Na_+", "Cl_-", "Mg_2+"], "diffusivity_data": { ("Liq", "Ca_2+"): 0.792e-9, ("Liq", "SO4_2-"): 1.06e-9, ("Liq", "Na_+"): 1.33e-9, ("Liq", "Cl_-"): 2.03e-9, ("Liq", "Mg_2+"): 0.706e-9 }, "mw_data": { "H2O": 18e-3, "Na_+": 23e-3, "Ca_2+": 40e-3, "Mg_2+": 24e-3, "Cl_-": 35e-3, "SO4_2-": 96e-3 }, "stokes_radius_data": { "Na_+": 0.184e-9, "Ca_2+": 0.309e-9, "Mg_2+": 0.347e-9, "Cl_-": 0.121e-9, "SO4_2-": 0.230e-9 }, "charge": { "Na_+": 1, "Ca_2+": 2, "Mg_2+": 2, "Cl_-": -1, "SO4_2-": -2 }, }) m.fs.stream = stream = m.fs.properties.build_state_block( [0], default={'defined_state': True}) mass_flow_in = 1 * pyunits.kg / pyunits.s feed_mass_frac = { 'Na_+': 11122e-6, 'Ca_2+': 382e-6, 'Mg_2+': 1394e-6, 'SO4_2-': 2136e-6, 'Cl_-': 20300e-6 } for ion, x in feed_mass_frac.items(): mol_comp_flow = x * pyunits.kg / pyunits.kg * mass_flow_in / stream[ 0].mw_comp[ion] stream[0].flow_mol_phase_comp['Liq', ion].fix(mol_comp_flow) H2O_mass_frac = 1 - sum(x for x in feed_mass_frac.values()) H2O_mol_comp_flow = H2O_mass_frac * pyunits.kg / pyunits.kg * mass_flow_in / stream[ 0].mw_comp['H2O'] stream[0].flow_mol_phase_comp['Liq', 'H2O'].fix(H2O_mol_comp_flow) stream[0].temperature.fix(298.15) stream[0].pressure.fix(101325) stream[0].assert_electroneutrality(tol=1e-2) metadata = m.fs.properties.get_metadata().properties for v_name in metadata: getattr(stream[0], v_name) assert stream[0].is_property_constructed('conc_mol_phase_comp') assert_units_consistent(m) check_dof(m, fail_flag=True) m.fs.properties.set_default_scaling('flow_mol_phase_comp', 1, index=('Liq', 'H2O')) m.fs.properties.set_default_scaling('flow_mol_phase_comp', 1, index=('Liq', 'Na_+')) m.fs.properties.set_default_scaling('flow_mol_phase_comp', 1, index=('Liq', 'Cl_-')) m.fs.properties.set_default_scaling('flow_mol_phase_comp', 1e1, index=('Liq', 'Ca_2+')) m.fs.properties.set_default_scaling('flow_mol_phase_comp', 1e1, index=('Liq', 'SO4_2-')) m.fs.properties.set_default_scaling('flow_mol_phase_comp', 1, index=('Liq', 'Mg_2+')) calculate_scaling_factors(m) # check if any variables are badly scaled badly_scaled_var_list = list(badly_scaled_var_generator(m)) assert len(badly_scaled_var_list) == 0 stream.initialize() # check if any variables are badly scaled badly_scaled_var_list = list(badly_scaled_var_generator(m)) assert len(badly_scaled_var_list) == 0 results = solver.solve(m) assert_optimal_termination(results) assert value(stream[0].flow_vol_phase['Liq']) == pytest.approx(0.001, rel=1e-3) assert value(stream[0].flow_mol_phase_comp['Liq', 'H2O']) == pytest.approx( 53.59256, rel=1e-3) assert value(stream[0].flow_mol_phase_comp['Liq', 'Na_+']) == pytest.approx( 0.4836, rel=1e-3) assert value(stream[0].flow_mol_phase_comp['Liq', 'Ca_2+']) == pytest.approx( 0.00955, rel=1e-3) assert value(stream[0].flow_mol_phase_comp['Liq', 'Mg_2+']) == pytest.approx( 0.05808, rel=1e-3) assert value(stream[0].flow_mol_phase_comp['Liq', 'Cl_-']) == pytest.approx( 0.58, rel=1e-3) assert value(stream[0].flow_mol_phase_comp['Liq', 'SO4_2-']) == pytest.approx( 0.02225, rel=1e-3) assert value(stream[0].dens_mass_phase['Liq']) == pytest.approx(1000, rel=1e-3) assert value(stream[0].pressure_osm) == pytest.approx(28.593e5, rel=1e-3) assert value(stream[0].flow_vol) == pytest.approx(0.001, rel=1e-3) assert value( sum(stream[0].conc_mass_phase_comp['Liq', j] for j in m.fs.properties.solute_set)) == pytest.approx(35.334, rel=1e-3) assert value( sum(stream[0].mass_frac_phase_comp['Liq', j] for j in m.fs.properties.solute_set)) == pytest.approx(35334e-6, rel=1e-3) assert value( sum(stream[0].mass_frac_phase_comp['Liq', j] for j in m.fs.properties.component_list)) == pytest.approx( 1, rel=1e-3) assert value( sum(stream[0].mole_frac_phase_comp['Liq', j] for j in m.fs.properties.component_list)) == pytest.approx( 1, rel=1e-3) assert value(stream[0].conc_mol_phase_comp['Liq', 'Na_+']) == pytest.approx( 483.565, rel=1e-3) assert value(stream[0].conc_mol_phase_comp['Liq', 'Cl_-']) == pytest.approx( 580, rel=1e-3) assert value(stream[0].conc_mol_phase_comp['Liq', 'Ca_2+']) == pytest.approx( 9.55, rel=1e-3) assert value(stream[0].conc_mol_phase_comp['Liq', 'SO4_2-']) == pytest.approx( 22.25, rel=1e-3) assert value(stream[0].conc_mol_phase_comp['Liq', 'Mg_2+']) == pytest.approx( 58.08, rel=1e-3) assert value(stream[0].conc_mass_phase_comp['Liq', 'Na_+']) == pytest.approx( 11.122, rel=1e-3) assert value(stream[0].conc_mass_phase_comp['Liq', 'Cl_-']) == pytest.approx( 20.3, rel=1e-3) assert value(stream[0].conc_mass_phase_comp['Liq', 'Ca_2+']) == pytest.approx( 0.382, rel=1e-3) assert value(stream[0].conc_mass_phase_comp['Liq', 'SO4_2-']) == pytest.approx( 2.136, rel=1e-3) assert value(stream[0].conc_mass_phase_comp['Liq', 'Mg_2+']) == pytest.approx( 1.394, rel=1e-3) assert value(stream[0].mole_frac_phase_comp['Liq', 'Na_+']) == pytest.approx( 8.833e-3, rel=1e-3) assert value(stream[0].mole_frac_phase_comp['Liq', 'Cl_-']) == pytest.approx( 1.059e-2, rel=1e-3) assert value(stream[0].mole_frac_phase_comp['Liq', 'Ca_2+']) == pytest.approx( 1.744e-4, rel=1e-3) assert value(stream[0].mole_frac_phase_comp['Liq', 'SO4_2-']) == pytest.approx( 4.064e-4, rel=1e-3) assert value(stream[0].mole_frac_phase_comp['Liq', 'Mg_2+']) == pytest.approx( 1.061e-3, rel=1e-3) assert value(stream[0].mass_frac_phase_comp['Liq', 'Na_+']) == pytest.approx( 1.112e-2, rel=1e-3) assert value(stream[0].mass_frac_phase_comp['Liq', 'Cl_-']) == pytest.approx( 2.03e-2, rel=1e-3) assert value(stream[0].mass_frac_phase_comp['Liq', 'Ca_2+']) == pytest.approx( 3.82e-4, rel=1e-3) assert value(stream[0].mass_frac_phase_comp['Liq', 'SO4_2-']) == pytest.approx( 2.136e-3, rel=1e-3) assert value(stream[0].mass_frac_phase_comp['Liq', 'Mg_2+']) == pytest.approx( 1.394e-3, rel=1e-3)
"H2O":0.0, "CO2":0.0034, "N2":0.0361, "Ar":0.0, "SO2":0.0} m, solver = main( comps=comps, rxns=rxns, phases=phases, air_comp=air_comp, ng_comp=ng_comp) run_full_load(m, solver) #iscale.constraint_autoscale_large_jac(m) jac, nlp = iscale.get_jacobian(m, scaled=True) print("Extreme Jacobian entries:") for i in iscale.extreme_jacobian_entries(jac=jac, nlp=nlp, large=100): print(f" {i[0]:.2e}, [{i[1]}, {i[2]}]") print("Unscaled constraints:") for c in iscale.unscaled_constraints_generator(m): print(f" {c}") print("Scaled constraints by factor:") for c, s in iscale.constraints_with_scale_factor_generator(m): print(f" {c}, {s}") print("Badly scaled variables:") for v, sv in iscale.badly_scaled_var_generator(m, large=1e2, small=1e-2, zero=1e-12): print(f" {v} -- {sv} -- {iscale.get_scaling_factor(v)}") print(f"Jacobian Condition Number: {iscale.jacobian_cond(jac=jac):.2e}") write_pfd_results("gas_turbine_results.svg", m.tags, m.tag_format) #run_series(m, solver)
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_var_scaling(self, NF_frame): m = NF_frame badly_scaled_var_lst = list(badly_scaled_var_generator(m)) assert badly_scaled_var_lst == []
def test_repeated_scaling(self, RO_frame): # check repeated scaling does not create badly scaled vars calculate_scaling_factors(RO_frame) for _ in badly_scaled_var_generator(RO_frame): assert False
def test_seawater_data(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = DSPMDEParameterBlock( default={ "solute_list": ["Ca_2+", "SO4_2-", "Na_+", "Cl_-", "Mg_2+"], "diffusivity_data": { ("Liq", "Ca_2+"): 0.792e-9, ("Liq", "SO4_2-"): 1.06e-9, ("Liq", "Na_+"): 1.33e-9, ("Liq", "Cl_-"): 2.03e-9, ("Liq", "Mg_2+"): 0.706e-9, }, "mw_data": { "H2O": 18e-3, "Na_+": 23e-3, "Ca_2+": 40e-3, "Mg_2+": 24e-3, "Cl_-": 35e-3, "SO4_2-": 96e-3, }, "electrical_mobility_data": { "Na_+": 5.19e-8, "Ca_2+": 6.17e-8, "Mg_2+": 5.50e-8, "Cl_-": 7.92e-8, "SO4_2-": 8.29e-8, }, "stokes_radius_data": { "Na_+": 0.184e-9, "Ca_2+": 0.309e-9, "Mg_2+": 0.347e-9, "Cl_-": 0.121e-9, "SO4_2-": 0.230e-9, }, "charge": { "Na_+": 1, "Ca_2+": 2, "Mg_2+": 2, "Cl_-": -1, "SO4_2-": -2 }, "density_calculation": DensityCalculation.seawater, "activity_coefficient_model": ActivityCoefficientModel.davies, }) m.fs.stream = stream = m.fs.properties.build_state_block( [0], default={"defined_state": True}) mass_flow_in = 1 * pyunits.kg / pyunits.s feed_mass_frac = { "Na_+": 11122e-6, "Ca_2+": 382e-6, "Mg_2+": 1394e-6, "SO4_2-": 2136e-6, "Cl_-": 20300e-6, } for ion, x in feed_mass_frac.items(): mol_comp_flow = (x * pyunits.kg / pyunits.kg * mass_flow_in / stream[0].mw_comp[ion]) stream[0].flow_mol_phase_comp["Liq", ion].fix(mol_comp_flow) H2O_mass_frac = 1 - sum(x for x in feed_mass_frac.values()) H2O_mol_comp_flow = (H2O_mass_frac * pyunits.kg / pyunits.kg * mass_flow_in / stream[0].mw_comp["H2O"]) stream[0].flow_mol_phase_comp["Liq", "H2O"].fix(H2O_mol_comp_flow) stream[0].temperature.fix(298.15) stream[0].pressure.fix(101325) stream[0].assert_electroneutrality(defined_state=True, tol=1e-2, adjust_by_ion="Cl_-") metadata = m.fs.properties.get_metadata().properties for v_name in metadata: getattr(stream[0], v_name) assert stream[0].is_property_constructed("conc_mol_phase_comp") assert_units_consistent(m) check_dof(m, fail_flag=True) m.fs.properties.set_default_scaling("flow_mol_phase_comp", 1e-1, index=("Liq", "H2O")) m.fs.properties.set_default_scaling("flow_mol_phase_comp", 1e1, index=("Liq", "Na_+")) m.fs.properties.set_default_scaling("flow_mol_phase_comp", 1e1, index=("Liq", "Cl_-")) m.fs.properties.set_default_scaling("flow_mol_phase_comp", 1e2, index=("Liq", "Ca_2+")) m.fs.properties.set_default_scaling("flow_mol_phase_comp", 1e2, index=("Liq", "SO4_2-")) m.fs.properties.set_default_scaling("flow_mol_phase_comp", 1e2, index=("Liq", "Mg_2+")) calculate_scaling_factors(m) stream.initialize() # check if any variables are badly scaled badly_scaled_var_list = list( badly_scaled_var_generator(m, large=100, small=0.01, zero=1e-10)) assert len(badly_scaled_var_list) == 0 results = solver.solve(m) assert_optimal_termination(results) assert value(stream[0].flow_vol_phase["Liq"]) == pytest.approx(9.767e-4, rel=1e-3) assert value(stream[0].flow_mol_phase_comp["Liq", "H2O"]) == pytest.approx( 53.59256, rel=1e-3) assert value(stream[0].flow_mol_phase_comp["Liq", "Na_+"]) == pytest.approx( 0.4836, rel=1e-3) assert value(stream[0].flow_mol_phase_comp["Liq", "Ca_2+"]) == pytest.approx( 0.00955, rel=1e-3) assert value(stream[0].flow_mol_phase_comp["Liq", "Mg_2+"]) == pytest.approx( 0.05808, rel=1e-3) assert value(stream[0].flow_mol_phase_comp["Liq", "Cl_-"]) == pytest.approx( 0.57443, rel=1e-3) assert value(stream[0].flow_mol_phase_comp["Liq", "SO4_2-"]) == pytest.approx( 0.02225, rel=1e-3) assert value(stream[0].dens_mass_phase["Liq"]) == pytest.approx(1023.816, rel=1e-3) assert value(stream[0].pressure_osm_phase["Liq"]) == pytest.approx( 29.132e5, rel=1e-3) assert value( stream[0].electrical_conductivity_phase["Liq"]) == pytest.approx( 8.08, rel=1e-3) assert value(stream[0].flow_vol) == pytest.approx(9.767e-4, rel=1e-3) assert value( sum(stream[0].conc_mass_phase_comp["Liq", j] for j in m.fs.properties.ion_set | m.fs.properties.solute_set)) == pytest.approx(35.9744, rel=1e-3) assert value( sum(stream[0].mass_frac_phase_comp["Liq", j] for j in m.fs.properties.ion_set | m.fs.properties.solute_set)) == pytest.approx(0.035142, rel=1e-3) assert value( sum(stream[0].mass_frac_phase_comp["Liq", j] for j in m.fs.properties.component_list)) == pytest.approx( 1, rel=1e-3) assert value( sum(stream[0].mole_frac_phase_comp["Liq", j] for j in m.fs.properties.component_list)) == pytest.approx( 1, rel=1e-3) assert value(stream[0].conc_mol_phase_comp["Liq", "Na_+"]) == pytest.approx( 495.082, rel=1e-3) assert value(stream[0].conc_mol_phase_comp["Liq", "Cl_-"]) == pytest.approx( 588.0431, rel=1e-3) assert value(stream[0].conc_mol_phase_comp["Liq", "Ca_2+"]) == pytest.approx( 9.777, rel=1e-3) assert value(stream[0].conc_mol_phase_comp["Liq", "SO4_2-"]) == pytest.approx( 22.780, rel=1e-3) assert value(stream[0].conc_mol_phase_comp["Liq", "Mg_2+"]) == pytest.approx( 59.467, rel=1e-3) assert value(stream[0].conc_mass_phase_comp["Liq", "Na_+"]) == pytest.approx( 11.387, rel=1e-3) assert value(stream[0].conc_mass_phase_comp["Liq", "Cl_-"]) == pytest.approx( 20.5815, rel=1e-3) assert value(stream[0].conc_mass_phase_comp["Liq", "Ca_2+"]) == pytest.approx( 0.391, rel=1e-3) assert value(stream[0].conc_mass_phase_comp["Liq", "SO4_2-"]) == pytest.approx( 2.187, rel=1e-3) assert value(stream[0].conc_mass_phase_comp["Liq", "Mg_2+"]) == pytest.approx( 1.427, rel=1e-3) assert value(stream[0].mole_frac_phase_comp["Liq", "Na_+"]) == pytest.approx( 8.833e-3, rel=1e-3) assert value(stream[0].mole_frac_phase_comp["Liq", "Cl_-"]) == pytest.approx( 1.049e-2, rel=1e-3) assert value(stream[0].mole_frac_phase_comp["Liq", "Ca_2+"]) == pytest.approx( 1.744e-4, rel=1e-3) assert value(stream[0].mole_frac_phase_comp["Liq", "SO4_2-"]) == pytest.approx( 4.064e-4, rel=1e-3) assert value(stream[0].mole_frac_phase_comp["Liq", "Mg_2+"]) == pytest.approx( 1.061e-3, rel=1e-3) assert value(stream[0].mass_frac_phase_comp["Liq", "Na_+"]) == pytest.approx( 1.112e-2, rel=1e-3) assert value(stream[0].mass_frac_phase_comp["Liq", "Cl_-"]) == pytest.approx( 2.01e-2, rel=1e-3) assert value(stream[0].mass_frac_phase_comp["Liq", "Ca_2+"]) == pytest.approx( 3.82e-4, rel=1e-3) assert value(stream[0].mass_frac_phase_comp["Liq", "SO4_2-"]) == pytest.approx( 2.136e-3, rel=1e-3) assert value(stream[0].mass_frac_phase_comp["Liq", "Mg_2+"]) == pytest.approx( 1.394e-3, rel=1e-3) assert value(stream[0].debye_huckel_constant) == pytest.approx(0.01554, rel=1e-3) assert value(stream[0].ionic_strength) == pytest.approx(0.73467, rel=1e-3)
data_module.add_data_match_obj(model=main_model.case[i].m, df_meta=df_meta, bin_stdev=bin_stdev) #load data and model inputs already solved ms.from_json(main_model.case[i].m, fname=f"results/state4_{i}.json.gz", root_name="unknown") main_model.case[i].m.obj_datarec.deactivate() #make sure the whole thing solves main_model.obj = pyo.Objective(expr=sum(main_model.case[i].m.obj_expr for i in case_indexes) / len(case_indexes) / 100) strip_bounds = pyo.TransformationFactory("contrib.strip_var_bounds") strip_bounds.apply_to(main_model, reversible=False) for v, sv in iscale.badly_scaled_var_generator(main_model, small=0, large=100): iscale.set_scaling_factor(v, 1 / pyo.value(v)) iscale.calculate_scaling_factors(main_model) solver.solve(main_model, linear_eliminate=True, tee=True) set_weight("1JT66801S", 30, case_indexes) set_weight("1FWS-FWFLW-A", 20, case_indexes) set_weight("DGS3", 0.5, case_indexes) set_weight("S634", 2, case_indexes) set_weight("S831", 5, case_indexes) drop_tags = [ "1FWS-STMFLW-A", "1TCMVACPT2", "S11",
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"])
def _test_no_badly_scaled_vars(m): for v, _ in badly_scaled_var_generator(m): # TODO: COSTING_UPDATE come back after costing has scaling strategy if "costing" in v.name: continue raise Exception(f"Badly scaled variable {v.name}")