def _set_ene_bal_scaling(unit): max_enth_mol_phase = 1 min_scale = 1 for phase in unit.control_volume.properties_in[0.0].enth_mol_phase: val = max( min_scale, abs( value(unit.control_volume.properties_in[0.0]. enth_mol_phase[phase].expr)), ) max_enth_mol_phase = max(val, max_enth_mol_phase) iscale.set_scaling_factor( unit.control_volume.properties_in[0.0]._enthalpy_flow_term[phase], 10 / val) iscale.set_scaling_factor( unit.control_volume.properties_out[0.0]._enthalpy_flow_term[phase], 10 / val) iscale.constraint_scaling_transform( unit.control_volume.enthalpy_balances[0.0], 10 / max_enth_mol_phase)
def calculate_scaling_factors(self): # set a default Reynolds number scaling for v in self.N_Re.values(): if iscale.get_scaling_factor(v, warning=True) is None: iscale.set_scaling_factor(v, 1e-4) for v in self.friction_factor_darcy.values(): if iscale.get_scaling_factor(v, warning=True) is None: iscale.set_scaling_factor(v, 100) for v in self.deltaP_gravity.values(): if iscale.get_scaling_factor(v, warning=True) is None: iscale.set_scaling_factor(v, 1e-3) for v in self.deltaP_friction.values(): if iscale.get_scaling_factor(v, warning=True) is None: iscale.set_scaling_factor(v, 1e-3) for t, c in self.volume_eqn.items(): sf = iscale.get_scaling_factor(self.volume[t], default=1, warning=True) iscale.constraint_scaling_transform(c, sf, overwrite=False) for t, c in self.Reynolds_number_eqn.items(): sf = iscale.get_scaling_factor(self.N_Re[t], default=1, warning=True) sf *= iscale.get_scaling_factor( self.control_volume.properties_in[t].visc_d_phase["Liq"], default=1, warning=True) iscale.constraint_scaling_transform(c, sf, overwrite=False) for t, c in self.pressure_change_friction_eqn.items(): sf = iscale.get_scaling_factor(self.deltaP_friction[t], default=1, warning=True) iscale.constraint_scaling_transform(c, sf, overwrite=False) for t, c in self.pressure_change_gravity_eqn.items(): sf = iscale.get_scaling_factor(self.deltaP_gravity[t], default=1, warning=True) iscale.constraint_scaling_transform(c, sf, overwrite=False) for t, c in self.pressure_change_total_eqn.items(): sf = iscale.get_scaling_factor(self.deltaP[t], default=1, warning=True) iscale.constraint_scaling_transform(c, sf, overwrite=False)
def test_scaling_inherent(self, inherent_reactions_config): model = inherent_reactions_config for i in model.fs.unit.control_volume.inherent_reaction_extent_index: scale = value( model.fs.unit.control_volume.properties_out[0.0].k_eq[ i[1]].expr) iscale.set_scaling_factor( model.fs.unit.control_volume.inherent_reaction_extent[0.0, i[1]], 10 / scale) iscale.constraint_scaling_transform( model.fs.unit.control_volume.properties_out[0.0]. inherent_equilibrium_constraint[i[1]], 0.1) # Next, try adding scaling for species min = 1e-3 for i in model.fs.unit.control_volume.properties_out[ 0.0].mole_frac_phase_comp: # i[0] = phase, i[1] = species if model.fs.unit.inlet.mole_frac_comp[0, i[1]].value > min: scale = model.fs.unit.inlet.mole_frac_comp[0, i[1]].value else: scale = min iscale.set_scaling_factor( model.fs.unit.control_volume.properties_out[0.0]. mole_frac_comp[i[1]], 10 / scale) iscale.set_scaling_factor( model.fs.unit.control_volume.properties_out[0.0]. mole_frac_phase_comp[i], 10 / scale) iscale.set_scaling_factor( model.fs.unit.control_volume.properties_out[0.0]. flow_mol_phase_comp[i], 10 / scale) iscale.constraint_scaling_transform( model.fs.unit.control_volume.properties_out[0.0]. component_flow_balances[i[1]], 10 / scale) iscale.constraint_scaling_transform( model.fs.unit.control_volume.material_balances[0.0, i[1]], 10 / scale) 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)
def m(self): m = pyo.ConcreteModel() m.a = pyo.Var(initialize=0.25, bounds=(-0.5, 0.5)) m.b = b = pyo.Block() b.a = pyo.Var([1, 2], bounds=(-10, 10)) m.c = pyo.Constraint(expr=(0, 1. / (m.a**2), 100)) b.c = pyo.Constraint([1, 2], rule=lambda b, i: (i - 1, b.a[i], i + 2)) b.d = pyo.Constraint(expr=b.a[1]**4 + b.a[2]**4 <= 4) set_scaling_factor(b.d, 1e6) b.o = pyo.Expression(expr=sum(b.a)**2) m.o = pyo.Objective(expr=m.a + b.o) # references are tricky, could cause a variable # to be iterated over several times in # component_data_objects m.b_a = pyo.Reference(b.a) return m
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', 'NaCl'], 1e2) calculate_scaling_factors(m.fs) # check that all variables have scaling factors unscaled_var_list = list(unscaled_variables_generator(m)) for v in unscaled_var_list: print(v) 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 set_scaling_factors(m): """ Set scaling factors for variables and expressions. These are used for variable scaling and used by the framework to scale constraints. Args: m: plant model to set scaling factors for. Returns: None """ # Set scaling factors for boiler system iscale.set_scaling_factor(m.fs.tank.control_volume.energy_holdup, 1e-10) iscale.set_scaling_factor(m.fs.tank.control_volume.material_holdup, 1e-6) if m.dynamic: for t, c in m.fs.tank.control_volume\ .energy_accumulation_disc_eq.items(): iscale.constraint_scaling_transform(c, 1e-6) # scaling factor for control valves for t in m.fs.config.time: iscale.set_scaling_factor( m.fs.valve.control_volume.properties_in[t].flow_mol, 0.001) # Calculate calculated scaling factors iscale.calculate_scaling_factors(m)
def calculate_chemical_scaling_factors_for_material_balances(unit): # Next, try adding scaling for species min = 1e-3 for i in unit.control_volume.properties_out[0.0].mole_frac_phase_comp: # i[0] = phase, i[1] = species if unit.inlet.mole_frac_comp[0, i[1]].value > min: scale = unit.inlet.mole_frac_comp[0, i[1]].value else: scale = min iscale.set_scaling_factor( unit.control_volume.properties_out[0.0].mole_frac_comp[i[1]], 10 / scale) iscale.set_scaling_factor( unit.control_volume.properties_out[0.0].mole_frac_phase_comp[i], 10 / scale) iscale.set_scaling_factor( unit.control_volume.properties_out[0.0].flow_mol_phase_comp[i], 10 / scale) iscale.constraint_scaling_transform( unit.control_volume.properties_out[0.0].component_flow_balances[ i[1]], 10 / scale, ) iscale.constraint_scaling_transform( unit.control_volume.material_balances[0.0, i[1]], 10 / scale)
def calculate_scaling_factors(self): # Get default scale factors and do calculations from base classes super().calculate_scaling_factors() d_sf_Q = self.params.default_scaling_factor["flow_vol"] d_sf_c = self.params.default_scaling_factor["conc_mass_comp"] for j, v in self.flow_mass_comp.items(): if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(v, d_sf_Q * d_sf_c) if self.is_property_constructed("flow_vol"): if iscale.get_scaling_factor(self.flow_vol) is None: iscale.set_scaling_factor(self.flow_vol, d_sf_Q) if self.is_property_constructed("conc_mass_comp"): for j, v in self.conc_mass_comp.items(): sf_c = iscale.get_scaling_factor(self.conc_mass_comp[j]) if sf_c is None: try: sf_c = self.params.default_scaling_factor[( "conc_mass_comp", j)] except KeyError: sf_c = d_sf_c iscale.set_scaling_factor(self.conc_mass_comp[j], sf_c)
def test_compressor(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = PressureChanger( default={ "property_package": m.fs.properties, "thermodynamic_assumption": ThermodynamicAssumption.isentropic, "compressor": True }) # set inputs m.fs.unit.inlet.flow_mol[0].fix(10000) m.fs.unit.inlet.enth_mol[0].fix(4000) m.fs.unit.inlet.pressure[0].fix(101325) m.fs.unit.deltaP.fix(500000) m.fs.unit.efficiency_isentropic.fix(0.9) iscale.set_scaling_factor(m.fs.unit.control_volume.work[0], 1e-5) iscale.calculate_scaling_factors(m) assert degrees_of_freedom(m) == 0 m.fs.unit.get_costing(mover_type="compressor") m.fs.unit.initialize() results = solver.solve(m) # Check for optimal solution assert results.solver.termination_condition == \ TerminationCondition.optimal assert results.solver.status == SolverStatus.ok assert value(m.fs.unit.control_volume.work[0]) == \ pytest.approx(101410.4, rel=1e-5) assert m.fs.unit.costing.purchase_cost.value == \ pytest.approx(334598, rel=1e-5) assert_units_consistent(m.fs.unit) solver.solve(m, tee=True) assert m.fs.unit.costing.purchase_cost.value == \ pytest.approx(334598, rel=1e-5)
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 calculate_scaling_factors(self): for v in self.deltaP_gravity.values(): if iscale.get_scaling_factor(v, warning=True) is None: iscale.set_scaling_factor(v, 1e-3) for v in self.deltaP_contraction.values(): if iscale.get_scaling_factor(v, warning=True) is None: iscale.set_scaling_factor(v, 1e-3) for t, c in self.pressure_change_contraction_eqn.items(): sf = iscale.get_scaling_factor( self.deltaP_contraction[t], default=1, warning=True) iscale.constraint_scaling_transform(c, sf) for t, c in self.pressure_change_gravity_eqn.items(): sf = iscale.get_scaling_factor( self.deltaP_gravity[t], default=1, warning=True) iscale.constraint_scaling_transform(c, sf) for t, c in self.pressure_change_total_eqn.items(): sf = iscale.get_scaling_factor( self.deltaP[t], default=1, warning=True) iscale.constraint_scaling_transform(c, sf)
def test_scaling_stoich(self, water_stoich): m = water_stoich # Next, try adding scaling for species min = 1e-3 for i in m.fs.unit.control_volume.properties_out[0.0].mole_frac_phase_comp: # i[0] = phase, i[1] = species if m.fs.unit.inlet.mole_frac_comp[0, i[1]].value > min: scale = m.fs.unit.inlet.mole_frac_comp[0, i[1]].value else: scale = min iscale.set_scaling_factor( m.fs.unit.control_volume.properties_out[0.0].mole_frac_comp[i[1]], 10 / scale, ) iscale.set_scaling_factor( m.fs.unit.control_volume.properties_out[0.0].mole_frac_phase_comp[i], 10 / scale, ) iscale.set_scaling_factor( m.fs.unit.control_volume.properties_out[0.0].flow_mol_phase_comp[i], 10 / scale, ) iscale.constraint_scaling_transform( m.fs.unit.control_volume.properties_out[0.0].component_flow_balances[ i[1] ], 10 / scale, ) iscale.constraint_scaling_transform( m.fs.unit.control_volume.material_balances[0.0, i[1]], 10 / scale ) iscale.set_scaling_factor( m.fs.unit.control_volume.rate_reaction_extent[0.0, "R1"], 1 ) iscale.calculate_scaling_factors(m.fs.unit) assert isinstance(m.fs.unit.control_volume.scaling_factor, Suffix) assert isinstance( m.fs.unit.control_volume.properties_out[0.0].scaling_factor, Suffix ) assert isinstance( m.fs.unit.control_volume.properties_in[0.0].scaling_factor, Suffix )
def test_scaling(self, model): iscale.set_scaling_factor( model.fs.unit.liquid_phase.properties_out[0].fug_phase_comp["Liq", "CO2"], 1e-5) iscale.set_scaling_factor( model.fs.unit.liquid_phase.properties_out[0].fug_phase_comp["Liq", "H2O"], 1e-3) iscale.calculate_scaling_factors(model.fs.unit) assert iscale.get_constraint_transform_applied_scaling_factor( model.fs.unit.unit_material_balance[0, "CO2"]) == 1 assert iscale.get_constraint_transform_applied_scaling_factor( model.fs.unit.unit_material_balance[0, "H2O"]) == 1 assert iscale.get_constraint_transform_applied_scaling_factor( model.fs.unit.unit_material_balance[0, "MEA"]) is None assert iscale.get_constraint_transform_applied_scaling_factor( model.fs.unit.unit_material_balance[0, "N2"]) == 1e8 assert iscale.get_constraint_transform_applied_scaling_factor( model.fs.unit.unit_material_balance[0, "O2"]) == 1e8 assert iscale.get_constraint_transform_applied_scaling_factor( model.fs.unit.unit_phase_equilibrium[0, "CO2"]) == 1e-5 assert iscale.get_constraint_transform_applied_scaling_factor( model.fs.unit.unit_phase_equilibrium[0, "H2O"]) == 1e-3 assert iscale.get_constraint_transform_applied_scaling_factor( model.fs.unit.unit_temperature_equality[0]) == 1e-2 assert iscale.get_constraint_transform_applied_scaling_factor( model.fs.unit.unit_enthalpy_balance[0]) == 1 assert iscale.get_constraint_transform_applied_scaling_factor( model.fs.unit.unit_pressure_balance[0]) == 1e-5
def test_scale_arcs(): m = pyo.ConcreteModel() m.x = pyo.Var([1, 2, 3, 4]) m.y = pyo.Var([1, 2, 3, 4]) m.p1 = Port() m.p1.add(m.x[1], name="x") m.p1.add(m.y[1], name="y") m.p = Port([2, 3, 4]) m.p[2].add(m.x[2], name="x") m.p[2].add(m.y[2], name="y") m.p[3].add(m.x[3], name="x") m.p[3].add(m.y[3], name="y") m.p[4].add(m.x[4], name="x") m.p[4].add(m.y[4], name="y") def arc_rule(b, i): if i == 1: return (m.p1, m.p[2]) elif i == 2: return (m.p[3], m.p[4]) m.arcs = Arc([1, 2], rule=arc_rule) sc.set_scaling_factor(m.x, 10) sc.set_scaling_factor(m.y, 20) sc.set_scaling_factor(m.x[1], 5) # make sure there is no error if the scaling is done with unexpanded arcs sc.scale_arc_constraints(m) # expand and make sure it works pyo.TransformationFactory('network.expand_arcs').apply_to(m) sc.scale_arc_constraints(m) m.x[1] = 1 m.x[2] = 2 m.x[3] = 3 m.x[4] = 4 m.y[1] = 11 m.y[2] = 12 m.y[3] = 13 m.y[4] = 14 # for all the arc constraints the differnce is 1 the scale factor is the # smallest scale factor for variables in a constraint. Make sure the # constraints are scaled as expected. assert abs(m.arcs_expanded[1].x_equality.body()) == 5 assert abs(m.arcs_expanded[2].x_equality.body()) == 10 assert abs(m.arcs_expanded[1].y_equality.body()) == 20 assert abs(m.arcs_expanded[2].y_equality.body()) == 20
def _set_mat_bal_scaling_FpcTP(unit, min_flow_mol_phase_comp=1e-3): # For species for i in unit.control_volume.properties_out[0.0].mole_frac_phase_comp: # i[0] = phase, i[1] = species scale = max(min_flow_mol_phase_comp, unit.inlet.flow_mol_phase_comp[0, i[0], i[1]].value) iscale.set_scaling_factor( unit.control_volume.properties_out[0.0].mole_frac_comp[i[1]], 10 / scale) iscale.set_scaling_factor( unit.control_volume.properties_out[0.0].mole_frac_phase_comp[i], 10 / scale) iscale.set_scaling_factor( unit.control_volume.properties_out[0.0].flow_mol_phase_comp[i], 10 / scale) iscale.constraint_scaling_transform( unit.control_volume.material_balances[0.0, i[1]], 10 / scale) if hasattr(unit.control_volume, "volume"): iscale.set_scaling_factor(unit.control_volume.volume, 10 / unit.volume[0.0].value)
def calculate_scaling_factors(self): super().calculate_scaling_factors() # set a default waterwall zone heat scaling factor for v in self.waterwall_heat.values(): if iscale.get_scaling_factor(v, warning=True) is None: iscale.set_scaling_factor(v, 1e-7) # set a default platen heat scaling factor if self.config.has_platen_superheater is True: for v in self.platen_heat.values(): if iscale.get_scaling_factor(v, warning=True) is None: iscale.set_scaling_factor(v, 1e-7) # set a default roof heat scaling factor if self.config.has_roof_superheater is True: for v in self.roof_heat.values(): if iscale.get_scaling_factor(v, warning=True) is None: iscale.set_scaling_factor(v, 1e-6) # set waterwall heat constraint scaling factor for t, c in self.eq_surr_waterwall_heat.items(): sf = iscale.get_scaling_factor(self.waterwall_heat[t], default=1e-7, warning=True) iscale.constraint_scaling_transform(c, sf) # set platen heat constraint scaling factor if self.config.has_platen_superheater is True: for t, c in self.eq_surr_platen_heat.items(): sf = iscale.get_scaling_factor(self.platen_heat[t], default=1e-7, warning=True) iscale.constraint_scaling_transform(c, sf) # set roof heat constraint scaling factor if self.config.has_roof_superheater is True: for t, c in self.eq_surr_roof_heat.items(): sf = iscale.get_scaling_factor(self.roof_heat[t], default=1e-6, warning=True) iscale.constraint_scaling_transform(c, sf) # set flue gas temperature constraint scaling factor for t, c in self.flue_gas_temp_eqn.items(): sf = iscale.get_scaling_factor(self.platen_heat[t], default=1e-7, warning=True) iscale.constraint_scaling_transform(c, sf)
def test_jacobian(self): """Make sure the Jacobian from Pynumero matches expectation. This is mostly to ensure we understand the interface and catch if things change. """ m = self.model() assert number_activated_objectives(m) == 0 jac, jac_scaled, nlp = sc.constraint_autoscale_large_jac(m, no_scale=True) assert number_activated_objectives(m) == 0 c1_row = nlp._condata_to_idx[m.c1] c2_row = nlp._condata_to_idx[m.c2] c3_row = nlp._condata_to_idx[m.c3] x_col = nlp._vardata_to_idx[m.x] y_col = nlp._vardata_to_idx[m.y] z_col = nlp._vardata_to_idx[m.z] assert jac[c1_row, x_col] == pytest.approx(-1e6) assert jac[c1_row, y_col] == pytest.approx(-1e3) assert jac[c1_row, z_col] == pytest.approx(1) assert jac[c2_row, x_col] == pytest.approx(3) assert jac[c2_row, y_col] == pytest.approx(4) assert jac[c2_row, z_col] == pytest.approx(2) assert jac[c3_row, z_col] == pytest.approx(3e8) # Make sure scaling factors don't affect the result sc.set_scaling_factor(m.c1, 1e-6) sc.set_scaling_factor(m.x, 1e-3) sc.set_scaling_factor(m.y, 1e-6) sc.set_scaling_factor(m.z, 1e-4) jac, jac_scaled, nlp = sc.constraint_autoscale_large_jac(m, no_scale=True) assert jac[c1_row, x_col] == pytest.approx(-1e6) # Check the scaled jacobian calculation assert jac_scaled[c1_row, x_col] == pytest.approx(-1000) assert jac_scaled[c1_row, y_col] == pytest.approx(-1000) assert jac_scaled[c1_row, z_col] == pytest.approx(0.01)
def calculate_scaling_factors(self): super().calculate_scaling_factors() # scale variables if iscale.get_scaling_factor( self.efficiency_pressure_exchanger) is None: # efficiency should always be between 0.1-1 iscale.set_scaling_factor(self.efficiency_pressure_exchanger, 1) # scale expressions if iscale.get_scaling_factor(self.low_pressure_side.work) is None: sf = iscale.get_scaling_factor( self.low_pressure_side.properties_in[0].flow_vol) sf = sf * iscale.get_scaling_factor( self.low_pressure_side.deltaP[0]) iscale.set_scaling_factor(self.low_pressure_side.work, sf) if iscale.get_scaling_factor(self.high_pressure_side.work) is None: sf = iscale.get_scaling_factor( self.high_pressure_side.properties_in[0].flow_vol) sf = sf * iscale.get_scaling_factor( self.high_pressure_side.deltaP[0]) iscale.set_scaling_factor(self.high_pressure_side.work, sf) # transform constraints for t, c in self.low_pressure_side.eq_isothermal_temperature.items(): sf = iscale.get_scaling_factor( self.low_pressure_side.properties_in[t].temperature) iscale.constraint_scaling_transform(c, sf) for t, c in self.high_pressure_side.eq_isothermal_temperature.items(): sf = iscale.get_scaling_factor( self.high_pressure_side.properties_in[t].temperature) iscale.constraint_scaling_transform(c, sf) for t, c in self.eq_pressure_transfer.items(): sf = iscale.get_scaling_factor(self.low_pressure_side.deltaP[t]) iscale.constraint_scaling_transform(c, sf) for t, c in self.eq_equal_flow_vol.items(): sf = iscale.get_scaling_factor( self.low_pressure_side.properties_in[t].flow_vol) iscale.constraint_scaling_transform(c, sf) for t, c in self.eq_equal_low_pressure.items(): sf = iscale.get_scaling_factor( self.low_pressure_side.properties_in[t].pressure) iscale.constraint_scaling_transform(c, sf)
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 model_scaling(self, model, variant: Variant): map_variant_reaction_scale_func = { Variant.equilibrium: self._do_equilibrium_reaction_scaling, Variant.inherent: self._do_inherent_reaction_scaling, } scale_func = map_variant_reaction_scale_func[variant] scale_func(model) # Next, try adding scaling for species min = 1e-3 for i in model.fs.unit.control_volume.properties_out[ 0.0].mole_frac_phase_comp: # i[0] = phase, i[1] = species if model.fs.unit.inlet.mole_frac_comp[0, i[1]].value > min: scale = model.fs.unit.inlet.mole_frac_comp[0, i[1]].value else: scale = min iscale.set_scaling_factor( model.fs.unit.control_volume.properties_out[0.0]. mole_frac_comp[i[1]], 10 / scale, ) iscale.set_scaling_factor( model.fs.unit.control_volume.properties_out[0.0]. mole_frac_phase_comp[i], 10 / scale, ) iscale.set_scaling_factor( model.fs.unit.control_volume.properties_out[0.0]. flow_mol_phase_comp[i], 10 / scale, ) iscale.constraint_scaling_transform( model.fs.unit.control_volume.properties_out[0.0]. component_flow_balances[i[1]], 10 / scale, ) iscale.constraint_scaling_transform( model.fs.unit.control_volume.material_balances[0.0, i[1]], 10 / scale) iscale.calculate_scaling_factors(model.fs.unit) return model
def test_user_set_scaling(): m = pyo.ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.pp = PhysicalParameterTestBlock() m.fs.cv = ControlVolume1DBlock( default={ "property_package": m.fs.pp, "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_material_balances( balance_type=MaterialBalanceType.componentTotal, has_phase_equilibrium=False) m.fs.cv.add_energy_balances(balance_type=EnergyBalanceType.enthalpyTotal, has_heat_transfer=True, has_work_transfer=True) # add momentum balance m.fs.cv.add_momentum_balances( balance_type=MomentumBalanceType.pressureTotal, has_pressure_change=True) m.fs.cv.apply_transformation() # The scaling factors used for this test were selected to be easy values to # test, they do not represent typical scaling factors. iscale.set_scaling_factor(m.fs.cv.heat, 11) iscale.set_scaling_factor(m.fs.cv.work, 12) iscale.set_scaling_factor(m.fs.cv.heat[0, 0], 17) iscale.calculate_scaling_factors(m) # Make sure the heat and work scaling factors are set and not overwritten # by the defaults in calculate_scaling_factors assert iscale.get_scaling_factor(m.fs.cv.heat) == 11 assert iscale.get_scaling_factor(m.fs.cv.work) == 12 # Make sure scaling factor is propagated but does not overwrite index specific factor for t in m.fs.time: for x in m.fs.cv.length_domain: if t == 0 and x == 0: assert iscale.get_scaling_factor(m.fs.cv.heat[t, x]) == 17 else: assert iscale.get_scaling_factor(m.fs.cv.heat[t, x]) == 11 assert iscale.get_scaling_factor(m.fs.cv.work[t, x]) == 12
def test_map_scaling_factor(caplog): m = pyo.ConcreteModel() m.x = pyo.Var([1, 2, 3, 4]) sc.set_scaling_factor(m.x[1], 11) sc.set_scaling_factor(m.x[2], 12) sc.set_scaling_factor(m.x[3], 13) caplog.set_level(logging.WARNING) caplog.clear() assert sc.map_scaling_factor(m.x.values(), warning=True) == 1 logrec = caplog.records[0] assert logrec.levelno == logging.WARNING assert "missing scaling factor" in logrec.message assert sc.map_scaling_factor(m.x.values(), func=max) == 13 assert sc.map_scaling_factor(m.x.values(), default=20) == 11 with pytest.raises(TypeError): sc.map_scaling_factor(m.x.values(), default=None) # test min_scaling_factor with just calls map_scaling_factor assert sc.min_scaling_factor(m.x.values()) == 1 assert sc.min_scaling_factor(m.x.values(), default=14) == 11
def calculate_scaling_factors(self): # Get default scale factors and do calculations from base classes super().calculate_scaling_factors() # Lock attribute creation to avoid hasattr triggering builds self._lock_attribute_creation = True # Due to the exponential relationship between most reaction properties # and temeprature, it is very hard to calculate good scaling factors # from order-of-magnitude guesses. Thus ,reaction scaling will always # require a lot of user input. Here we will calculate scaling factors # for those properties that have non-exponential relationships to T. if hasattr(self, "dh_rxn"): for r, v in self.dh_rxn.items(): if iscale.get_scaling_factor(v) is None: rblock = getattr(self.params, "reaction_" + r) try: carg = self.params.config.rate_reactions[r] except (AttributeError, KeyError): carg = self.params.config.equilibrium_reactions[r] sf = carg["heat_of_reaction"].calculate_scaling_factors( self, rblock) iscale.set_scaling_factor(v, sf) if hasattr(self, "k_eq"): for r, v in self.k_eq.items(): if iscale.get_scaling_factor(v) is None: rblock = getattr(self.params, "reaction_" + r) carg = self.params.config.equilibrium_reactions[r] sf = carg[ "equilibrium_constant"].calculate_scaling_factors( self, rblock) iscale.set_scaling_factor(v, sf) if hasattr(self, "log_k_eq"): for r, v in self.log_k_eq.items(): if iscale.get_scaling_factor(v) is None: rblock = getattr(self.params, "reaction_" + r) carg = self.params.config.equilibrium_reactions[r] sf = carg[ "equilibrium_constant"].calculate_scaling_factors( self, rblock) iscale.set_scaling_factor(v, log(sf)) if hasattr(self, "equilibrium_constraint"): for r, v in self.equilibrium_constraint.items(): carg = self.params.config.equilibrium_reactions[r] if iscale.get_scaling_factor(v) is None: if carg["equilibrium_form"].__name__.startswith("log_"): # Log form constraint sf = iscale.get_scaling_factor(self.log_k_eq[r], default=1, warning=True) else: sf = iscale.get_scaling_factor(self.k_eq[r], default=1, warning=True) sf_const = carg["equilibrium_form"].calculate_scaling_factors( self, sf) iscale.constraint_scaling_transform(v, sf_const, overwrite=False) # Unlock attribute creation when done self._lock_attribute_creation = False
def calculate_scaling_factors(self): super().calculate_scaling_factors() units_meta = self.config.property_package.get_metadata().get_derived_units # scaling factors for turbidity relationship # Supressing warning (these factors are not very important) if iscale.get_scaling_factor(self.slope) is None: sf = iscale.get_scaling_factor(self.slope, default=1, warning=False) iscale.set_scaling_factor(self.slope, sf) if iscale.get_scaling_factor(self.intercept) is None: sf = iscale.get_scaling_factor(self.intercept, default=1, warning=False) iscale.set_scaling_factor(self.intercept, sf) # scaling factors for turbidity measurements and chemical doses # Supressing warning if iscale.get_scaling_factor(self.initial_turbidity_ntu) is None: sf = iscale.get_scaling_factor(self.initial_turbidity_ntu, default=1, warning=False) iscale.set_scaling_factor(self.initial_turbidity_ntu, sf) if iscale.get_scaling_factor(self.final_turbidity_ntu) is None: sf = iscale.get_scaling_factor(self.final_turbidity_ntu, default=1, warning=False) iscale.set_scaling_factor(self.final_turbidity_ntu, sf) if iscale.get_scaling_factor(self.chemical_doses) is None: sf = iscale.get_scaling_factor(self.chemical_doses, default=1, warning=False) iscale.set_scaling_factor(self.chemical_doses, sf) # set scaling for tss_loss_rate if iscale.get_scaling_factor(self.tss_loss_rate) is None: sf = 0 for t in self.control_volume.properties_in: sf += value(self.control_volume.properties_in[t].flow_mass_phase_comp['Liq','TSS']) sf = sf / len(self.control_volume.properties_in) if sf < 0.01: sf = 0.01 iscale.set_scaling_factor(self.tss_loss_rate, 1/sf) for ind, c in self.eq_tss_loss_rate.items(): iscale.constraint_scaling_transform(c, 1/sf) # set scaling for tds_gain_rate if self.config.chemical_additives: if iscale.get_scaling_factor(self.tds_gain_rate) is None: sf = 0 for t in self.control_volume.properties_in: sum = 0 for j in self.config.chemical_additives.keys(): chem_dose = pyunits.convert(self.chemical_doses[t, j], to_units=units_meta('mass')*units_meta('length')**-3) chem_dose = chem_dose/self.chemical_mw[j] * \ self.salt_from_additive_mole_ratio[j] * \ self.salt_mw[j]*self.control_volume.properties_in[t].flow_vol_phase['Liq'] sum = sum+chem_dose sf += value(sum) sf = sf / len(self.control_volume.properties_in) if sf < 0.001: sf = 0.001 iscale.set_scaling_factor(self.tds_gain_rate, 1/sf) for ind, c in self.eq_tds_gain_rate.items(): iscale.constraint_scaling_transform(c, 1/sf) # set scaling for mass transfer terms for ind, c in self.eq_mass_transfer_term.items(): if ind[2] == "TDS": if self.config.chemical_additives: sf = iscale.get_scaling_factor(self.tds_gain_rate) else: sf = 1 elif ind[2] == "TSS": sf = iscale.get_scaling_factor(self.tss_loss_rate) elif ind[2] == "Sludge": sf = iscale.get_scaling_factor(self.tss_loss_rate) else: sf = 1 iscale.constraint_scaling_transform(c, sf) iscale.set_scaling_factor(self.control_volume.mass_transfer_term[ind] , sf) # set scaling factors for control_volume.properties_in based on control_volume.properties_out for t in self.control_volume.properties_in: if iscale.get_scaling_factor(self.control_volume.properties_in[t].dens_mass_phase) is None: sf = iscale.get_scaling_factor(self.control_volume.properties_out[t].dens_mass_phase) iscale.set_scaling_factor(self.control_volume.properties_in[t].dens_mass_phase, sf) if iscale.get_scaling_factor(self.control_volume.properties_in[t].flow_mass_phase_comp) is None: for ind in self.control_volume.properties_in[t].flow_mass_phase_comp: sf = iscale.get_scaling_factor(self.control_volume.properties_out[t].flow_mass_phase_comp[ind]) iscale.set_scaling_factor(self.control_volume.properties_in[t].flow_mass_phase_comp[ind], sf) if iscale.get_scaling_factor(self.control_volume.properties_in[t].mass_frac_phase_comp) is None: for ind in self.control_volume.properties_in[t].mass_frac_phase_comp: sf = iscale.get_scaling_factor(self.control_volume.properties_out[t].mass_frac_phase_comp[ind]) iscale.set_scaling_factor(self.control_volume.properties_in[t].mass_frac_phase_comp[ind], sf) if iscale.get_scaling_factor(self.control_volume.properties_in[t].flow_vol_phase) is None: for ind in self.control_volume.properties_in[t].flow_vol_phase: sf = iscale.get_scaling_factor(self.control_volume.properties_out[t].flow_vol_phase[ind]) iscale.set_scaling_factor(self.control_volume.properties_in[t].flow_vol_phase[ind], sf) # update scaling for control_volume.properties_out for t in self.control_volume.properties_out: if iscale.get_scaling_factor(self.control_volume.properties_out[t].dens_mass_phase) is None: iscale.set_scaling_factor(self.control_volume.properties_out[t].dens_mass_phase, 1e-3) # need to update scaling factors for TSS, Sludge, and TDS to account for the # expected change in their respective values from the loss/gain rates for ind in self.control_volume.properties_out[t].flow_mass_phase_comp: if ind[1] == "TSS": sf_og = iscale.get_scaling_factor(self.control_volume.properties_out[t].flow_mass_phase_comp[ind]) sf_new = iscale.get_scaling_factor(self.tss_loss_rate) iscale.set_scaling_factor(self.control_volume.properties_out[t].flow_mass_phase_comp[ind], 100*sf_new*(sf_new/sf_og)) if ind[1] == "Sludge": sf_og = iscale.get_scaling_factor(self.control_volume.properties_out[t].flow_mass_phase_comp[ind]) sf_new = iscale.get_scaling_factor(self.tss_loss_rate) iscale.set_scaling_factor(self.control_volume.properties_out[t].flow_mass_phase_comp[ind], 100*sf_new*(sf_new/sf_og)) for ind in self.control_volume.properties_out[t].mass_frac_phase_comp: if ind[1] == "TSS": sf_og = iscale.get_scaling_factor(self.control_volume.properties_out[t].mass_frac_phase_comp[ind]) sf_new = iscale.get_scaling_factor(self.tss_loss_rate) iscale.set_scaling_factor(self.control_volume.properties_out[t].mass_frac_phase_comp[ind], 100*sf_new*(sf_new/sf_og)) if ind[1] == "Sludge": sf_og = iscale.get_scaling_factor(self.control_volume.properties_out[t].mass_frac_phase_comp[ind]) sf_new = iscale.get_scaling_factor(self.tss_loss_rate) iscale.set_scaling_factor(self.control_volume.properties_out[t].mass_frac_phase_comp[ind], 100*sf_new*(sf_new/sf_og))
def set_operating_conditions(m): # ---specifications--- # parameters pump_efi = 0.75 # pump efficiency [-] erd_efi = 0.8 # energy recovery device efficiency [-] mem_A = 4.2e-12 # membrane water permeability coefficient [m/s-Pa] mem_B = 3.5e-8 # membrane salt permeability coefficient [m/s] height = 1e-3 # channel height in membrane stage [m] spacer_porosity = 0.97 # spacer porosity in membrane stage [-] width = 5 # membrane width factor [m] area = 100 # membrane area [m^2] pressure_atm = 101325 # atmospheric pressure [Pa] # feed feed_flow_mass = 1*pyunits.kg/pyunits.s feed_mass_frac_NaCl = 70.0/1000.0 feed_temperature = 273.15 + 25 # initialize feed m.fs.feed.pressure[0].fix(pressure_atm) m.fs.feed.temperature[0].fix(feed_temperature) m.fs.feed.flow_mass_phase_comp[0, 'Liq', 'NaCl'].fix(feed_flow_mass * feed_mass_frac_NaCl) m.fs.feed.flow_mass_phase_comp[0, 'Liq', 'H2O'].fix(feed_flow_mass * (1-feed_mass_frac_NaCl)) # initialize pumps for pump in m.fs.PrimaryPumps.values(): pump.control_volume.properties_out[0].pressure = 75e5 pump.efficiency_pump.fix(pump_efi) pump.control_volume.properties_out[0].pressure.fix() iscale.set_scaling_factor(pump.control_volume.work, 1e-3) # initialize eq pumps for pump in m.fs.BoosterPumps.values(): pump.efficiency_pump.fix(pump_efi) iscale.set_scaling_factor(pump.control_volume.work, 1e-3) # initialize stages for idx, stage in m.fs.ROUnits.items(): if idx > m.fs.StageSet.first(): B_scale = 100.0 else: B_scale = 1.0 stage.A_comp.fix(mem_A) stage.B_comp.fix(mem_B*B_scale) stage.channel_height.fix(height) stage.spacer_porosity.fix(spacer_porosity) stage.area.fix(area/float(idx)) stage.width.fix(width) stage.permeate.pressure[0].fix(pressure_atm) # energy recovery device m.fs.EnergyRecoveryDevice.efficiency_pump.fix(erd_efi) m.fs.EnergyRecoveryDevice.control_volume.properties_out[0].pressure.fix(pressure_atm) iscale.set_scaling_factor(m.fs.EnergyRecoveryDevice.control_volume.work, 1e-3) # ---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')) iscale.calculate_scaling_factors(m) # ---checking model--- assert_units_consistent(m) assert_no_degrees_of_freedom(m) print('Feed Concentration = %.1f ppt' % (value(m.fs.feed.flow_mass_phase_comp[0, 'Liq', 'NaCl'])*1000))
def calculate_scaling_factors(self): super().calculate_scaling_factors() # setting scaling factors for variables # default scaling factors have already been set with # idaes.core.property_base.calculate_scaling_factors() # scaling factors for parameters for j, v in self.params.mw_comp.items(): if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(self.params.mw_comp[j], 1e2) if iscale.get_scaling_factor(self.params.dens_mass) is None: iscale.set_scaling_factor(self.params.dens_mass, 1e-3) if iscale.get_scaling_factor(self.params.cp) is None: iscale.set_scaling_factor(self.params.cp, 1e-3) # these variables should have user input if iscale.get_scaling_factor(self.flow_mass_phase_comp["Liq", "H2O"]) is None: sf = iscale.get_scaling_factor(self.flow_mass_phase_comp["Liq", "H2O"], default=1, warning=True) iscale.set_scaling_factor(self.flow_mass_phase_comp["Liq", "H2O"], sf) if iscale.get_scaling_factor(self.flow_mass_phase_comp["Liq", "Na"]) is None: sf = iscale.get_scaling_factor(self.flow_mass_phase_comp["Liq", "Na"], default=1e2, warning=True) iscale.set_scaling_factor(self.flow_mass_phase_comp["Liq", "Na"], sf) if iscale.get_scaling_factor(self.flow_mass_phase_comp["Liq", "Ca"]) is None: sf = iscale.get_scaling_factor(self.flow_mass_phase_comp["Liq", "Ca"], default=1e4, warning=True) iscale.set_scaling_factor(self.flow_mass_phase_comp["Liq", "Ca"], sf) if iscale.get_scaling_factor(self.flow_mass_phase_comp["Liq", "Mg"]) is None: sf = iscale.get_scaling_factor(self.flow_mass_phase_comp["Liq", "Mg"], default=1e3, warning=True) iscale.set_scaling_factor(self.flow_mass_phase_comp["Liq", "Mg"], sf) if iscale.get_scaling_factor(self.flow_mass_phase_comp["Liq", "SO4"]) is None: sf = iscale.get_scaling_factor(self.flow_mass_phase_comp["Liq", "SO4"], default=1e3, warning=True) iscale.set_scaling_factor(self.flow_mass_phase_comp["Liq", "SO4"], sf) if iscale.get_scaling_factor(self.flow_mass_phase_comp["Liq", "Cl"]) is None: sf = iscale.get_scaling_factor(self.flow_mass_phase_comp["Liq", "Cl"], default=1e2, warning=True) iscale.set_scaling_factor(self.flow_mass_phase_comp["Liq", "Cl"], sf) # these variables do not typically require user input, # will not override if the user does provide the scaling factor if self.is_property_constructed("mass_frac_phase_comp"): for j in self.params.component_list: if (iscale.get_scaling_factor( self.mass_frac_phase_comp["Liq", j]) is None): if j == "H2O": iscale.set_scaling_factor( self.mass_frac_phase_comp["Liq", j], 1) else: sf = iscale.get_scaling_factor( self.flow_mass_phase_comp[ "Liq", j]) / iscale.get_scaling_factor( self.flow_mass_phase_comp["Liq", "H2O"]) iscale.set_scaling_factor( self.mass_frac_phase_comp["Liq", j], sf) if self.is_property_constructed("flow_vol"): sf = iscale.get_scaling_factor( self.flow_mass_phase_comp["Liq", "H2O"]) / iscale.get_scaling_factor( self.params.dens_mass) iscale.set_scaling_factor(self.flow_vol, sf) if self.is_property_constructed("flow_mol_phase_comp"): for j in self.params.component_list: if (iscale.get_scaling_factor( self.flow_mol_phase_comp["Liq", j]) is None): sf = iscale.get_scaling_factor(self.flow_mass_phase_comp[ "Liq", j]) / iscale.get_scaling_factor( self.params.mw_comp[j]) iscale.set_scaling_factor( self.flow_mol_phase_comp["Liq", j], sf) if self.is_property_constructed("conc_mol_phase_comp"): for j in self.params.component_list: if (iscale.get_scaling_factor( self.conc_mol_phase_comp["Liq", j]) is None): sf = iscale.get_scaling_factor(self.flow_mol_phase_comp[ "Liq", j]) / iscale.get_scaling_factor(self.flow_vol) iscale.set_scaling_factor( self.conc_mol_phase_comp["Liq", j], sf) if self.is_property_constructed("enth_flow"): if iscale.get_scaling_factor(self.enth_flow) is None: sf = (iscale.get_scaling_factor(self.params.cp) * iscale.get_scaling_factor( self.flow_mass_phase_comp["Liq", "H2O"]) * 1e-1 ) # temperature change on the order of 1e1 iscale.set_scaling_factor(self.enth_flow, sf) # transforming constraints # property relationships with no index, simple constraint v_str_lst_simple = ["flow_vol"] for v_str in v_str_lst_simple: if self.is_property_constructed(v_str): v = getattr(self, v_str) sf = iscale.get_scaling_factor(v, default=1, warning=True) c = getattr(self, "eq_" + v_str) iscale.constraint_scaling_transform(c, sf) # property relationships indexed by component and phase v_str_lst_phase_comp = [ "mass_frac_phase_comp", "flow_mol_phase_comp", "conc_mol_phase_comp", ] for v_str in v_str_lst_phase_comp: if self.is_property_constructed(v_str): v_comp = getattr(self, v_str) c_comp = getattr(self, "eq_" + v_str) for j, c in c_comp.items(): sf = iscale.get_scaling_factor(v_comp["Liq", j], default=1, warning=True) iscale.constraint_scaling_transform(c, sf)
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 calculate_scaling_factors(self): if iscale.get_scaling_factor(self.dens_solvent) is None: sf = iscale.get_scaling_factor( self.feed_side.properties[0, 0].dens_mass_phase['Liq']) iscale.set_scaling_factor(self.dens_solvent, sf) super().calculate_scaling_factors() # these variables should have user input, if not there will be a warning if iscale.get_scaling_factor(self.width) is None: sf = iscale.get_scaling_factor(self.width, default=1, warning=True) iscale.set_scaling_factor(self.width, sf) if iscale.get_scaling_factor(self.length) is None: sf = iscale.get_scaling_factor(self.length, default=10, warning=True) iscale.set_scaling_factor(self.length, sf) # setting scaling factors for variables # will not override if the user provides the scaling factor ## default of 1 set by ControlVolume1D if iscale.get_scaling_factor(self.area_cross) == 1: iscale.set_scaling_factor(self.area_cross, 100) for (t, x, p, j), v in self.mass_transfer_phase_comp.items(): sf = (iscale.get_scaling_factor( self.feed_side.properties[t, x].get_material_flow_terms(p, j)) / iscale.get_scaling_factor(self.feed_side.length)) * value( self.nfe) if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(v, sf) v = self.feed_side.mass_transfer_term[t, x, p, j] if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(v, sf) if hasattr(self, 'deltaP'): for v in self.deltaP.values(): if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(v, 1e-4) if hasattr(self, 'dP_dx'): for v in self.feed_side.pressure_dx.values(): iscale.set_scaling_factor(v, 1e-5) else: for v in self.feed_side.pressure_dx.values(): iscale.set_scaling_factor(v, 1e5)
def calculate_scaling_factors(self): # setting scaling factors for variables # will not override if the user does provide the scaling factor if iscale.get_scaling_factor(self.dens_solvent) is None: sf = iscale.get_scaling_factor( self.feed_side.properties_in[0].dens_mass_phase['Liq']) iscale.set_scaling_factor(self.dens_solvent, sf) super().calculate_scaling_factors() for (t, p, j), v in self.mass_transfer_phase_comp.items(): sf = iscale.get_scaling_factor( self.feed_side.properties_in[t].get_material_flow_terms(p, j)) if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(v, sf) v = self.feed_side.mass_transfer_term[t, p, j] if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(v, sf) if hasattr(self, 'area_cross'): if iscale.get_scaling_factor(self.area_cross) is None: iscale.set_scaling_factor(self.area_cross, 100) if hasattr(self, 'length'): if iscale.get_scaling_factor(self.length) is None: iscale.set_scaling_factor(self.length, 1) if hasattr(self, 'width'): if iscale.get_scaling_factor(self.width) is None: iscale.set_scaling_factor(self.width, 1) if hasattr(self, 'dP_dx'): for v in self.dP_dx.values(): if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(v, 1e-4)
def calculate_scaling_factors(self): super().calculate_scaling_factors() # Var scaling # The following Vars' sf are allowed to be provided by users or set by default. if ( iscale.get_scaling_factor(self.solute_diffusivity_membrane, warning=True) is None ): iscale.set_scaling_factor(self.solute_diffusivity_membrane, 1e10) if iscale.get_scaling_factor(self.membrane_thickness, warning=True) is None: iscale.set_scaling_factor(self.membrane_thickness, 1e4) if ( iscale.get_scaling_factor(self.water_permeability_membrane, warning=True) is None ): iscale.set_scaling_factor(self.water_permeability_membrane, 1e14) if iscale.get_scaling_factor(self.cell_length, warning=True) is None: iscale.set_scaling_factor(self.cell_length, 1e1) if iscale.get_scaling_factor(self.cell_width, warning=True) is None: iscale.set_scaling_factor(self.cell_width, 1e1) if iscale.get_scaling_factor(self.spacer_thickness, warning=True) is None: iscale.set_scaling_factor(self.spacer_thickness, 1e4) if ( iscale.get_scaling_factor(self.membrane_surface_resistance, warning=True) is None ): iscale.set_scaling_factor(self.membrane_surface_resistance, 1e4) if iscale.get_scaling_factor(self.electrodes_resistance, warning=True) is None: iscale.set_scaling_factor(self.electrodes_resistance, 1e4) if iscale.get_scaling_factor(self.current, warning=True) is None: iscale.set_scaling_factor(self.current, 1) if iscale.get_scaling_factor(self.voltage, warning=True) is None: iscale.set_scaling_factor(self.voltage, 1e-1) # The folloing Vars are built for constructing constraints and their sf are computed from other Vars. iscale.set_scaling_factor( self.elec_migration_flux_in, iscale.get_scaling_factor(self.current) * iscale.get_scaling_factor(self.cell_length) ** -1 * iscale.get_scaling_factor(self.cell_width) ** -1 * 1e5, ) iscale.set_scaling_factor( self.elec_migration_flux_out, iscale.get_scaling_factor(self.current) * iscale.get_scaling_factor(self.cell_length) ** -1 * iscale.get_scaling_factor(self.cell_width) ** -1 * 1e5, ) iscale.set_scaling_factor( self.power_electrical, iscale.get_scaling_factor(self.current) * iscale.get_scaling_factor(self.voltage), ) for ind, c in self.specific_power_electrical.items(): iscale.set_scaling_factor( self.specific_power_electrical[ind], 3.6e6 * iscale.get_scaling_factor(self.current[ind]) * iscale.get_scaling_factor(self.voltage[ind]) * iscale.get_scaling_factor( self.diluate_channel.properties_out[ind].flow_vol_phase["Liq"] ) ** -1, ) # Constraint scaling for ind, c in self.eq_current_voltage_relation.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.membrane_surface_resistance) ) for ind, c in self.eq_power_electrical.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.power_electrical) ) for ind, c in self.eq_specific_power_electrical.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.specific_power_electrical[ind]) ) for ind, c in self.eq_elec_migration_flux_in.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.elec_migration_flux_in) ) for ind, c in self.eq_elec_migration_flux_out.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.elec_migration_flux_out) ) for ind, c in self.eq_nonelec_flux_in.items(): if ind[2] == "H2O": sf = ( 1e-3 * 0.018 * iscale.get_scaling_factor(self.water_permeability_membrane) * iscale.get_scaling_factor( self.concentrate_channel.properties_in[ ind[0] ].pressure_osm_phase[ind[1]] ) ) sf = ( iscale.get_scaling_factor(self.solute_diffusivity_membrane) / iscale.get_scaling_factor(self.membrane_thickness) * iscale.get_scaling_factor( self.concentrate_channel.properties_in[ind[0]].conc_mol_phase_comp[ ind[1], ind[2] ] ) ) iscale.set_scaling_factor(self.nonelec_flux_in[ind], sf) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_nonelec_flux_out.items(): if ind[2] == "H2O": sf = ( 1e-3 * 0.018 * iscale.get_scaling_factor(self.water_permeability_membrane) * iscale.get_scaling_factor( self.concentrate_channel.properties_out[ ind[0] ].pressure_osm_phase[ind[1]] ) ) else: sf = ( iscale.get_scaling_factor(self.solute_diffusivity_membrane) / iscale.get_scaling_factor(self.membrane_thickness) * iscale.get_scaling_factor( self.concentrate_channel.properties_out[ ind[0] ].conc_mol_phase_comp[ind[1], ind[2]] ) ) iscale.set_scaling_factor(self.nonelec_flux_out[ind], sf) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_mass_transfer_term_diluate.items(): iscale.constraint_scaling_transform( c, min( iscale.get_scaling_factor(self.elec_migration_flux_in[ind]), iscale.get_scaling_factor( self.nonelec_flux_in[ind], self.elec_migration_flux_out[ind] ), iscale.get_scaling_factor(self.nonelec_flux_out[ind]), ), ) for ind, c in self.eq_mass_transfer_term_concentrate.items(): iscale.constraint_scaling_transform( c, min( iscale.get_scaling_factor(self.elec_migration_flux_in[ind]), iscale.get_scaling_factor( self.nonelec_flux_in[ind], self.elec_migration_flux_out[ind] ), iscale.get_scaling_factor(self.nonelec_flux_out[ind]), ), ) for ind, c in self.eq_power_electrical.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.power_electrical[ind]), ) for ind, c in self.eq_specific_power_electrical.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.specific_power_electrical[ind]) * iscale.get_scaling_factor( self.diluate_channel.properties_out[ind].flow_vol_phase["Liq"] ), ) for ind, c in self.eq_current_efficiency.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.current[ind]) ) for ind, c in self.eq_isothermal_diluate.items(): iscale.constraint_scaling_transform( c, self.diluate_channel.properties_in[ind].temperature ) for ind, c in self.eq_isothermal_concentrate.items(): iscale.constraint_scaling_transform( c, self.concentrate_channel.properties_in[ind].temperature )