def calculate_scaling_factors(self): super().calculate_scaling_factors() for t, c in self.stodola_equation.items(): s = iscale.get_scaling_factor( self.control_volume.properties_in[t].flow_mol)**2 iscale.constraint_scaling_transform(c, s)
def build_tb(m, base_inlet="ion", base_outlet="TDS", name_str=None): """ Build a translator block to convert for the specified base from inlet to outlet. """ if name_str is None: name_str = "tb_" + base_inlet + "_to_" + base_outlet if base_inlet not in ["ion", "salt"]: raise ValueError( "Unexpected property base inlet {base_inlet} for build_tb" "".format(base_inlet=base_inlet)) prop_inlet = property_models.get_prop(m, base=base_inlet) if base_outlet not in ["TDS"]: raise ValueError( "Unexpected property base outlet {base_outlet} for build_tb" "".format(base_outlet=base_outlet)) prop_outlet = property_models.get_prop(m, base=base_outlet) # build translator block setattr( m.fs, name_str, Translator( default={ "inlet_property_package": prop_inlet, "outlet_property_package": prop_outlet, }), ) blk = getattr(m.fs, name_str) # scale translator block to get scaling factors calculate_scaling_factors(blk) # add translator block constraints blk.eq_equal_temperature = Constraint( expr=blk.inlet.temperature[0] == blk.outlet.temperature[0]) constraint_scaling_transform( blk.eq_equal_temperature, get_scaling_factor(blk.properties_in[0].temperature)) blk.eq_equal_pressure = Constraint( expr=blk.inlet.pressure[0] == blk.outlet.pressure[0]) constraint_scaling_transform( blk.eq_equal_pressure, get_scaling_factor(blk.properties_in[0].pressure)) if base_inlet == "ion" and base_outlet == "TDS": blk.eq_H2O_balance = Constraint(expr=blk.inlet.flow_mass_phase_comp[ 0, "Liq", "H2O"] == blk.outlet.flow_mass_phase_comp[0, "Liq", "H2O"]) constraint_scaling_transform( blk.eq_H2O_balance, get_scaling_factor( blk.properties_out[0].flow_mass_phase_comp["Liq", "H2O"]), ) blk.eq_TDS_balance = Constraint(expr=sum( blk.inlet.flow_mass_phase_comp[0, "Liq", j] for j in ["Na", "Ca", "Mg", "SO4", "Cl" ]) == blk.outlet.flow_mass_phase_comp[0, "Liq", "TDS"]) constraint_scaling_transform( blk.eq_TDS_balance, get_scaling_factor( blk.properties_out[0].flow_mass_phase_comp["Liq", "TDS"]), ) elif base_inlet == "salt" and base_outlet == "TDS": blk.eq_H2O_balance = Constraint(expr=blk.inlet.flow_mass_phase_comp[ 0, "Liq", "H2O"] == blk.outlet.flow_mass_phase_comp[0, "Liq", "H2O"]) constraint_scaling_transform( blk.eq_H2O_balance, get_scaling_factor( blk.properties_out[0].flow_mass_phase_comp["Liq", "H2O"]), ) blk.eq_TDS_balance = Constraint(expr=sum( blk.inlet.flow_mass_phase_comp[0, "Liq", j] for j in ["NaCl", "CaSO4", "MgSO4", "MgCl2" ]) == blk.outlet.flow_mass_phase_comp[0, "Liq", "TDS"]) constraint_scaling_transform( blk.eq_TDS_balance, get_scaling_factor( blk.properties_out[0].flow_mass_phase_comp["Liq", "TDS"]), ) else: raise ValueError("Unexpected property base combination for build_tb") blk.properties_in[0].mass_frac_phase_comp # touch for initialization blk.properties_out[0].mass_frac_phase_comp
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 calculate_state(self, var_args=None, hold_state=False, outlvl=idaeslog.NOTSET, solver=None, optarg=None): """ Solves state blocks given a set of variables and their values. These variables can be state variables or properties. This method is typically used before initialization to solve for state variables because non-state variables (i.e. properties) cannot be fixed in initialization routines. Keyword Arguments: var_args : dictionary with variables and their values, they can be state variables or properties {(VAR_NAME, INDEX): VALUE} hold_state : flag indicating whether all of the state variables should be fixed after calculate state. True - State variables will be fixed. False - State variables will remain unfixed, unless already fixed. outlvl : idaes logger object that sets output level of solve call (default=idaeslog.NOTSET) solver : solver name string if None is provided the default solver for IDAES will be used (default = None) optarg : solver options dictionary object (default={}) Returns: results object from state block solve """ # Get logger solve_log = idaeslog.getSolveLogger(self.name, level=outlvl, tag="properties") # Initialize at current state values (not user provided) self.initialize(solver=solver, optarg=optarg, outlvl=outlvl) # Set solver and options opt = get_solver(solver, optarg) # Fix variables and check degrees of freedom flags = { } # dictionary noting which variables were fixed and their previous state for k in self.keys(): sb = self[k] for (v_name, ind), val in var_args.items(): var = getattr(sb, v_name) if iscale.get_scaling_factor(var[ind]) is None: _log.warning( "While using the calculate_state method on {sb_name}, variable {v_name} " "was provided as an argument in var_args, but it does not have a scaling " "factor. This suggests that the calculate_scaling_factor method has not been " "used or the variable was created on demand after the scaling factors were " "calculated. It is recommended to touch all relevant variables (i.e. call " "them or set an initial value) before using the calculate_scaling_factor " "method.".format(v_name=v_name, sb_name=sb.name)) if var[ind].is_fixed(): flags[(k, v_name, ind)] = True if value(var[ind]) != val: raise ConfigurationError( "While using the calculate_state method on {sb_name}, {v_name} was " "fixed to a value {val}, but it was already fixed to value {val_2}. " "Unfix the variable before calling the calculate_state " "method or update var_args." "".format(sb_name=sb.name, v_name=var.name, val=val, val_2=value(var[ind]))) else: flags[(k, v_name, ind)] = False var[ind].fix(val) if degrees_of_freedom(sb) != 0: raise RuntimeError( "While using the calculate_state method on {sb_name}, the degrees " "of freedom were {dof}, but 0 is required. Check var_args and ensure " "the correct fixed variables are provided." "".format(sb_name=sb.name, dof=degrees_of_freedom(sb))) # Solve with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: results = solve_indexed_blocks(opt, [self], tee=slc.tee) solve_log.info_high("Calculate state: {}.".format( idaeslog.condition(results))) if not check_optimal_termination(results): _log.warning( "While using the calculate_state method on {sb_name}, the solver failed " "to converge to an optimal solution. This suggests that the user provided " "infeasible inputs, or that the model is poorly scaled, poorly initialized, " "or degenerate.") # unfix all variables fixed with var_args for (k, v_name, ind), previously_fixed in flags.items(): if not previously_fixed: var = getattr(self[k], v_name) var[ind].unfix() # fix state variables if hold_state if hold_state: fix_state_vars(self) return results
def calculate_scaling_factors(self): super().calculate_scaling_factors() units_meta = self.config.property_package.get_metadata( ).get_derived_units # Provide some intial guess values before scaling self.propogate_initial_state() # Add scaling for unit model vars (with user input) if iscale.get_scaling_factor(self.caustic_dose_rate) is None: sf = iscale.get_scaling_factor(self.caustic_dose_rate, default=1e4, warning=True) iscale.set_scaling_factor(self.caustic_dose_rate, sf) if iscale.get_scaling_factor(self.reactor_volume) is None: sf = iscale.get_scaling_factor(self.reactor_volume, default=1, warning=True) iscale.set_scaling_factor(self.reactor_volume, sf) if iscale.get_scaling_factor(self.reactor_retention_time) is None: sf = iscale.get_scaling_factor(self.reactor_retention_time, default=1e-2, warning=True) iscale.set_scaling_factor(self.reactor_retention_time, sf) # Add scaling for unit model vars (without user input) if iscale.get_scaling_factor(self.conc_mol_Boron) is None: sf = iscale.get_scaling_factor( self.control_volume.properties_in[0].conc_mol_phase_comp[ "Liq", self.boron_name_id], default=1, warning=False, ) iscale.set_scaling_factor(self.conc_mol_Boron, sf / 10) if iscale.get_scaling_factor(self.conc_mol_Borate) is None: sf = iscale.get_scaling_factor( self.control_volume.properties_in[0].conc_mol_phase_comp[ "Liq", self.borate_name_id], default=1, warning=False, ) iscale.set_scaling_factor(self.conc_mol_Borate, sf / 10) # Scaling for H and OH if iscale.get_scaling_factor(self.conc_mol_H) is None: if self.proton_name_id in self.config.property_package.component_list: sf = iscale.get_scaling_factor( self.control_volume.properties_in[0].conc_mol_phase_comp[ "Liq", self.proton_name_id], default=1, warning=False, ) else: sf = 10 iscale.set_scaling_factor(self.conc_mol_H, sf) if iscale.get_scaling_factor(self.conc_mol_OH) is None: if self.hydroxide_name_id in self.config.property_package.component_list: sf = iscale.get_scaling_factor( self.control_volume.properties_in[0].conc_mol_phase_comp[ "Liq", self.hydroxide_name_id], default=1, warning=False, ) else: sf = 10 iscale.set_scaling_factor(self.conc_mol_OH, sf) # Scale isothermal condition sf = iscale.get_scaling_factor( self.control_volume.properties_in[0].temperature) for t in self.control_volume.properties_in: iscale.constraint_scaling_transform(self.eq_isothermal[t], sf) # Scale reactor volume constraint sf = iscale.get_scaling_factor(self.reactor_volume) for t in self.control_volume.properties_in: iscale.constraint_scaling_transform(self.eq_reactor_volume[t], sf) # Scaling for water dissociation and boron dissociation for t in self.control_volume.properties_in: sf = iscale.get_scaling_factor( self.conc_mol_H) * iscale.get_scaling_factor(self.conc_mol_OH) iscale.constraint_scaling_transform(self.eq_water_dissociation[t], sf) for t in self.control_volume.properties_in: sf = iscale.get_scaling_factor( self.conc_mol_Borate) * iscale.get_scaling_factor( self.conc_mol_H) iscale.constraint_scaling_transform(self.eq_boron_dissociation[t], sf) # Scaling for total boron for t in self.control_volume.properties_in: sf = iscale.get_scaling_factor(self.conc_mol_Boron) iscale.constraint_scaling_transform(self.eq_total_boron[t], sf) # Scaling for electroneutrality for t in self.control_volume.properties_in: sf = iscale.get_scaling_factor( self.conc_mol_H) + iscale.get_scaling_factor( self.conc_mol_Borate) iscale.constraint_scaling_transform(self.eq_electroneutrality[t], sf) # Scaling for mass_transfer_term for t in self.control_volume.properties_in: for j in self.config.property_package.component_list: sf = iscale.get_scaling_factor(self.conc_mol_Borate) iscale.constraint_scaling_transform( self.eq_mass_transfer_term[t, "Liq", j], sf)
def calculate_scaling_factors(b): sf_flow = iscale.get_scaling_factor(b.flow_mol, default=1, warning=True) sf_mf = {} for i, v in b.mole_frac_phase_comp.items(): sf_mf[i] = iscale.get_scaling_factor(v, default=1e3, warning=True) sf_h = iscale.get_scaling_factor(b.enth_mol, default=1e-4, warning=True) if b.config.defined_state is False: iscale.constraint_scaling_transform(b.sum_mole_frac_out, min(sf_mf.values()), overwrite=False) iscale.constraint_scaling_transform(b.enth_mol_eq, sf_h, overwrite=False) if len(b.phase_list) == 1: iscale.constraint_scaling_transform(b.total_flow_balance, sf_flow, overwrite=False) for j in b.component_list: sf_j = iscale.get_scaling_factor(b.mole_frac_comp[j], default=1e3, warning=True) iscale.constraint_scaling_transform(b.component_flow_balances[j], sf_j, overwrite=False) # b.phase_fraction_constraint is well scaled elif len(b.phase_list) == 2: iscale.constraint_scaling_transform(b.total_flow_balance, sf_flow, overwrite=False) for j in b.component_list: sf_j = iscale.get_scaling_factor(b.mole_frac_comp[j], default=1e3, warning=True) iscale.constraint_scaling_transform(b.component_flow_balances[j], sf_j * sf_flow, overwrite=False) iscale.constraint_scaling_transform(b.sum_mole_frac, min(sf_mf.values()), overwrite=False) for p in b.phase_list: iscale.constraint_scaling_transform(b.phase_fraction_constraint[p], sf_flow, overwrite=False) else: iscale.constraint_scaling_transform(b.total_flow_balance, sf_flow, overwrite=False) for j in b.component_list: sf_j = iscale.get_scaling_factor(b.mole_frac_comp[j], default=1e3, warning=True) iscale.constraint_scaling_transform(b.component_flow_balances[j], sf_j * sf_flow, overwrite=False) for p in b.phase_list: iscale.constraint_scaling_transform(b.sum_mole_frac[p], min(sf_mf[p, :].values()), overwrite=False) iscale.constraint_scaling_transform(b.phase_fraction_constraint[p], sf_flow, overwrite=False) if b.params._electrolyte: calculate_electrolyte_scaling(b)
def calculate_scaling_factors(self): super().calculate_scaling_factors() for t, c in self.inlet_flow_constraint.items(): s = iscale.get_scaling_factor( self.control_volume.properties_in[t].flow_mol)**2 iscale.constraint_scaling_transform(c, s, overwrite=False)
def calculate_scaling_factors(self): super().calculate_scaling_factors() for ind, c in self.control_volume.isothermal_balance.items(): sf = iscale.get_scaling_factor(self.control_volume.properties_in[0].temperature) iscale.constraint_scaling_transform(c, sf)
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() # for the following variables: flow_mass_phase_comp, pressure, # temperature, dens_mass_phase, visc_d_phase, osm_coeff, and enth_mass_phase # 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=1e0, warning=True) iscale.set_scaling_factor(self.flow_mass_phase_comp["Liq", "H2O"], sf) if iscale.get_scaling_factor(self.flow_mass_phase_comp["Vap", "H2O"]) is None: sf = iscale.get_scaling_factor(self.flow_mass_phase_comp["Vap", "H2O"], default=1e0, warning=True) iscale.set_scaling_factor(self.flow_mass_phase_comp["Vap", "H2O"], sf) # 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, 1e2) # these variables do not typically require user input, # will not override if the user does provide the scaling factor if self.is_property_constructed("flow_vol_phase"): for p in self.params.phase_list: if iscale.get_scaling_factor(self.flow_vol_phase[p]) is None: sf = iscale.get_scaling_factor(self.flow_mass_phase_comp[ p, "H2O"]) / iscale.get_scaling_factor( self.dens_mass_phase[p]) iscale.set_scaling_factor(self.flow_vol_phase[p], sf) if self.is_property_constructed("flow_vol"): if iscale.get_scaling_factor(self.flow_vol) is None: sf_liq = iscale.get_scaling_factor(self.flow_vol_phase["Liq"]) sf_vap = iscale.get_scaling_factor(self.flow_vol_phase["Vap"]) sf = min(sf_liq, sf_vap) iscale.set_scaling_factor(self.flow_vol, sf) if self.is_property_constructed("flow_mol_phase_comp"): for p in self.params.phase_list: if (iscale.get_scaling_factor( self.flow_mol_phase_comp[p, "H2O"]) is None): sf = iscale.get_scaling_factor( self.flow_mass_phase_comp[p, "H2O"]) sf /= iscale.get_scaling_factor(self.params.mw_comp["H2O"]) iscale.set_scaling_factor( self.flow_mol_phase_comp[p, "H2O"], sf) if self.is_property_constructed("mole_frac_phase_comp"): sf_flow_mol_liq = iscale.get_scaling_factor( self.flow_mol_phase_comp["Liq", "H2O"]) sf_flow_mol_vap = iscale.get_scaling_factor( self.flow_mol_phase_comp["Vap", "H2O"]) sf_flow_mol = min(sf_flow_mol_liq, sf_flow_mol_vap) for p in self.params.phase_list: if (iscale.get_scaling_factor( self.mole_frac_phase_comp[p, "H2O"]) is None): sf = (iscale.get_scaling_factor( self.flow_mol_phase_comp[p, "H2O"]) / sf_flow_mol) print("iter:", p, sf) iscale.set_scaling_factor( self.mole_frac_phase_comp[p, "H2O"], sf) if self.is_property_constructed("enth_flow_phase"): for p in self.params.phase_list: if iscale.get_scaling_factor(self.enth_flow_phase[p]) is None: sf = iscale.get_scaling_factor( self.flow_mass_phase_comp[p, "H2O"]) sf *= iscale.get_scaling_factor(self.enth_mass_phase[p]) iscale.set_scaling_factor(self.enth_flow_phase[p], sf) # transforming constraints for metadata_dic in self.params.get_metadata().properties.values(): var_str = metadata_dic["name"] if metadata_dic[ "method"] is not None and self.is_property_constructed( var_str): var = getattr(self, var_str) if isinstance(var, Expression): continue # properties that are expressions do not have constraints con = getattr(self, "eq_" + var_str) for ind in con.keys(): sf = iscale.get_scaling_factor(var[ind], default=1, warning=True) iscale.constraint_scaling_transform(con[ind], sf)
def calculate_scaling_factors(self): super().calculate_scaling_factors() if hasattr(self, "previous_state"): for t, v in self.previous_state.items(): iscale.set_scaling_factor(v.flow_mol, 1e-3) iscale.set_scaling_factor(v.pressure, 1e-5) iscale.set_scaling_factor(v.temperature, 1e-1) if hasattr(self, "tank_diameter"): for t, v in self.tank_diameter.items(): iscale.set_scaling_factor(v, 1) if hasattr(self, "tank_length"): for t, v in self.tank_length.items(): iscale.set_scaling_factor(v, 1) if hasattr(self, "heat_duty"): for t, v in self.heat_duty.items(): iscale.set_scaling_factor(v, 1e-5) if hasattr(self, "material_accumulation"): for (t, p, j), v in self.material_accumulation.items(): iscale.set_scaling_factor(v, 1e-3) if hasattr(self, "energy_accumulation"): for (t, p), v in self.energy_accumulation.items(): iscale.set_scaling_factor(v, 1e-3) if hasattr(self, "material_holdup"): for (t, p, j), v in self.material_holdup.items(): iscale.set_scaling_factor(v, 1e-5) if hasattr(self, "energy_holdup"): for (t, p), v in self.energy_holdup.items(): iscale.set_scaling_factor(v, 1e-5) if hasattr(self, "previous_material_holdup"): for (t, p, j), v in self.previous_material_holdup.items(): iscale.set_scaling_factor(v, 1e-5) if hasattr(self, "previous_energy_holdup"): for (t, p), v in self.previous_energy_holdup.items(): iscale.set_scaling_factor(v, 1e-5) # Volume constraint if hasattr(self, "volume_cons"): for t, c in self.volume_cons.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.tank_length[t], default=1, warning=True)) # Previous time Material Holdup Rule if hasattr(self, "previous_material_holdup_rule"): for (t, i), c in self.previous_material_holdup_rule.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.material_holdup[t, i, j], default=1, warning=True)) # Previous time Energy Holdup Rule if hasattr(self, "previous_energy_holdup_rule"): for (t, i), c in self.previous_energy_holdup_rule.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.energy_holdup[t, i], default=1, warning=True)) # Material Balances if hasattr(self, "material_balances"): for (t, i, j), c in self.material_balances.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.material_accumulation[t, i, j], default=1, warning=True)) # Material Holdup Integration if hasattr(self, "material_holdup_integration"): for (t, i, j), c in self.material_holdup_integration.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.material_holdup[t, i, j], default=1, warning=True)) # Material Holdup Constraints if hasattr(self, "material_holdup_calculation"): for (t, i, j), c in self.material_holdup_calculation.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.material_holdup[t, i, j], default=1, warning=True)) # Enthalpy Balances if hasattr(self, "energy_accumulation_equation"): for t, c in self.energy_accumulation_equation.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.energy_accumulation[t, p], default=1, warning=True)) # Energy Holdup Integration if hasattr(self, "energy_holdup_calculation"): for (t, i), c in self.energy_holdup_calculation.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.energy_holdup[t, i], default=1, warning=True)) # Energy Balance Equation if hasattr(self, "energy_balances"): for t, c in self.energy_balances.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.energy_holdup[t, i], default=1, warning=True))
def calculate_scaling_factors(self): super().calculate_scaling_factors() # TODO: require users to set scaling factor for area or calculate it based on mass transfer and flux iscale.set_scaling_factor(self.area, 1e-1) # setting scaling factors for variables # these variables should have user input, if not there will be a warning if iscale.get_scaling_factor(self.area) is None: sf = iscale.get_scaling_factor(self.area, default=1, warning=True) iscale.set_scaling_factor(self.area, sf) # these variables do not typically require user input, # will not override if the user does provide the scaling factor if iscale.get_scaling_factor(self.A_comp) is None: iscale.set_scaling_factor(self.A_comp, 1e11) if iscale.get_scaling_factor(self.B_comp) is None: iscale.set_scaling_factor(self.B_comp, 1e5) if iscale.get_scaling_factor(self.sigma) is None: iscale.set_scaling_factor(self.sigma, 1) 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) for vobj in [self.flux_mass_phase_comp_in, self.flux_mass_phase_comp_out]: for (t, p, j), v in vobj.items(): if iscale.get_scaling_factor(v) is None: comp = self.config.property_package.get_component(j) if comp.is_solvent(): # scaling based on solvent flux equation sf = (iscale.get_scaling_factor(self.A_comp[t, j]) * iscale.get_scaling_factor(self.dens_solvent) * iscale.get_scaling_factor(self.feed_side.properties_in[t].pressure)) iscale.set_scaling_factor(v, sf) elif comp.is_solute(): # scaling based on solute flux equation sf = (iscale.get_scaling_factor(self.B_comp[t, j]) * iscale.get_scaling_factor(self.feed_side.properties_in[t].conc_mass_phase_comp[p, j])) iscale.set_scaling_factor(v, sf) for vobj in [self.avg_conc_mass_phase_comp_in, self.avg_conc_mass_phase_comp_out]: for (t, p, j), v in vobj.items(): if iscale.get_scaling_factor(v) is None: sf = iscale.get_scaling_factor(self.feed_side.properties_in[t].conc_mass_phase_comp[p, j]) iscale.set_scaling_factor(v, sf) for (t, p, j), v in self.feed_side.mass_transfer_term.items(): if iscale.get_scaling_factor(v) is None: sf = iscale.get_scaling_factor(self.feed_side.properties_in[t].get_material_flow_terms(p, j)) comp = self.config.property_package.get_component(j) if comp.is_solute: sf *= 1e2 # solute typically has mass transfer 2 orders magnitude less than flow iscale.set_scaling_factor(v, sf) for (t, p, j), v in self.mass_transfer_phase_comp.items(): if iscale.get_scaling_factor(v) is None: sf = iscale.get_scaling_factor(self.feed_side.properties_in[t].get_material_flow_terms(p, j)) comp = self.config.property_package.get_component(j) if comp.is_solute: sf *= 1e2 # solute typically has mass transfer 2 orders magnitude less than flow iscale.set_scaling_factor(v, sf) # TODO: update IDAES control volume to scale mass_transfer and enthalpy_transfer for ind, v in self.feed_side.mass_transfer_term.items(): (t, p, j) = ind if iscale.get_scaling_factor(v) is None: sf = iscale.get_scaling_factor(self.feed_side.mass_transfer_term[t, p, j]) iscale.constraint_scaling_transform(self.feed_side.material_balances[t, j], sf) for t, v in self.feed_side.enthalpy_transfer.items(): if iscale.get_scaling_factor(v) is None: sf = (iscale.get_scaling_factor(self.feed_side.properties_in[t].enth_flow)) iscale.set_scaling_factor(v, sf) iscale.constraint_scaling_transform(self.feed_side.enthalpy_balances[t], sf) # transforming constraints for ind, c in self.eq_mass_transfer_term.items(): sf = iscale.get_scaling_factor(self.mass_transfer_phase_comp[ind]) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_permeate_production.items(): sf = iscale.get_scaling_factor(self.mass_transfer_phase_comp[ind]) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_flux_in.items(): sf = iscale.get_scaling_factor(self.flux_mass_phase_comp_in[ind]) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_flux_out.items(): sf = iscale.get_scaling_factor(self.flux_mass_phase_comp_out[ind]) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_avg_conc_in.items(): sf = iscale.get_scaling_factor(self.avg_conc_mass_phase_comp_in[ind]) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_avg_conc_out.items(): sf = iscale.get_scaling_factor(self.avg_conc_mass_phase_comp_out[ind]) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_connect_mass_transfer.items(): sf = iscale.get_scaling_factor(self.mass_transfer_phase_comp[ind]) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_connect_enthalpy_transfer.items(): sf = iscale.get_scaling_factor(self.feed_side.enthalpy_transfer[ind]) iscale.constraint_scaling_transform(c, sf) for t, c in self.eq_permeate_isothermal.items(): sf = iscale.get_scaling_factor(self.feed_side.properties_in[t].temperature) iscale.constraint_scaling_transform(c, sf)
def calculate_scaling_factors(self): super().calculate_scaling_factors() for k in ('ion_set', 'solute_set'): if hasattr(self.config.property_package, k): solute_set = getattr(self.config.property_package, k) break # TODO: require users to set scaling factor for area or calculate it based on mass transfer and flux iscale.set_scaling_factor(self.area, 1e-1) # setting scaling factors for variables # these variables should have user input, if not there will be a warning if iscale.get_scaling_factor(self.area) is None: sf = iscale.get_scaling_factor(self.area, default=1, warning=True) iscale.set_scaling_factor(self.area, sf) # these variables do not typically require user input, # will not override if the user does provide the scaling factor # TODO: this default scaling assumes SI units rather than being based on the property package if iscale.get_scaling_factor(self.dens_solvent) is None: iscale.set_scaling_factor(self.dens_solvent, 1e-3) for t, v in self.flux_vol_solvent.items(): if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(v, 1e6) for (t, p, j), v in self.rejection_phase_comp.items(): if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(v, 1e1) for (t, p, j), v in self.mass_transfer_phase_comp.items(): if iscale.get_scaling_factor(v) is None: sf = 10 * iscale.get_scaling_factor( self.feed_side.properties_in[t].get_material_flow_terms( p, j)) iscale.set_scaling_factor(v, sf) if iscale.get_scaling_factor(self.recovery_vol_phase) is None: iscale.set_scaling_factor(self.recovery_vol_phase, 1) for (t, p, j), v in self.recovery_mass_phase_comp.items(): if j in self.config.property_package.solvent_set: sf = 1 elif j in solute_set: sf = 10 if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(v, sf) # transforming constraints for ind, c in self.feed_side.eq_isothermal.items(): sf = iscale.get_scaling_factor( self.feed_side.properties_in[0].temperature) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_mass_transfer_term.items(): sf = iscale.get_scaling_factor(self.mass_transfer_phase_comp[ind]) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_solvent_transfer.items(): sf = iscale.get_scaling_factor(self.mass_transfer_phase_comp[ind]) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_permeate_production.items(): sf = iscale.get_scaling_factor(self.mass_transfer_phase_comp[ind]) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_rejection_phase_comp.items(): sf = iscale.get_scaling_factor(self.rejection_phase_comp[ind]) iscale.constraint_scaling_transform(c, sf) for t, c in self.eq_permeate_isothermal.items(): sf = iscale.get_scaling_factor( self.feed_side.properties_in[t].temperature) iscale.constraint_scaling_transform(c, sf) for t, c in self.eq_recovery_vol_phase.items(): sf = iscale.get_scaling_factor(self.recovery_vol_phase[t, 'Liq']) iscale.constraint_scaling_transform(c, sf) for (t, j), c in self.eq_recovery_mass_phase_comp.items(): sf = iscale.get_scaling_factor(self.recovery_mass_phase_comp[t, 'Liq', j]) iscale.constraint_scaling_transform(c, sf)
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 _set_default_factor(v, s): for i in v: if iscale.get_scaling_factor(v[i]) is None: iscale.set_scaling_factor(v[i], s)
def _cache_scaling_factors(self): self._scaling_cache = [ (c, get_scaling_factor(c)) for c in self._model.component_data_objects( pyo.Constraint, active=True, descend_into=True)]
def calculate_scaling_factors(self): super().calculate_scaling_factors() if hasattr(self, "work_fluid"): for t, v in self.work_fluid.items(): iscale.set_scaling_factor( v, iscale.get_scaling_factor(self.control_volume.work[t], default=1, warning=True)) if hasattr(self, "work_mechanical"): for t, v in self.work_mechanical.items(): iscale.set_scaling_factor( v, iscale.get_scaling_factor(self.control_volume.work[t], default=1, warning=True)) if hasattr(self, "work_isentropic"): for t, v in self.work_isentropic.items(): iscale.set_scaling_factor( v, iscale.get_scaling_factor(self.control_volume.work[t], default=1, warning=True)) if hasattr(self, "ratioP_calculation"): for t, c in self.ratioP_calculation.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor( self.control_volume.properties_in[t].pressure, default=1, warning=True)) if hasattr(self, "fluid_work_calculation"): for t, c in self.fluid_work_calculation.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.control_volume.deltaP[t], default=1, warning=True)) if hasattr(self, "actual_work"): for t, c in self.actual_work.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.control_volume.work[t], default=1, warning=True)) if hasattr(self, "adiabatic"): for t, c in self.adiabatic.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor( self.control_volume.properties_in[t].enth_mol, default=1, warning=True)) if hasattr(self, "isentropic_pressure"): for t, c in self.isentropic_pressure.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor( self.control_volume.properties_in[t].pressure, default=1, warning=True)) if hasattr(self, "isentropic"): for t, c in self.isentropic.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor( self.control_volume.properties_in[t].entr_mol, default=1, warning=True)) if hasattr(self, "isentropic_energy_balance"): for t, c in self.isentropic_energy_balance.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.control_volume.work[t], default=1, warning=True)) if hasattr(self, "costing"): # import costing scaling factors costing.calculate_scaling_factors(self.costing)
def build_tb(m, base_inlet='ion', base_outlet='TDS', name_str=None): """ Build a translator block to convert for the specified base from inlet to outlet. """ if name_str is None: name_str = 'tb_' + base_inlet + '_to_' + base_outlet if base_inlet not in ['ion', 'salt']: raise ValueError( 'Unexpected property base inlet {base_inlet} for build_tb' ''.format(base_inlet=base_inlet)) prop_inlet = property_models.get_prop(m, base=base_inlet) if base_outlet not in ['TDS']: raise ValueError( 'Unexpected property base outlet {base_outlet} for build_tb' ''.format(base_outlet=base_outlet)) prop_outlet = property_models.get_prop(m, base=base_outlet) # build translator block setattr( m.fs, name_str, Translator( default={ "inlet_property_package": prop_inlet, "outlet_property_package": prop_outlet })) blk = getattr(m.fs, name_str) # scale translator block to get scaling factors calculate_scaling_factors(blk) # add translator block constraints blk.eq_equal_temperature = Constraint( expr=blk.inlet.temperature[0] == blk.outlet.temperature[0]) constraint_scaling_transform( blk.eq_equal_temperature, get_scaling_factor(blk.properties_in[0].temperature)) blk.eq_equal_pressure = Constraint( expr=blk.inlet.pressure[0] == blk.outlet.pressure[0]) constraint_scaling_transform( blk.eq_equal_pressure, get_scaling_factor(blk.properties_in[0].pressure)) if base_inlet == 'ion' and base_outlet == 'TDS': blk.eq_H2O_balance = Constraint(expr=blk.inlet.flow_mass_phase_comp[ 0, 'Liq', 'H2O'] == blk.outlet.flow_mass_phase_comp[0, 'Liq', 'H2O']) constraint_scaling_transform( blk.eq_H2O_balance, get_scaling_factor( blk.properties_out[0].flow_mass_phase_comp['Liq', 'H2O'])) blk.eq_TDS_balance = Constraint(expr=sum( blk.inlet.flow_mass_phase_comp[0, 'Liq', j] for j in ['Na', 'Ca', 'Mg', 'SO4', 'Cl' ]) == blk.outlet.flow_mass_phase_comp[0, 'Liq', 'TDS']) constraint_scaling_transform( blk.eq_TDS_balance, get_scaling_factor( blk.properties_out[0].flow_mass_phase_comp['Liq', 'TDS'])) elif base_inlet == 'salt' and base_outlet == 'TDS': blk.eq_H2O_balance = Constraint(expr=blk.inlet.flow_mass_phase_comp[ 0, 'Liq', 'H2O'] == blk.outlet.flow_mass_phase_comp[0, 'Liq', 'H2O']) constraint_scaling_transform( blk.eq_H2O_balance, get_scaling_factor( blk.properties_out[0].flow_mass_phase_comp['Liq', 'H2O'])) blk.eq_TDS_balance = Constraint(expr=sum( blk.inlet.flow_mass_phase_comp[0, 'Liq', j] for j in ['NaCl', 'CaSO4', 'MgSO4', 'MgCl2' ]) == blk.outlet.flow_mass_phase_comp[0, 'Liq', 'TDS']) constraint_scaling_transform( blk.eq_TDS_balance, get_scaling_factor( blk.properties_out[0].flow_mass_phase_comp['Liq', 'TDS'])) else: raise ValueError('Unexpected property base combination for build_tb') blk.properties_in[0].mass_frac_phase_comp # touch for initialization blk.properties_out[0].mass_frac_phase_comp
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() # for the following variables: pressure, # temperature, dens_mass, visc_d_phase, diffus_phase_comp # these variables should have user input if iscale.get_scaling_factor(self.flow_mol_phase_comp['Liq', 'H2O']) is None: sf = iscale.get_scaling_factor(self.flow_mol_phase_comp['Liq', 'H2O'], default=1, warning=True) iscale.set_scaling_factor(self.flow_mol_phase_comp['Liq', 'H2O'], sf) for j in self.params.solute_set: if iscale.get_scaling_factor(self.flow_mol_phase_comp['Liq', j]) is None: sf = iscale.get_scaling_factor(self.flow_mol_phase_comp['Liq', j], default=1, warning=True) iscale.set_scaling_factor(self.flow_mol_phase_comp['Liq', j], sf) # scaling factors for parameters for j, v in self.mw_comp.items(): if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(self.mw_comp[j], 1e1) for ind, v in self.diffus_phase_comp.items(): if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(self.diffus_phase_comp[ind], 1e10) for p, v in self.dens_mass_phase.items(): if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(self.dens_mass_phase[p], 1e-2) for p, v in self.visc_d_phase.items(): if iscale.get_scaling_factor(v) is None: iscale.set_scaling_factor(self.visc_d_phase[p], 1e3) if self.is_property_constructed('mole_frac_phase_comp'): for j in self.params.component_list: if iscale.get_scaling_factor(self.mole_frac_phase_comp['Liq', j]) is None: if j == 'H2O': iscale.set_scaling_factor(self.mole_frac_phase_comp['Liq', j], 1) else: sf = (iscale.get_scaling_factor(self.flow_mol_phase_comp['Liq', j]) / iscale.get_scaling_factor(self.flow_mol_phase_comp['Liq', 'H2O'])) iscale.set_scaling_factor(self.mole_frac_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_dens = iscale.get_scaling_factor(self.dens_mass_phase['Liq']) sf = (sf_dens * iscale.get_scaling_factor(self.mole_frac_phase_comp['Liq', j], default=1) / iscale.get_scaling_factor(self.mw_comp[j])) iscale.set_scaling_factor(self.conc_mol_phase_comp['Liq', j], sf) if self.is_property_constructed('flow_mass_phase_comp'): for j in self.params.component_list: if iscale.get_scaling_factor(self.flow_mass_phase_comp['Liq', j]) is None: sf = iscale.get_scaling_factor(self.flow_mol_phase_comp['Liq', j], default=1) sf *= iscale.get_scaling_factor(self.mw_comp[j]) iscale.set_scaling_factor(self.flow_mass_phase_comp['Liq', j], 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('pressure_osm'): if iscale.get_scaling_factor(self.pressure_osm) is None: sf = iscale.get_scaling_factor(self.pressure) iscale.set_scaling_factor(self.pressure_osm, sf) if self.is_property_constructed('mass_frac_phase_comp'): for j in self.params.component_list: comp = self.params.get_component(j) if iscale.get_scaling_factor(self.mass_frac_phase_comp['Liq', j]) is None: if comp.is_solute(): sf = (iscale.get_scaling_factor(self.flow_mass_phase_comp['Liq', j], default=1) / iscale.get_scaling_factor(self.flow_mass_phase_comp['Liq', 'H2O'], default=1)) iscale.set_scaling_factor(self.mass_frac_phase_comp['Liq', j], sf) elif comp.is_solvent(): iscale.set_scaling_factor(self.mass_frac_phase_comp['Liq', j], 100) else: raise TypeError(f'comp={comp}, j = {j}') if self.is_property_constructed('flow_vol_phase'): sf = (iscale.get_scaling_factor(self.flow_mol_phase_comp['Liq', 'H2O'], default=1) * iscale.get_scaling_factor(self.mw_comp[j]) / iscale.get_scaling_factor(self.dens_mass_phase['Liq'])) iscale.set_scaling_factor(self.flow_vol_phase, sf) if self.is_property_constructed('flow_vol'): sf = iscale.get_scaling_factor(self.flow_vol_phase) iscale.set_scaling_factor(self.flow_vol, sf) if self.is_property_constructed('conc_mass_phase_comp'): for j in self.params.component_list: sf_dens = iscale.get_scaling_factor(self.dens_mass_phase['Liq']) if iscale.get_scaling_factor(self.conc_mass_phase_comp['Liq', j]) is None: if j == 'H2O': # solvents typically have a mass fraction between 0.5-1 iscale.set_scaling_factor(self.conc_mass_phase_comp['Liq', j], sf_dens) else: iscale.set_scaling_factor( self.conc_mass_phase_comp['Liq', j], sf_dens * iscale.get_scaling_factor(self.mass_frac_phase_comp['Liq', j],default=1,warning=True)) if self.is_property_constructed('molality_comp'): for j in self.params.solute_set: if iscale.get_scaling_factor(self.molality_comp[j]) is None: sf = (iscale.get_scaling_factor(self.flow_mol_phase_comp['Liq', j]) / iscale.get_scaling_factor(self.flow_mol_phase_comp['Liq', 'H2O']) / iscale.get_scaling_factor(self.mw_comp[j])) iscale.set_scaling_factor(self.molality_comp[j], sf) if self.is_property_constructed('act_coeff_phase_comp'): for j in self.params.solute_set: if iscale.get_scaling_factor(self.act_coeff_phase_comp['Liq', j]) is None: iscale.set_scaling_factor(self.act_coeff_phase_comp['Liq', j], 1) # transforming constraints # property relationships with no index, simple constraint if self.is_property_constructed('pressure_osm'): sf = iscale.get_scaling_factor(self.pressure_osm, default=1, warning=True) iscale.constraint_scaling_transform(self.eq_pressure_osm, sf) # # property relationships with phase index, but simple constraint for v_str in ('flow_vol_phase', 'dens_mass_phase'): if self.is_property_constructed(v_str): v = getattr(self, v_str) sf = iscale.get_scaling_factor(v['Liq'], default=1, warning=True) c = getattr(self, 'eq_' + v_str) iscale.constraint_scaling_transform(c, sf) # property relationship indexed by component v_str_lst_comp = ['molality_comp'] for v_str in v_str_lst_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[j], default=1, warning=True) iscale.constraint_scaling_transform(c, sf) # property relationships indexed by component and phase v_str_lst_phase_comp = ['mass_frac_phase_comp', 'conc_mass_phase_comp', 'flow_mass_phase_comp', 'mole_frac_phase_comp', 'conc_mol_phase_comp', 'act_coeff_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 calculate_scaling_factors(self): for t, c in self.heat_transfer_correlation.items(): sf = iscale.get_scaling_factor( self.heat_duty[t], default=1, warning=True) iscale.constraint_scaling_transform(c, sf)
def calculate_scaling_factors(self): super().calculate_scaling_factors() if hasattr(self, "work_fluid"): for t, v in self.work_fluid.items(): iscale.set_scaling_factor( v, iscale.get_scaling_factor(self.control_volume.work[t], default=1, warning=True)) if hasattr(self, "work_mechanical"): for t, v in self.work_mechanical.items(): iscale.set_scaling_factor( v, iscale.get_scaling_factor(self.control_volume.work[t], default=1, warning=True)) if hasattr(self, "work_isentropic"): for t, v in self.work_isentropic.items(): iscale.set_scaling_factor( v, iscale.get_scaling_factor(self.control_volume.work[t], default=1, warning=True)) if hasattr(self, "ratioP_calculation"): for t, c in self.ratioP_calculation.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor( self.control_volume.properties_in[t].pressure, default=1, warning=True), overwrite=False) if hasattr(self, "fluid_work_calculation"): for t, c in self.fluid_work_calculation.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.control_volume.deltaP[t], default=1, warning=True), overwrite=False) if hasattr(self, "actual_work"): for t, c in self.actual_work.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.control_volume.work[t], default=1, warning=True), overwrite=False) if hasattr(self, "isentropic_pressure"): for t, c in self.isentropic_pressure.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor( self.control_volume.properties_in[t].pressure, default=1, warning=True), overwrite=False) if hasattr(self, "isentropic"): for t, c in self.isentropic.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor( self.control_volume.properties_in[t].entr_mol, default=1, warning=True), overwrite=False) if hasattr(self, "isentropic_energy_balance"): for t, c in self.isentropic_energy_balance.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.control_volume.work[t], default=1, warning=True), overwrite=False) if hasattr(self, "zero_work_equation"): for t, c in self.zero_work_equation.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.control_volume.work[t], default=1, warning=True)) if hasattr(self, "state_material_balances"): cvol = self.control_volume phase_list = cvol.properties_in.phase_list phase_component_set = cvol.properties_in.phase_component_set mb_type = cvol._constructed_material_balance_type if mb_type == MaterialBalanceType.componentPhase: for (t, p, j), c in self.state_material_balances.items(): sf = iscale.get_scaling_factor( cvol.properties_in[t].get_material_flow_terms(p, j), default=1, warning=True) iscale.constraint_scaling_transform(c, sf) elif mb_type == MaterialBalanceType.componentTotal: for (t, j), c in self.state_material_balances.items(): sf = iscale.min_scaling_factor([ cvol.properties_in[t].get_material_flow_terms(p, j) for p in phase_list if (p, j) in phase_component_set ]) iscale.constraint_scaling_transform(c, sf) else: # There are some other material balance types but they create # constraints with different names. _log.warning(f"Unknown material balance type {mb_type}") if hasattr(self, "costing"): # import costing scaling factors costing.calculate_scaling_factors(self.costing)
def build_tb(m): # build translator block m.fs.tb_pretrt_to_desal = Translator( default={ "inlet_property_package": m.fs.stoich_softening_thermo_params, "outlet_property_package": m.fs.prop_TDS, }) blk = m.fs.tb_pretrt_to_desal # add translator block constraints blk.eq_equal_temperature = Constraint(expr=blk.properties_in[0].temperature == blk.properties_out[0].temperature) blk.eq_equal_pressure = Constraint( expr=blk.properties_in[0].pressure == blk.properties_out[0].pressure) blk.eq_H2O_balance = Constraint( expr=blk.properties_in[0].flow_mol * blk.properties_in[0].mole_frac_comp["H2O"] == blk.properties_out[0].flow_mol_phase_comp["Liq", "H2O"]) mw_comp = { "H2O": 18.015e-3, "Na": 22.990e-3, "Ca": 40.078e-3, "Mg": 24.305e-3, "SO4": 96.06e-3, "Cl": 35.453e-3, } # TODO: this does not catch the Cl that is not associated with with Na blk.eq_TDS_balance = Constraint( expr=blk.properties_out[0].flow_mass_phase_comp[ "Liq", "TDS"] == blk.properties_in[0].flow_mol * blk.properties_in[0].mole_frac_comp["Ca(HCO3)2"] * mw_comp["Ca"] + blk.properties_in[0].flow_mol * blk.properties_in[0].mole_frac_comp["Mg(HCO3)2"] * mw_comp["Mg"] + blk.properties_in[0].flow_mol * blk.properties_in[0].mole_frac_comp["NaCl"] * (mw_comp["Na"] + mw_comp["Cl"]) + blk.properties_in[0].flow_mol * blk.properties_in[0].mole_frac_comp["Cl_-"] * mw_comp["Cl"] + blk.properties_in[0].flow_mol * blk.properties_in[0].mole_frac_comp["SO4_2-"] * mw_comp["SO4"]) # scale translator block to get scaling factors calculate_scaling_factors(blk) constraint_scaling_transform( blk.eq_equal_temperature, get_scaling_factor(blk.properties_out[0].temperature)) constraint_scaling_transform( blk.eq_equal_pressure, get_scaling_factor(blk.properties_out[0].pressure)) constraint_scaling_transform( blk.eq_H2O_balance, get_scaling_factor(blk.properties_out[0].flow_mol_phase_comp["Liq", "H2O"]), ) constraint_scaling_transform( blk.eq_TDS_balance, get_scaling_factor(blk.properties_out[0].flow_mass_phase_comp["Liq", "TDS"]), ) # touch variables blk.properties_out[0].mass_frac_phase_comp
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() # for the following variables: flow_mass_phase_comp, pressure, # temperature, dens_mass, visc_d, diffus, osm_coeff, and enth_mass # 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=1e0, 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', 'NaCl']) is None: sf = iscale.get_scaling_factor(self.flow_mass_phase_comp['Liq', 'NaCl'], default=1e2, warning=True) iscale.set_scaling_factor(self.flow_mass_phase_comp['Liq', 'NaCl'], sf) # 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, 1e2) # these variables do not typically require user input, # will not override if the user does provide the scaling factor if self.is_property_constructed('pressure_osm'): if iscale.get_scaling_factor(self.pressure_osm) is None: iscale.set_scaling_factor( self.pressure_osm, iscale.get_scaling_factor(self.pressure)) 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 == 'NaCl': 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) elif j == 'H2O': iscale.set_scaling_factor( self.mass_frac_phase_comp['Liq', j], 100) if self.is_property_constructed('flow_vol_phase'): sf = (iscale.get_scaling_factor(self.flow_mass_phase_comp['Liq', 'H2O']) / iscale.get_scaling_factor(self.dens_mass_phase['Liq'])) iscale.set_scaling_factor(self.flow_vol_phase, sf) if self.is_property_constructed('flow_vol'): sf = iscale.get_scaling_factor(self.flow_vol_phase) iscale.set_scaling_factor(self.flow_vol, sf) if self.is_property_constructed('conc_mass_phase_comp'): for j in self.params.component_list: sf_dens = iscale.get_scaling_factor( self.dens_mass_phase['Liq']) if iscale.get_scaling_factor( self.conc_mass_phase_comp['Liq', j]) is None: if j == 'H2O': # solvents typically have a mass fraction between 0.5-1 iscale.set_scaling_factor( self.conc_mass_phase_comp['Liq', j], sf_dens) elif j == 'NaCl': iscale.set_scaling_factor( self.conc_mass_phase_comp['Liq', j], sf_dens * iscale.get_scaling_factor( self.mass_frac_phase_comp['Liq', j])) 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]) sf /= 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('mole_frac_phase_comp'): for j in self.params.component_list: if iscale.get_scaling_factor( self.mole_frac_phase_comp['Liq', j]) is None: if j == 'NaCl': sf = (iscale.get_scaling_factor( self.flow_mol_phase_comp['Liq', j]) / iscale.get_scaling_factor( self.flow_mol_phase_comp['Liq', 'H2O'])) iscale.set_scaling_factor( self.mole_frac_phase_comp['Liq', j], sf) elif j == 'H2O': iscale.set_scaling_factor( self.mole_frac_phase_comp['Liq', j], 1) if self.is_property_constructed('molality_comp'): for j in self.params.component_list: if isinstance(getattr(self.params, j), Solute): if iscale.get_scaling_factor( self.molality_comp[j]) is None: sf = iscale.get_scaling_factor( self.mass_frac_phase_comp['Liq', j]) sf /= iscale.get_scaling_factor(self.params.mw_comp[j]) iscale.set_scaling_factor(self.molality_comp[j], sf) if self.is_property_constructed('enth_flow'): iscale.set_scaling_factor( self.enth_flow, iscale.get_scaling_factor(self.flow_mass_phase_comp['Liq', 'H2O']) * iscale.get_scaling_factor(self.enth_mass_phase['Liq'])) # transforming constraints if self.is_property_constructed('pressure_osm'): sf = iscale.get_scaling_factor(self.pressure_osm, default=1, warning=True) iscale.constraint_scaling_transform(self.eq_pressure_osm, sf) if self.is_property_constructed('osm_coeff'): sf = iscale.get_scaling_factor(self.osm_coeff, default=1, warning=True) iscale.constraint_scaling_transform(self.eq_osm_coeff, sf) # property relationships with phase index, but simple constraint for v_str in ('visc_d_phase', 'enth_mass_phase', 'flow_vol_phase', 'diffus_phase'): if self.is_property_constructed(v_str): sf = iscale.get_scaling_factor(self.component(v_str)['Liq'], default=1, warning=True) iscale.constraint_scaling_transform( self.component('eq_' + v_str), sf) if self.is_property_constructed('dens_mass_phase'): sf = iscale.get_scaling_factor(self.dens_mass_phase['Liq']) iscale.constraint_scaling_transform(self.eq_dens_mass_phase, sf) # property relationship indexed by component if self.is_property_constructed('molality_comp'): for j, c in self.eq_molality_comp.items(): sf = iscale.get_scaling_factor(self.molality_comp[j], default=1, warning=True) iscale.constraint_scaling_transform(c, sf) # property relationships indexed by component and phase for v_str in ('mass_frac_phase_comp', 'conc_mass_phase_comp', 'flow_mol_phase_comp', 'mole_frac_phase_comp'): if self.is_property_constructed(v_str): v_comp = self.component(v_str) for j, c in self.component('eq_' + v_str).items(): sf = iscale.get_scaling_factor(v_comp['Liq', j], default=1, warning=True) iscale.constraint_scaling_transform(c, sf)
def test_propogate_indexed_scaling(): m = pyo.ConcreteModel() m.b = pyo.Block() m.a = pyo.Var() m.x = pyo.Var([1, 2, 3], initialize=1e6) m.y = pyo.Var([1, 2, 3], initialize=1e-8) m.z = pyo.Var([1, 2, 3], initialize=1e-20) @m.Constraint([1, 2, 3]) def c1(b, i): return m.x[i] == 0 @m.Constraint([1, 2, 3]) def c2(b, i): return m.y[i] == 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) sc.set_scaling_factor(m.a, 104) sc.set_scaling_factor(m.b.c1, 14) # Set sufix directly since set_scaling_factor also sets data objects m.scaling_factor[m.x] = 11 m.scaling_factor[m.y] = 13 m.b.scaling_factor[m.b.w] = 16 m.scaling_factor[m.c1] = 14 for i in [1, 2, 3]: assert sc.get_scaling_factor(m.x[i]) is None assert sc.get_scaling_factor(m.y[i]) is None assert sc.get_scaling_factor(m.z[i]) is None assert sc.get_scaling_factor(m.b.w[i]) is None assert sc.get_scaling_factor(m.c1[i]) is None assert sc.get_scaling_factor(m.c2[i]) is None assert sc.get_scaling_factor(m.x) == 11 assert sc.get_scaling_factor(m.y) == 13 assert sc.get_scaling_factor(m.z) is None assert sc.get_scaling_factor(m.b.w) == 16 assert sc.get_scaling_factor(m.c1) == 14 assert sc.get_scaling_factor(m.c2) is None sc.propagate_indexed_component_scaling_factors(m) for i in [1, 2, 3]: assert sc.get_scaling_factor(m.x[i]) is 11 assert sc.get_scaling_factor(m.y[i]) is 13 assert sc.get_scaling_factor(m.z[i]) is None assert sc.get_scaling_factor(m.b.w[i]) is 16 assert sc.get_scaling_factor(m.c1[i]) is 14 assert sc.get_scaling_factor(m.c2[i]) is None
def calculate_scaling_factors(b): sf_flow = iscale.get_scaling_factor(b.flow_mol, default=1, warning=True) sf_h = iscale.get_scaling_factor(b.enth_mol, default=1, warning=True) sf_mf = iscale.get_scaling_factor(b.mole_frac_phase_comp, default=1e3, warning=True) for j in b.component_list: sf_j = iscale.get_scaling_factor(b.mole_frac_comp[j], default=1e3, warning=True) iscale.constraint_scaling_transform(b.mole_frac_comp_eq[j], sf_j) iscale.constraint_scaling_transform(b.enth_mol_eq, sf_h) if len(b.phase_list) == 1: iscale.constraint_scaling_transform(b.total_flow_balance, sf_flow) for j in b.component_list: sf_j = iscale.get_scaling_factor(b.mole_frac_comp[j], default=1e3, warning=True) iscale.constraint_scaling_transform(b.component_flow_balances[j], sf_j) # b.phase_fraction_constraint is well scaled elif len(b.phase_list) == 2: iscale.constraint_scaling_transform(b.total_flow_balance, sf_flow) for j in b.component_list: iscale.constraint_scaling_transform(b.component_flow_balances[j], sf_flow) iscale.constraint_scaling_transform(b.sum_mole_frac, sf_mf) for p in b.phase_list: sf_p = iscale.get_scaling_factor(b.phase_frac[p], default=1, warning=True) iscale.constraint_scaling_transform(b.phase_fraction_constraint[p], sf_p * sf_flow) else: for j in b.component_list: sf_fc = iscale.get_scaling_factor(b.flow_mol_comp[j], default=1, warning=True) iscale.constraint_scaling_transform(b.component_flow_balances[j], sf_fc) for p in b.phase_list: sf_fp = iscale.get_scaling_factor(b.flow_mol_phase[p], default=1, warning=True) iscale.constraint_scaling_transform(b.sum_mole_frac[p], sf_mf) iscale.constraint_scaling_transform(b.phase_fraction_constraint[p], sf_fp) if b.params._electrolyte: calculate_electrolyte_scaling(b)
def test_set_get_unset(caplog): """Make sure the Jacobian from Pynumero matches expectation. This is mostly to ensure we understand the interface and catch if things change. """ m = pyo.ConcreteModel() m.x = pyo.Var() m.z = pyo.Var([1, 2, 3, 4]) m.c1 = pyo.Constraint(expr=0 == m.x) @m.Constraint([1, 2, 3, 4]) def c2(b, i): return b.z[i] == 0 m.ex = pyo.Expression(expr=m.x) sc.set_scaling_factor(m.z, 10) assert sc.get_scaling_factor(m.z) == 10 assert sc.get_scaling_factor(m.z[1]) == 10 assert sc.get_scaling_factor(m.z[2]) == 10 assert sc.get_scaling_factor(m.z[3]) == 10 assert sc.get_scaling_factor(m.z[4]) == 10 sc.unset_scaling_factor(m.z) assert sc.get_scaling_factor(m.z) is None assert sc.get_scaling_factor(m.z[1]) is None assert sc.get_scaling_factor(m.z[2]) is None assert sc.get_scaling_factor(m.z[3]) is None assert sc.get_scaling_factor(m.z[4]) is None sc.set_scaling_factor(m.z, 10, data_objects=False) assert sc.get_scaling_factor(m.z) == 10 assert sc.get_scaling_factor(m.z[1]) is None assert sc.get_scaling_factor(m.z[2]) is None assert sc.get_scaling_factor(m.z[3]) is None assert sc.get_scaling_factor(m.z[4]) is None sc.set_scaling_factor(m.z, 10) sc.unset_scaling_factor(m.z, data_objects=False) assert sc.get_scaling_factor(m.z) is None assert sc.get_scaling_factor(m.z[1]) == 10 assert sc.get_scaling_factor(m.z[2]) == 10 assert sc.get_scaling_factor(m.z[3]) == 10 assert sc.get_scaling_factor(m.z[4]) == 10 sc.unset_scaling_factor(m.z) caplog.set_level(logging.WARNING) caplog.clear() assert sc.get_scaling_factor(m.z[1], warning=True) is None assert sc.get_scaling_factor(m.z[1], warning=True, default=1) == 1 for i in [0, 1]: # two calls should be two log records logrec = caplog.records[i] assert logrec.levelno == logging.WARNING assert "missing scaling factor" in logrec.message # This one is a bit of a mystery, what do you really expect if you provide # a default and ask for an exception. I'll guess if you provide a default, # your don't really want an exception. assert sc.get_scaling_factor(m.z[1], exception=True, default=1) == 1 caplog.clear() with pytest.raises(KeyError): sc.get_scaling_factor(m.z[1], exception=True) logrec = caplog.records[0] assert logrec.levelno == logging.ERROR assert "missing scaling factor" in logrec.message # Okay it's pretty well tested, but make sure it works for constraints and # expressions sc.set_scaling_factor(m.x, 11) sc.set_scaling_factor(m.ex, 2) sc.set_scaling_factor(m.c1, 3) sc.set_scaling_factor(m.c2, 4) assert sc.get_scaling_factor(m.x) == 11 assert sc.get_scaling_factor(m.ex) == 2 assert sc.get_scaling_factor(m.c1) == 3 assert sc.get_scaling_factor(m.c2) == 4 assert sc.get_scaling_factor(m.c2[1]) == 4 assert sc.get_scaling_factor(m.c2[2]) == 4 assert sc.get_scaling_factor(m.c2[3]) == 4 assert sc.get_scaling_factor(m.c2[4]) == 4 # Check the underlying suffix assert m.scaling_factor[m.x] == 11 assert m.scaling_factor[m.ex] == 2 assert m.scaling_factor[m.c1] == 3 assert m.scaling_factor[m.c2] == 4 assert m.scaling_factor[m.c2[1]] == 4 assert m.scaling_factor[m.c2[2]] == 4 assert m.scaling_factor[m.c2[3]] == 4 assert m.scaling_factor[m.c2[4]] == 4
def calculate_scaling_factors(self): super().calculate_scaling_factors() # scaling factors for parameters 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', 'TSS']) is None: sf = iscale.get_scaling_factor(self.flow_mass_phase_comp['Liq', 'TSS'], default=1e2, warning=True) iscale.set_scaling_factor(self.flow_mass_phase_comp['Liq', 'TSS'], sf) if iscale.get_scaling_factor(self.flow_mass_phase_comp['Liq', 'TDS']) is None: sf = iscale.get_scaling_factor(self.flow_mass_phase_comp['Liq', 'TDS'], default=1e2, warning=True) iscale.set_scaling_factor(self.flow_mass_phase_comp['Liq', 'TDS'], sf) if iscale.get_scaling_factor( self.flow_mass_phase_comp['Liq', 'Sludge']) is None: sf = iscale.get_scaling_factor(self.flow_mass_phase_comp['Liq', 'Sludge'], default=1e3, warning=True) iscale.set_scaling_factor( self.flow_mass_phase_comp['Liq', 'Sludge'], 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'): #Apply variable scaling for pair in self.seawater_mass_frac_dict.keys(): if iscale.get_scaling_factor( self.mass_frac_phase_comp[pair]) is None: if pair[1] == 'H2O': iscale.set_scaling_factor( self.mass_frac_phase_comp[pair], 1) else: sf = (iscale.get_scaling_factor( self.flow_mass_phase_comp[pair]) / iscale.get_scaling_factor( self.flow_mass_phase_comp['Liq', 'H2O'])) iscale.set_scaling_factor( self.mass_frac_phase_comp[pair], sf) #Apply constraint scaling for pair in self.seawater_mass_frac_dict.keys(): sf = iscale.get_scaling_factor(self.mass_frac_phase_comp[pair], default=1, warning=True) iscale.constraint_scaling_transform( self.eq_mass_frac_phase_comp[pair], sf) if self.is_property_constructed('dens_mass_phase'): if iscale.get_scaling_factor(self.dens_mass_phase) is None: iscale.set_scaling_factor(self.dens_mass_phase, 1e-3) # transforming constraints sf = iscale.get_scaling_factor(self.dens_mass_phase) iscale.constraint_scaling_transform(self.eq_dens_mass_phase['Liq'], sf) if self.is_property_constructed('flow_vol_phase'): sf = (iscale.get_scaling_factor(self.flow_mass_phase_comp['Liq', 'H2O']) / iscale.get_scaling_factor(self.dens_mass_phase['Liq'])) iscale.set_scaling_factor(self.flow_vol_phase['Liq'], sf) # transforming constraints iscale.constraint_scaling_transform(self.eq_flow_vol_phase['Liq'], sf) if self.is_property_constructed('conc_mass_phase_comp'): #Apply variable scaling for pair in self.seawater_mass_frac_dict.keys(): if iscale.get_scaling_factor( self.conc_mass_phase_comp[pair]) is None: if pair[0] == 'Liq': sf = (iscale.get_scaling_factor( self.mass_frac_phase_comp[pair]) * iscale.get_scaling_factor( self.dens_mass_phase['Liq'])) iscale.set_scaling_factor( self.conc_mass_phase_comp[pair], sf) else: raise PropertyPackageError( "Unsupported phase for CoagulationParameterData property package" ) #Apply constraint scaling for pair in self.seawater_mass_frac_dict.keys(): sf = iscale.get_scaling_factor(self.conc_mass_phase_comp[pair], default=1, warning=True) iscale.constraint_scaling_transform( self.eq_conc_mass_phase_comp[pair], 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) iscale.set_scaling_factor(self.enth_flow, sf)
def calculate_scaling_factors(self): super().calculate_scaling_factors() # Get some scale factors that are frequently used to calculate others sf_flow = iscale.get_scaling_factor(self.flow_mol) sf_mol_fraction = {} comps = self.params.component_list for i in comps: sf_mol_fraction[i] = iscale.get_scaling_factor( self.mole_frac_comp[i]) # calculate flow_mol_comp scale factors for i, c in self.flow_mol_comp.items(): iscale.set_scaling_factor(c, sf_flow * sf_mol_fraction[i]) if self.is_property_constructed("energy_density_terms"): for i, c in self.energy_density_terms.items(): sf1 = iscale.get_scaling_factor(self.enth_mol_phase[i]) sf2 = iscale.get_scaling_factor(self.dens_mol_phase[i]) iscale.set_scaling_factor(c, sf1 * sf2) if self.is_property_constructed("enthalpy_flow_terms"): for i, c in self.enthalpy_flow_terms.items(): sf1 = iscale.get_scaling_factor(self.enth_mol_phase[i]) sf2 = iscale.get_scaling_factor(self.flow_mol) iscale.set_scaling_factor(c, sf1 * sf2) if self.is_property_constructed("heat_cap_correlation"): iscale.constraint_scaling_transform( self.heat_cap_correlation, iscale.get_scaling_factor(self.cp_mol) * iscale.get_scaling_factor(self.flow_mol)) if self.is_property_constructed("enthalpy_correlation"): for p, c in self.enthalpy_correlation.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.enth_mol) * iscale.get_scaling_factor(self.flow_mol)) if self.is_property_constructed("entropy_correlation"): iscale.constraint_scaling_transform( self.entropy_correlation, iscale.get_scaling_factor(self.entr_mol) * iscale.get_scaling_factor(self.flow_mol)) if self.is_property_constructed("vapor_pressure_correlation"): iscale.constraint_scaling_transform( self.vapor_pressure_correlation, log(iscale.get_scaling_factor(self.pressure_sat)) * iscale.get_scaling_factor(self.flow_mol)) if self.is_property_constructed("therm_cond_con"): for i, c in self.therm_cond_con.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.therm_cond_comp[i])) if self.is_property_constructed("therm_mix_con"): iscale.constraint_scaling_transform( self.therm_mix_con, iscale.get_scaling_factor(self.therm_cond)) if self.is_property_constructed("visc_d_con"): for i, c in self.visc_d_con.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.visc_d_comp[i])) if self.is_property_constructed("visc_d_mix_con"): iscale.constraint_scaling_transform( self.visc_d_mix_con, iscale.get_scaling_factor(self.visc_d))
def calculate_scaling_factors(self): super().calculate_scaling_factors() iscale.set_scaling_factor( self.crystal_growth_rate, 1e7) # growth rates typically of order 1e-7 to 1e-9 m/s iscale.set_scaling_factor(self.crystal_median_length, 1e3) # Crystal lengths typically in mm iscale.set_scaling_factor( self.souders_brown_constant, 1e2) # Typical values are 0.0244, 0.04 and 0.06 iscale.set_scaling_factor( self.diameter_crystallizer, 1) # Crystallizer diameters typically up to about 20 m iscale.set_scaling_factor( self.height_crystallizer, 1) # H/D ratio maximum is about 1.5, so same scaling as diameter iscale.set_scaling_factor(self.height_slurry, 1) # Same scaling as diameter iscale.set_scaling_factor(self.magma_circulation_flow_vol, 1) iscale.set_scaling_factor(self.relative_supersaturation, 10) iscale.set_scaling_factor(self.t_res, 1) # Residence time is in hours iscale.set_scaling_factor( self.volume_suspension, 0.1) # Suspension volume usually in tens to hundreds range iscale.set_scaling_factor( self.crystallization_yield, 1) # Yield is between 0 and 1, usually in the 10-60% range iscale.set_scaling_factor(self.product_volumetric_solids_fraction, 10) iscale.set_scaling_factor( self.temperature_operating, iscale.get_scaling_factor(self.properties_in[0].temperature), ) iscale.set_scaling_factor(self.pressure_operating, 1e-3) iscale.set_scaling_factor( self.dens_mass_magma, 1e-3) # scaling factor of dens_mass_phase['Liq'] iscale.set_scaling_factor( self.dens_mass_slurry, 1e-3) # scaling factor of dens_mass_phase['Liq'] iscale.set_scaling_factor( self.work_mechanical[0], iscale.get_scaling_factor( self.properties_in[0].flow_mass_phase_comp["Vap", "H2O"]) * iscale.get_scaling_factor( self.properties_in[0].enth_mass_solvent["Vap"]), ) # transforming constraints for ind, c in self.eq_T_con1.items(): sf = iscale.get_scaling_factor(self.properties_in[0].temperature) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_T_con2.items(): sf = iscale.get_scaling_factor(self.properties_in[0].temperature) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_T_con3.items(): sf = iscale.get_scaling_factor(self.properties_in[0].temperature) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_p_con1.items(): sf = iscale.get_scaling_factor(self.properties_in[0].pressure) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_p_con2.items(): sf = iscale.get_scaling_factor(self.properties_in[0].pressure) iscale.constraint_scaling_transform(c, sf) for ind, c in self.eq_p_con3.items(): sf = iscale.get_scaling_factor(self.properties_in[0].pressure) iscale.constraint_scaling_transform(c, sf) for j, c in self.eq_mass_balance_constraints.items(): sf = iscale.get_scaling_factor( self.properties_in[0].flow_mass_phase_comp["Liq", j]) iscale.constraint_scaling_transform(c, sf) for j, c in self.eq_solubility_massfrac_equality_constraint.items(): iscale.constraint_scaling_transform(c, 1e0) for j, c in self.eq_dens_magma.items(): iscale.constraint_scaling_transform( c, iscale.get_scaling_factor(self.dens_mass_magma)) for j, c in self.eq_removal_balance.items(): sf = iscale.get_scaling_factor( self.properties_in[0].flow_mass_phase_comp["Liq", j]) iscale.constraint_scaling_transform(c, sf)
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)