def return_expression(b, rblock, r_idx, T): e = None s = None if hasattr(b.params, "_electrolyte") and b.params._electrolyte: pc_set = b.params.true_phase_component_set else: pc_set = b.phase_component_set # Get reaction orders and construct power law expression for p, j in pc_set: p_obj = b.state_ref.params.get_phase(p) # First, build E o = rblock.reaction_order[p, j] if e is None and o.value != 0: e = get_concentration_term(b, r_idx)[p, j]**o elif e is not None and o.value != 0: e = e * get_concentration_term(b, r_idx)[p, j]**o if p_obj.is_solid_phase(): # If solid phase, identify S r_config = b.params.config.equilibrium_reactions[r_idx] try: stoic = r_config.stoichiometry[p, j] if s is None and stoic != 0: s = b.state_ref.flow_mol_phase_comp[p, j] elif s is not None and stoic != 0: s += b.state_ref.flow_mol_phase_comp[p, j] except KeyError: pass if s is None: # Catch for not finding a solid phase raise ConfigurationError( "{} did not find a solid phase component for precipitation " "reaction {}. This is likely due to the reaction " "configuration.".format(b.name, r_idx)) else: # Need to remove units as complementarity is not consistent sunits = pyunits.get_units(s) if sunits is not None: s = s / sunits Q = b.k_eq[r_idx] - e # Need to remove units again Qunits = pyunits.get_units(b.k_eq[r_idx]) if Qunits is not None: Q = Q / Qunits return s - smooth_max(0, s - Q, rblock.eps) == 0
def delta_temperature_underwood_callback(b): r""" This is a callback for a temperature difference expression to calculate :math:`\Delta T` in the heat exchanger model using log-mean temperature difference (LMTD) approximation given by Underwood (1970). It can be supplied to "delta_temperature_callback" HeatExchanger configuration option. This uses a cube root function that works with negative numbers returning the real negative root. This should always evaluate successfully. This form is .. math:: \Delta T = \left(\frac{ \Delta T_1^\frac{1}{3} + \Delta T_2^\frac{1}{3}}{2}\right)^3 where :math:`\Delta T_1` is the temperature difference at the hot inlet end and :math:`\Delta T_2` is the temperature difference at the hot outlet end. """ dT1 = b.delta_temperature_in dT2 = b.delta_temperature_out temp_units = pyunits.get_units(dT1[dT1.index_set().first()]) # external function that ruturns the real root, for the cuberoot of negitive # numbers, so it will return without error for positive and negitive dT. b.cbrt = ExternalFunction(library=functions_lib(), function="cbrt", arg_units=[temp_units]) @b.Expression(b.flowsheet().time) def delta_temperature(b, t): return ((b.cbrt(dT1[t]) + b.cbrt(dT2[t])) / 2.0)**3 * temp_units
def test_module_example(self): from pyomo.environ import ConcreteModel, Var, Objective, units model = ConcreteModel() model.acc = Var() model.obj = Objective(expr=(model.acc * units.m / units.s**2 - 9.81 * units.m / units.s**2)**2) self.assertEqual('m**2/s**4', str(units.get_units(model.obj.expr)))
def return_log_expression(b, rblock, r_idx, T): units = pyunits.get_units(rblock.k_eq_ref) if units is None or units == pyunits.dimensionless: expr = rblock.k_eq_ref else: expr = rblock.k_eq_ref / units return b.log_k_eq[r_idx] == log(expr)
def return_expression(blk, p, j, T): cobj = blk.params.get_component(j) return exp( cobj.diffus_phase_comp_coeff_1 + cobj.diffus_phase_comp_coeff_2 / T + cobj.diffus_phase_comp_coeff_3 * log(blk.visc_d_phase[p] / pyunits.get_units(blk.visc_d_phase[p])) ) * pyunits.m**2 / pyunits.s
def test_cp_mol_phase(build_model): m = build_model assert (str(pyunits.get_units(Cubic.cp_mol_phase( m.props, "Vap"))) == 'kg*m**2/K/mol/s**2') assert (pytest.approx(value(Cubic.cp_mol_phase(m.props, "Vap")), rel=0.1) == data["cp_mol_phase"])
def test_build(self): model = ConcreteModel() model.param = GenericParameterBlock(default=configuration) assert isinstance(model.param.phase_list, Set) assert len(model.param.phase_list) == 2 for i in model.param.phase_list: assert i in ["Liq", "Vap"] assert model.param.Liq.is_liquid_phase() assert model.param.Vap.is_vapor_phase() assert isinstance(model.param.component_list, Set) assert len(model.param.component_list) == 2 for i in model.param.component_list: assert i in ['bmimPF6', 'carbon_dioxide'] assert isinstance(model.param.get_component(i), Component) assert isinstance(model.param._phase_component_set, Set) assert len(model.param._phase_component_set) == 3 for i in model.param._phase_component_set: assert i in [("Liq", "bmimPF6"), ("Liq", "carbon_dioxide"), ("Vap", "carbon_dioxide")] assert model.param.config.state_definition == FTPx assertStructuredAlmostEqual( model.param.config.state_bounds, { "flow_mol": (0, 100, 1000, pyunits.mol/pyunits.s), "temperature": (10, 300, 500, pyunits.K), "pressure": (5e-4, 1e5, 1e10, pyunits.Pa) }, item_callback=lambda x: value(x) * ( pyunits.get_units(x) or pyunits.dimensionless)._get_pint_unit() ) assert model.param.config.phase_equilibrium_state == { ("Vap", "Liq"): SmoothVLE} assert isinstance(model.param.phase_equilibrium_idx, Set) assert len(model.param.phase_equilibrium_idx) == 1 for i in model.param.phase_equilibrium_idx: assert i in ["PE1"] assert model.param.phase_equilibrium_list == { "PE1": {"carbon_dioxide": ("Vap", "Liq")}} assert model.param.pressure_ref.value == 101325 assert model.param.temperature_ref.value == 298.15 assert model.param.bmimPF6.mw.value == 284.18E-3 assert model.param.bmimPF6.pressure_crit.value == 24e5 assert model.param.bmimPF6.temperature_crit.value == 860 assert model.param.carbon_dioxide.mw.value == 44.010E-3 assert model.param.carbon_dioxide.pressure_crit.value == 71.8e5 assert model.param.carbon_dioxide.temperature_crit.value == 304.1 assert_units_consistent(model)
def return_expression(b, rblock, r_idx, T): e = None if hasattr(b.params, "_electrolyte") and b.params._electrolyte: pc_set = b.params.true_phase_component_set else: pc_set = b.phase_component_set # Get reaction orders and construct power law expression for p, j in pc_set: o = rblock.reaction_order[p, j] if e is None and o != 0: # Need to strip units from concentration term (if applicable) c = get_concentration_term(b, r_idx)[p, j] u = pyunits.get_units(c) if u is not None: # Has units, so divide conc by units expr = c / u else: # Units is None, so just use conc expr = c e = o * safe_log(expr, eps=rblock.eps) elif e is not None and o != 0: # Need to strip units from concentration term (if applicable) c = get_concentration_term(b, r_idx)[p, j] u = pyunits.get_units(c) if u is not None: # Has units, so divide conc by units expr = c / u else: # Units is None, so just use conc expr = c e = e + o * safe_log(expr, eps=rblock.eps) # Need to check units on k_eq as well u = pyunits.get_units(b.k_eq[r_idx]) if u is not None: # Has units, so divide k_eq by units expr = b.k_eq[r_idx] / u else: # Units is None, so just use k_eq expr = b.k_eq[r_idx] return safe_log(expr, eps=rblock.eps) == e
def test_isentropic_speed_sound_phase(build_model): m = build_model assert (str( pyunits.get_units(Cubic.isentropic_speed_sound_phase(m.props, "Vap"))) == 'm/s') assert (pytest.approx(value( Cubic.isentropic_speed_sound_phase(m.props, "Vap")), rel=0.1) == data["isentropic_speed_sound_phase"])
def test_heat_capacity_ratio_phase(build_model): m = build_model assert (str( pyunits.get_units(Cubic.heat_capacity_ratio_phase(m.props, "Vap"))) == 'None') assert (pytest.approx(value(Cubic.heat_capacity_ratio_phase( m.props, "Vap")), rel=0.1) == data["heat_capacity_ratio_phase"])
def test_build(self): model = ConcreteModel() model.params = GenericParameterBlock(default=config_dict) assert isinstance(model.params.phase_list, Set) assert len(model.params.phase_list) == 2 for i in model.params.phase_list: assert i in ["Liq", "Vap"] assert model.params.Liq.is_liquid_phase() assert model.params.Vap.is_vapor_phase() assert isinstance(model.params.component_list, Set) assert len(model.params.component_list) == 2 for i in model.params.component_list: assert i in ['benzene', 'toluene'] assert isinstance(model.params.get_component(i), Component) assert isinstance(model.params._phase_component_set, Set) assert len(model.params._phase_component_set) == 4 for i in model.params._phase_component_set: assert i in [("Liq", "benzene"), ("Liq", "toluene"), ("Vap", "benzene"), ("Vap", "toluene")] assert model.params.config.state_definition == FPhx assertStructuredAlmostEqual( model.params.config.state_bounds, { "flow_mol": (0, 100, 1000, pyunits.mol / pyunits.s), "enth_mol": (1e4, 5e4, 2e5, pyunits.J / pyunits.mol), "temperature": (273.15, 300, 450, pyunits.K), "pressure": (5e4, 1e5, 1e6, pyunits.Pa) }, item_callback=lambda x: value(x) * (pyunits.get_units(x) or pyunits.dimensionless)._get_pint_unit()) assert model.params.config.phase_equilibrium_state == { ("Vap", "Liq"): SmoothVLE } assert isinstance(model.params.phase_equilibrium_idx, Set) assert len(model.params.phase_equilibrium_idx) == 2 for i in model.params.phase_equilibrium_idx: assert i in ["PE1", "PE2"] assert model.params.phase_equilibrium_list == { "PE1": { "benzene": ("Vap", "Liq") }, "PE2": { "toluene": ("Vap", "Liq") } } assert model.params.pressure_ref.value == 1e5 assert model.params.temperature_ref.value == 300 assert_units_consistent(model)
def check_units(self): """Check the expr units by exchanging the real model with unit model components :return: None """ self.units = pyo_units.get_units(self.expression) return None
def print_HX_results(blk, exchanger_list): """ Function to print results of Heat Exchangers Args: blk: flowsheet of the equipment exchanger_list: List of equipment to print data Returns: Printed List """ # Initialize dictionary and fill with exchanger list exchangerdict = {} for i, el in enumerate(exchanger_list): exchangerdict[str(el)] = el # initialize null dictionaries for data to be printed Tin_ = {} Tout_ = {} f_ = {} Q_ = {} # Loop over heat exchangers for i in exchangerdict.keys(): Tin_[i] = value( exchangerdict[i].control_volume.properties_in[0].temperature) Tout_[i] = value( exchangerdict[i].control_volume.properties_out[0].temperature) f_[i] = value( exchangerdict[i].control_volume.properties_out[0].flow_mol) Q_[i] = value(exchangerdict[i].control_volume.heat[0]) T_units = pyunits.get_units( exchangerdict[i].control_volume.properties_in[0].temperature) DG_units = pyunits.get_units(exchangerdict[i].heat_duty[0]) # Print the header print("Heat Exchanger Summary: ") # Print Inlet Temperature, Outlet Temperature and Heat for i in exchangerdict.keys(): print("Heat exchanger: ", exchangerdict[i]) print(f'Inlet T: {" "*3} {Tin_[i] : 0.3f} {T_units}') print(f'Outlet T: {" "*2} {Tout_[i] : 0.3f} {T_units}') print(f'Q : {" "*9} {Q_[i]: 0.3f} {DG_units}')
def eq_lmtd(b, t): dT_in = b.delta_temperature_in dT_out = b.delta_temperature_out temp_units = pyunits.get_units(dT_in) dT_avg = (dT_in + dT_out) / 2 # external function that ruturns the real root, for the cuberoot of negitive # numbers, so it will return without error for positive and negitive dT. b.cbrt = ExternalFunction(library=functions_lib(), function="cbrt", arg_units=[temp_units**3]) return b.lmtd == b.cbrt((dT_in * dT_out * dT_avg)) * temp_units
def return_log_expression(b, rblock, r_idx, T): units = rblock.parent_block().get_metadata().derived_units k_units = pyunits.get_units(rblock.k_eq_ref) if (k_units is None or k_units is pyunits.dimensionless): l_keq_ref = log(rblock.k_eq_ref) else: l_keq_ref = log(rblock.k_eq_ref / k_units) return (b.log_k_eq[r_idx] - l_keq_ref) == ( -b.dh_rxn[r_idx] / pyunits.convert(c.gas_constant, to_units=units["gas_constant"]) * (1 / T - 1 / rblock.T_eq_ref))
def check_term(self, term, convert_to): unit_term = pyo_units.get_units(term) _print(f' Units: {unit_term} ==> {convert_to}\n') _changed_flag = False term_new = term if unit_term is not None: _print('Starting conversion and making the new term\n') term_new = pyo_units.convert(term, to_units=getattr( pyo_units, convert_to)) return term_new
def _check_term(term, convert_to): """This loops through terms in the expression to ensure the units are valid :param expression term: The term to check :param str convert_to: The units to convert to, if necessary :return term_new: The updated expression term :rtype: expression """ unit_term = pyo_units.get_units(term) term_new = term if unit_term is not None: term_new = pyo_units.convert(term, to_units=getattr( pyo_units, convert_to)) return term_new
def check_units(self): #, c_mod, c_mod_new): """Check the expr units by exchanging the real model with unit model components Args: key (str): component represented in ODE expr (Expression): Expression object of ODE c_mod (Comp): original Comp object used to declare the expressions c_mod_new (Comp_Check): dummy model with unit components Returns: pint_units (): Returns expression with unit model components """ self.units = pyo_units.get_units(self.expression) return None
def delta_temperature_chen_callback(b): r""" This is a callback for a temperature difference expression to calculate :math:`\Delta T` in the heat exchanger model using log-mean temperature difference (LMTD) approximation given by Chen (1987). It can be supplied to "delta_temperature_callback" HeatExchanger configuration option. This uses a cube root function that works with negative numbers returning the real negative root. This should always evaluate successfully. """ dT1 = b.delta_temperature_in dT2 = b.delta_temperature_out temp_units = pyunits.get_units(dT1) # external function that ruturns the real root, for the cuberoot of negitive # numbers, so it will return without error for positive and negitive dT. b.cbrt = ExternalFunction(library=functions_lib(), function="cbrt", arg_units=[temp_units**3]) @b.Expression(b.flowsheet().time) def delta_temperature(b, t): return b.cbrt(dT1[t] * dT2[t] * 0.5 * (dT1[t] + dT2[t])) * temp_units
def test_build(self): model = ConcreteModel() model.params = GenericParameterBlock(default=configuration) assert isinstance(model.params.phase_list, Set) assert len(model.params.phase_list) == 2 for i in model.params.phase_list: assert i in ["Liq", "Vap"] assert model.params.Liq.is_liquid_phase() assert model.params.Vap.is_vapor_phase() assert isinstance(model.params.component_list, Set) assert len(model.params.component_list) == 2 for i in model.params.component_list: assert i in ['H2O', 'CO2'] assert isinstance(model.params.get_component(i), Component) assert isinstance(model.params._phase_component_set, Set) assert len(model.params._phase_component_set) == 3 for i in model.params._phase_component_set: assert i in [("Liq", "H2O"), ("Vap", "H2O"), ("Vap", "CO2")] assert model.params.config.state_definition == FTPx assertStructuredAlmostEqual( model.params.config.state_bounds, { "flow_mol": (0, 10, 20, pyunits.mol / pyunits.s), "temperature": (273.15, 323.15, 1000, pyunits.K), "pressure": (5e4, 108900, 1e7, pyunits.Pa), "mole_frac_comp": { "H2O": (0, 0.5, 1), "CO2": (0, 0.5, 1) } }, item_callback=lambda x: value(x) * (pyunits.get_units(x) or pyunits.dimensionless)._get_pint_unit()) assert model.params.config.phase_equilibrium_state == { ("Vap", "Liq"): SmoothVLE } assert isinstance(model.params.phase_equilibrium_idx, Set) assert len(model.params.phase_equilibrium_idx) == 1 for i in model.params.phase_equilibrium_idx: assert i in ["PE1"] assert model.params.phase_equilibrium_list == { "PE1": { "H2O": ("Vap", "Liq") } } assert model.params.pressure_ref.value == 101325 assert model.params.temperature_ref.value == 298.15 assert model.params.H2O.mw.value == 18.0153E-3 assert model.params.H2O.pressure_crit.value == 220.64E5 assert model.params.H2O.temperature_crit.value == 647 assert model.params.CO2.mw.value == 44.0095E-3 assert model.params.CO2.pressure_crit.value == 73.825E5 assert model.params.CO2.temperature_crit.value == 304.23 assert_units_consistent(model)
def min_utility(blk, heating, cooling, DTmin, eps=1e-6, DG_units=pyunits.Mwatt): """ Function for Duran-Grossmann for minimization of utilities This function adds variables and constraints to the flowsheet to minimize utilities Args: blk: flowsheet heating: Equipment that requires Heat cooling: Equipment from wich heat is being removed DTmin: HRAT (Heat Recovery Approximation Temperature) eps: Epsilon for smoothing operation Returns: Constraint and variable object representing the calculation for hot utility and cold utility """ # Generate lists out of strings from Args exchanger_list = heating + cooling pinch_streams = exchanger_list # Generate dictionaries out of strings to convert to pyomo objects pinch_streamsdict = {} coolingdict = {} heatingdict = {} exchangerdict = {} for i, el in enumerate(exchanger_list): pinch_streamsdict[str(el)] = el for i, el in enumerate(cooling): coolingdict[str(el)] = el for i, el in enumerate(heating): heatingdict[str(el)] = el for i, el in enumerate(exchanger_list): exchangerdict[str(el)] = el Q = {} for i in exchangerdict: Q[i] = pyunits.convert(pinch_streamsdict[i].heat_duty[0], to_units=DG_units) # Run function to fill exchanger data for pinch calculations for # initialization of variables exchangeData = heat_data(blk, heating, cooling, DG_units) # Call pinch calculation for initialization of variables in PD class PD = pinch_calc(heating, cooling, exchangeData, DTmin, eps) # Define dictionary for addition of DTmin to heating equipment dT = {} for i, el in enumerate(cooling): dT[str(el)] = 0 for i, el in enumerate(heating): dT[str(el)] = DTmin def T_in(blk, i): return pinch_streamsdict[i].control_volume.properties_in[0].temperature blk.Tin = Expression(pinch_streamsdict.keys(), rule=T_in, doc='Inlet temperature in exchangers') def T_out(blk, i): return pinch_streamsdict[i].control_volume.properties_out[ 0].temperature blk.Tout = Expression(pinch_streamsdict.keys(), rule=T_out, doc='Outlet temperature in exchangers') # Expression for cp of equimpent with heat exchange def Theta_(blk, i): if i in heatingdict.keys(): return (Q[i] / (0.5 * ((blk.Tout[i] - blk.Tin[i] + (EpsT)) + sqrt((blk.Tout[i] - blk.Tin[i] - (EpsT))**2 + eps)))) else: return (Q[i] / (-0.5 * ((-(blk.Tout[i] - blk.Tin[i]) - (-EpsT)) + sqrt(( (-EpsT) - (blk.Tout[i] - blk.Tin[i]))**2 + eps)))) blk.Theta = Expression(pinch_streamsdict.keys(), rule=Theta_, doc='FCp in exchangers') # Define expression for pinch candidate temperature def T_(blk, i): return ( pinch_streamsdict[i].control_volume.properties_in[0].temperature + dT[i]) blk.T_ = Expression(pinch_streamsdict.keys(), rule=T_, doc='Pinch candidate temperature') # Define variable for heat content above the pinch point blk.QAh = Var(pinch_streamsdict.keys(), initialize=PD.initQAh, bounds=(1e-8, None), doc='Heat content above pinch', units=pyunits.get_units(Q[str(pinch_streams[0])])) # Define a cpnstraint to calculate the varaible QAh def rule_heat_above_pinch(blk, p): return (blk.QAh[p] == sum( blk.Theta[i] * (0.5 * ((blk.Tin[i] - blk.T_[p]) + sqrt( (blk.Tin[i] - blk.T_[p])**2 + eps)) - 0.5 * ((blk.Tout[i] - blk.T_[p]) + sqrt( (blk.Tout[i] - blk.T_[p])**2 + eps))) for i in coolingdict.keys())) blk.heat_above_pinch = Constraint(pinch_streamsdict.keys(), rule=rule_heat_above_pinch) # Define variable for heat content below the pinch point blk.QAc = Var(pinch_streamsdict.keys(), initialize=PD.initQAc, bounds=(1e-8, None), doc='Heat content bellow pinch', units=pyunits.get_units(Q[str(pinch_streams[0])])) # Define a constraint to calculate the varaible QAc def rule_heat_below_pinch(blk, p): return (blk.QAc[p] == sum( blk.Theta[i] * (0.5 * ((blk.Tout[i] - blk.T_[p] + DTmin) + sqrt( (blk.Tout[i] - blk.T_[p] + DTmin)**2 + eps)) - 0.5 * ((blk.Tin[i] - blk.T_[p] + DTmin) + sqrt( (blk.Tin[i] - blk.T_[p] + DTmin)**2 + eps))) for i in heatingdict.keys())) blk.heat_below_pinch = Constraint(pinch_streamsdict.keys(), rule=rule_heat_below_pinch) # Define variable for Heat of hot utility blk.Qs = Var(initialize=PD.initQs, bounds=(1e-8, None), doc='Heating utilities', units=pyunits.get_units(Q[str(pinch_streams[0])])) # Define a constraint to solve for Qs # Where 1E-6 is added to both sides of the constraint as a scaling factor def rule_heating_utility(blk, p): return (blk.Qs >= (blk.QAc[p] - blk.QAh[p])) blk.heating_utility = Constraint(pinch_streamsdict.keys(), rule=rule_heating_utility) # Define variable for Heat of cold utility blk.Qw = Var(initialize=PD.initQw, bounds=(1e-8, None), doc='Cooling utilities', units=pyunits.get_units(Q[str(pinch_streams[0])])) # Define a constraint to solve for Qw # Where 1E-6 is added to both sides of the constraint as a scaling factor def rule_cooling_utility(blk): return blk.Qw == -sum(Q[i] for i in exchangerdict.keys()) + blk.Qs blk.cooling_utility = Constraint(rule=rule_cooling_utility)
def heat_ex_data(blk, heating, cooling): """ Function for turning IDAES heat exchanging equipment into a class for use in plotting Args: blk: Flowsheet heating: Equipment that heats streams cooling: Equipment that cools streams Returns: CD: Class with heating and cooling equipment as arrays """ # Generate dictionaries out of strings to convert to pyomo objects exchanger_list = heating + cooling pinch_streams = exchanger_list pinch_streamsdict = {} coolingdict = {} heatingdict = {} exchangerdict = {} T_units = pyunits.get_units( pinch_streams[0].control_volume.properties_in[0].temperature) DG_units = pyunits.get_units(blk.Qw) for i, el in enumerate(exchanger_list): pinch_streamsdict[str(el)] = el for i, el in enumerate(cooling): coolingdict[str(el)] = el for i, el in enumerate(heating): heatingdict[str(el)] = el for i, el in enumerate(exchanger_list): exchangerdict[str(el)] = el # Generate zero arrays from length of the cooling list CHX = len(coolingdict) CTin = np.zeros(CHX) CTout = np.zeros(CHX) CQ = np.zeros(CHX) # Convert Pyomo model values into arrays j = 0 for i in coolingdict.keys(): CTin[j] = value( coolingdict[i].control_volume.properties_in[0].temperature) + 1 CTout[j] = value( coolingdict[i].control_volume.properties_out[0].temperature) CQ[j] = value( pyunits.convert(coolingdict[i].control_volume.heat[0], to_units=DG_units)) j += 1 # Generate zero arrays from length of the heating list HHX = len(heatingdict) HTin = np.zeros(HHX) HTout = np.zeros(HHX) HQ = np.zeros(HHX) # Convert Pyomo model values into arrays j = 0 for i in heatingdict.keys(): HTin[j] = value( heatingdict[i].control_volume.properties_in[0].temperature) HTout[j] = value( heatingdict[i].control_volume.properties_out[0].temperature) + 1 HQ[j] = value( pyunits.convert(heatingdict[i].control_volume.heat[0], to_units=DG_units)) j += 1 # Fill class with values and arrays Qw = value(blk.Qw) CD = CurveData(Qw, T_units, DG_units) CD.Cooling_Tin = CTin CD.Cooling_Tout = CTout CD.Cooling_Q = CQ CD.Heating_Tin = HTin CD.Heating_Tout = HTout CD.Heating_Q = HQ return CD
def test_module_example(self): from pyomo.environ import ConcreteModel, Var, Objective, units # import components and 'units' instance model = ConcreteModel() model.acc = Var() model.obj = Objective(expr=(model.acc*units.m/units.s**2 - 9.81*units.m/units.s**2)**2) self.assertEqual('m ** 2 / s ** 4', str(units.get_units(model.obj.expr)))
def Txy_data(model, component_1, component_2, pressure, num_points=20, temperature=298.15, print_level=idaeslog.NOTSET, solver=None, solver_op=None): """ Function to generate T-x-y data. The function builds a state block and extracts bubble and dew temperatures at P pressure for N number of compositions. As N is increased increase the time of the calculation will increase and create a smoother looking plot. Args: component_1: Component 1 component_2: Component 2 pressure: Pressure at which the bubble and drew temperatures will be calculates temperature: Temperature at which to initialize state block num_points: Number of data point to be calculated model: Model wit intialized Property package which contains data to calculate bubble and dew temperatures for component 1 and component 2 print_level: printing level from initialization solver: solver to use (default=None, use IDAES default solver) solver_op: solver options Returns: (Class): A class containing the T-x-y data """ components = list(model.params.component_list) components_used = [component_1, component_2] components_not_used = list(set(components) - set(components_used)) # Add properties parameter blocks to the flowsheet with specifications model.props = model.params.build_state_block( [1], default={"defined_state": True}) # Set intial concentration of component 1 close to 1 x = 0.99 # Set conditions for flash unit model model.props[1].mole_frac_comp[component_1].fix(x) for i in components_not_used: model.props[1].mole_frac_comp[i].fix(1e-5) xs = sum( value(model.props[1].mole_frac_comp[i]) for i in components_not_used) model.props[1].mole_frac_comp[component_2].fix(1 - x - xs) model.props[1].flow_mol.fix(1) model.props[1].temperature.fix(temperature) model.props[1].pressure.fix(pressure) # Initialize flash unit model model.props[1].calculate_scaling_factors() model.props.initialize(solver=solver, optarg=solver_op, outlvl=print_level) solver = get_solver(solver, solver_op) # Create an array of compositions with N number of points x_d = np.linspace(x, 1 - x - xs, num_points) # Create emprty arrays for concentration, bubble temperature and dew temperature X = [] Tbubb = [] Tdew = [] # Obtain pressure and temperature units from the unit model Punit = pyunits.get_units(model.props[1].pressure) Tunit = pyunits.get_units(model.props[1].temperature) count = 1 # Create and run loop to calculate temperatures at every composition for i in range(len(x_d)): model.props[1].mole_frac_comp[component_1].fix(x_d[i]) model.props[1].mole_frac_comp[component_2].fix(1 - x_d[i] - xs) # solve the model status = solver.solve(model, tee=False) # If solution is optimal store the concentration, and calculated temperatures in the created arrays if (status.solver.status == SolverStatus.ok) and (status.solver.termination_condition == TerminationCondition.optimal): print('Case: ', count, ' Optimal. ', component_1, 'x = {:.2f}'.format(x_d[i])) if hasattr(model.props[1], "_mole_frac_tdew") and hasattr( model.props[1], "_mole_frac_tbub"): Tbubb.append( value(model.props[1].temperature_bubble['Vap', 'Liq'])) Tdew.append(value(model.props[1].temperature_dew['Vap', 'Liq'])) elif hasattr(model.props[1], "_mole_frac_tdew"): print('One of the components only exists in vapor phase.') Tdew.append(value(model.props[1].temperature_dew['Vap', 'Liq'])) elif hasattr(model.props[1], "_mole_frac_tbub"): print('One of the components only exists in liquid phase.') Tbubb.append( value(model.props[1].temperature_bubble['Vap', 'Liq'])) X.append(x_d[i]) # If the solver did not solve to an optimal solution, do not store the data point else: print('Case: ', count, ' No Result', component_1, 'x = {:.2f}'.format(x_d[i])) count += 1 # Call TXYData function and store the data in TD class TD = TXYDataClass(component_1, component_2, Punit, Tunit, pressure) TD.TBubb = Tbubb TD.TDew = Tdew TD.x = X # Return the data class with all the information of the calculations return TD
def test_build(self): model = ConcreteModel() model.params = GenericParameterBlock(default=configuration) assert isinstance(model.params.phase_list, Set) assert len(model.params.phase_list) == 2 for i in model.params.phase_list: assert i in ["Liq", "Vap"] assert model.params.Liq.is_liquid_phase() assert model.params.Vap.is_vapor_phase() assert isinstance(model.params.component_list, Set) assert len(model.params.component_list) == 13 for i in model.params.component_list: assert i in ['hydrogen', 'methane', 'ethane', 'propane', 'nbutane', 'ibutane', 'ethylene', 'propene', 'butene', 'pentene', 'hexene', 'heptene', 'octene'] assert isinstance(model.params.get_component(i), Component) assert isinstance(model.params._phase_component_set, Set) assert len(model.params._phase_component_set) == 24 for i in model.params._phase_component_set: assert i in [ ("Liq", "ethane"), ("Vap", "hydrogen"), ("Vap", "methane"), ("Vap", "ethane"), ("Liq", "propane"), ("Liq", "nbutane"), ("Liq", "ibutane"), ("Vap", "propane"), ("Vap", "nbutane"), ("Vap", "ibutane"), ("Liq", "ethylene"), ("Liq", "propene"), ("Liq", "butene"), ("Vap", "ethylene"), ("Vap", "propene"), ("Vap", "butene"), ("Liq", "pentene"), ("Liq", "hexene"), ("Liq", "heptene"), ("Vap", "pentene"), ("Vap", "hexene"), ("Vap", "heptene"), ("Liq", "octene"), ("Vap", "octene")] assert model.params.config.state_definition == FTPx assertStructuredAlmostEqual( model.params.config.state_bounds, { "flow_mol": (0, 100, 1000, pyunits.mol/pyunits.s), "temperature": (273.15, 300, 1500, pyunits.K), "pressure": (5e4, 1e5, 1e7, pyunits.Pa) }, item_callback=lambda x: value(x) * ( pyunits.get_units(x) or pyunits.dimensionless)._get_pint_unit() ) assert model.params.config.phase_equilibrium_state == { ("Vap", "Liq"): SmoothVLE} assert isinstance(model.params.phase_equilibrium_idx, Set) assert len(model.params.phase_equilibrium_idx) == 11 for i in model.params.phase_equilibrium_idx: assert i in ["PE1", "PE2", "PE3", "PE4", "PE5", "PE6", "PE7", "PE8", "PE9", "PE10", "PE11"] assert model.params.phase_equilibrium_list == { "PE1": {"ethane": ("Vap", "Liq")}, "PE2": {"propane": ("Vap", "Liq")}, "PE3": {"nbutane": ("Vap", "Liq")}, "PE4": {"ibutane": ("Vap", "Liq")}, "PE5": {"ethylene": ("Vap", "Liq")}, "PE6": {"propene": ("Vap", "Liq")}, "PE7": {"butene": ("Vap", "Liq")}, "PE8": {"pentene": ("Vap", "Liq")}, "PE9": {"hexene": ("Vap", "Liq")}, "PE10": {"heptene": ("Vap", "Liq")}, "PE11": {"octene": ("Vap", "Liq")}} assert model.params.pressure_ref.value == 101325 assert model.params.temperature_ref.value == 298.15 assert model.params.hydrogen.mw.value == 2.016E-3 assert model.params.hydrogen.pressure_crit.value == 12.9e5 assert model.params.hydrogen.temperature_crit.value == 33.2 assert model.params.methane.mw.value == 16.043E-3 assert model.params.methane.pressure_crit.value == 46e5 assert model.params.methane.temperature_crit.value == 190.4 assert model.params.ethane.mw.value == 30.070E-3 assert model.params.ethane.pressure_crit.value == 48.8e5 assert model.params.ethane.temperature_crit.value == 305.4 assert model.params.propane.mw.value == 44.094E-3 assert model.params.propane.pressure_crit.value == 42.5e5 assert model.params.propane.temperature_crit.value == 369.8 assert model.params.nbutane.mw.value == 58.124E-3 assert model.params.nbutane.pressure_crit.value == 38.0e5 assert model.params.nbutane.temperature_crit.value == 425.2 assert model.params.ibutane.mw.value == 58.124E-3 assert model.params.ibutane.pressure_crit.value == 36.5e5 assert model.params.ibutane.temperature_crit.value == 408.2 assert model.params.ethylene.mw.value == 28.054E-3 assert model.params.ethylene.pressure_crit.value == 50.5e5 assert model.params.ethylene.temperature_crit.value == 282.4 assert model.params.propene.mw.value == 42.081E-3 assert model.params.propene.pressure_crit.value == 46.2e5 assert model.params.propene.temperature_crit.value == 365.0 assert model.params.butene.mw.value == 56.104E-3 assert model.params.butene.pressure_crit.value == 40.2e5 assert model.params.butene.temperature_crit.value == 419.3 assert model.params.pentene.mw.value == 70.135E-3 assert model.params.pentene.pressure_crit.value == 40.5e5 assert model.params.pentene.temperature_crit.value == 464.7 assert model.params.hexene.mw.value == 84.162E-3 assert model.params.hexene.pressure_crit.value == 31.7e5 assert model.params.hexene.temperature_crit.value == 504.0 assert model.params.heptene.mw.value == 98.189E-3 assert model.params.heptene.pressure_crit.value == 25.4e5 assert model.params.heptene.temperature_crit.value == 537.2 assert model.params.octene.mw.value == 112.216E-3 assert model.params.octene.pressure_crit.value == 26.2e5 assert model.params.octene.temperature_crit.value == 566.6 assert_units_consistent(model)
def input_rule(b, i): if units.get_units(input_map[i]) is None: return b.ROM_input[i] == input_map[i] else: unit_conversion = units.get_units(input_map[i]) return b.ROM_input[i] == input_map[i]/unit_conversion
def return_expression(b, rblock, r_idx, T): units = pyunits.get_units(rblock.k_eq_ref) if units is None or units is pyunits.dimensionless: return exp(b.log_k_eq[r_idx]) else: return exp(b.log_k_eq[r_idx]) * units
def _as_quantity(x): unit = pyunits.get_units(x) if unit is None: unit = pyunits.dimensionless return value(x) * unit._get_pint_unit()
def test_build(self): model = ConcreteModel() model.params = GenericParameterBlock(default=configuration) assert isinstance(model.params.phase_list, Set) assert len(model.params.phase_list) == 2 for i in model.params.phase_list: assert i in ["Liq", "Vap"] assert model.params.Liq.is_liquid_phase() assert model.params.Vap.is_vapor_phase() assert isinstance(model.params.component_list, Set) assert len(model.params.component_list) == 3 for i in model.params.component_list: assert i in ['nitrogen', 'argon', 'oxygen'] assert isinstance(model.params.get_component(i), Component) assert isinstance(model.params._phase_component_set, Set) assert len(model.params._phase_component_set) == 6 for i in model.params._phase_component_set: assert i in [("Liq", "nitrogen"), ("Liq", "argon"), ("Liq", "oxygen"), ("Vap", "nitrogen"), ("Vap", "argon"), ("Vap", "oxygen")] assert model.params.config.state_definition == FTPx assertStructuredAlmostEqual( model.params.config.state_bounds, { "flow_mol": (0, 100, 1000, pyunits.mol / pyunits.s), "temperature": (10, 300, 350, pyunits.K), "pressure": (5e4, 1e5, 1e7, pyunits.Pa) }, item_callback=lambda x: value(x) * (pyunits.get_units(x) or pyunits.dimensionless)._get_pint_unit()) assert model.params.config.phase_equilibrium_state == { ("Vap", "Liq"): SmoothVLE } assert isinstance(model.params.phase_equilibrium_idx, Set) assert len(model.params.phase_equilibrium_idx) == 3 for i in model.params.phase_equilibrium_idx: assert i in ["PE1", "PE2", "PE3"] assert model.params.phase_equilibrium_list == { "PE1": { "nitrogen": ("Vap", "Liq") }, "PE2": { "argon": ("Vap", "Liq") }, "PE3": { "oxygen": ("Vap", "Liq") } } assert model.params.pressure_ref.value == 101325 assert model.params.temperature_ref.value == 298.15 assert model.params.nitrogen.mw.value == 28.0135E-3 assert model.params.nitrogen.pressure_crit.value == 34e5 assert model.params.nitrogen.temperature_crit.value == 126.2 assert model.params.argon.mw.value == 39.948E-3 assert model.params.argon.pressure_crit.value == 48.98e5 assert model.params.argon.temperature_crit.value == 150.86 assert model.params.oxygen.mw.value == 31.999E-3 assert model.params.oxygen.pressure_crit.value == 50.43e5 assert model.params.oxygen.temperature_crit.value == 154.58 assert_units_consistent(model)