def test_conservation(self, iron_oc): # Conservation of material check calculate_variable_from_constraint( iron_oc.fs.unit.gas_inlet_block[0].mw, iron_oc.fs.unit.gas_inlet_block[0].mw_eqn) calculate_variable_from_constraint( iron_oc.fs.unit.gas_outlet_block[0].mw, iron_oc.fs.unit.gas_outlet_block[0].mw_eqn) mbal_gas = value((iron_oc.fs.unit.gas_inlet.flow_mol[0] * iron_oc.fs.unit.gas_inlet_block[0].mw) - (iron_oc.fs.unit.gas_outlet.flow_mol[0] * iron_oc.fs.unit.gas_outlet_block[0].mw)) mbal_solid = value(iron_oc.fs.unit.solid_inlet.flow_mass[0] - iron_oc.fs.unit.solid_outlet.flow_mass[0]) mbal_tol = mbal_gas + mbal_solid assert abs(mbal_tol) <= 1e-2 # Reaction stoichiometric ratio check # Overall reducer reactions for methane combustion: # CH4 + 12Fe2O3 => 8Fe3O4 + CO2 + 2H2O mole_gas_reacted = value( iron_oc.fs.unit.gas_inlet.flow_mol[0] * iron_oc.fs.unit.gas_inlet.mole_frac_comp[0, 'CH4'] - iron_oc.fs.unit.gas_outlet.flow_mol[0] * iron_oc.fs.unit.gas_outlet.mole_frac_comp[0, 'CH4']) mole_solid_reacted = value( (iron_oc.fs.unit.solid_inlet.flow_mass[0] * iron_oc.fs.unit.solid_inlet.mass_frac_comp[0, 'Fe2O3'] / iron_oc.fs.unit.solid_inlet_block[0]._params.mw_comp['Fe2O3']) - (iron_oc.fs.unit.solid_outlet.flow_mass[0] * iron_oc.fs.unit.solid_outlet.mass_frac_comp[0, 'Fe2O3'] / iron_oc.fs.unit.solid_outlet_block[0]._params.mw_comp['Fe2O3'])) stoichiometric_ratio = mole_solid_reacted / mole_gas_reacted assert (pytest.approx(12, abs=1e-6) == stoichiometric_ratio)
def test_linear(self): m = ConcreteModel() m.x = Var() m.c = Constraint(expr=5*m.x == 10) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 2)
def test_turbine(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = PressureChanger( default={ "property_package": m.fs.properties, "thermodynamic_assumption": ThermodynamicAssumption.isentropic, "compressor": False }) # set inputs m.fs.unit.inlet.flow_mol[0].fix(1000) # mol/s Tin = 500 # K Pin = 1000000 # Pa Pout = 700000 # Pa hin = iapws95.htpx(Tin * units.K, Pin * units.Pa) m.fs.unit.inlet.enth_mol[0].fix(hin) m.fs.unit.inlet.pressure[0].fix(Pin) m.fs.unit.deltaP.fix(Pout - Pin) m.fs.unit.efficiency_isentropic.fix(0.9) m.fs.unit.initialize() m.fs.unit.get_costing() calculate_variable_from_constraint(m.fs.unit.costing.purchase_cost, m.fs.unit.costing.cp_cost_eq) assert degrees_of_freedom(m) == 0 assert_units_consistent(m.fs.unit) solver.solve(m, tee=True) assert m.fs.unit.costing.purchase_cost.value ==\ pytest.approx(213199, 1e-5)
def test_linear(self): m = ConcreteModel() m.x = Var() m.c = Constraint(expr=5 * m.x == 10) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 2)
def calculate_variable_scaling_factor(self, var): """ Calculates the scaling factor of a variable based on the constraint assigned to it. Loads each variable in that constraint with its nominal value (inverse of scaling factor), calculates the value of the target variable from the constraint, then sets its scaling factor to the inverse of the calculated value. """ vardata = self.get_representative_data_object(var) condata = self.var2con[vardata] scaling_factor = self.scaling_factor in_constraint = list(identify_variables(condata.expr)) source_vars = [v for v in in_constraint if v is not vardata] nominal_source = [1 / scaling_factor[var] for var in source_vars] with CacheVars(in_constraint) as cache: for v, nom_val in zip(source_vars, nominal_source): v.set_value(nom_val) # This assumes that target var is initialized to a somewhat # reasonable value calculate_variable_from_constraint(vardata, condata) nominal_target = vardata.value if nominal_target == 0: target_factor = 1.0 else: target_factor = abs(1 / nominal_target) if self.dim == 0: scaling_factor[var] = target_factor else: for v in var.values(): scaling_factor[v] = target_factor
def test_compressor(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = PressureChanger( default={ "property_package": m.fs.properties, "thermodynamic_assumption": ThermodynamicAssumption.isentropic, "compressor": True }) # set inputs m.fs.unit.inlet.flow_mol[0].fix(10000) m.fs.unit.inlet.enth_mol[0].fix(4000) m.fs.unit.inlet.pressure[0].fix(101325) m.fs.unit.deltaP.fix(500000) m.fs.unit.efficiency_isentropic.fix(0.9) iscale.calculate_scaling_factors(m) m.fs.unit.initialize() assert degrees_of_freedom(m) == 0 m.fs.unit.get_costing(mover_type="compressor") calculate_variable_from_constraint(m.fs.unit.costing.purchase_cost, m.fs.unit.costing.cp_cost_eq) assert_units_consistent(m.fs.unit) solver.solve(m, tee=True) assert m.fs.unit.costing.purchase_cost.value == \ pytest.approx(334648, 1e-5)
def test_nonlinear_bound_violation(self): m = ConcreteModel() m.v1 = Var(initialize=1, domain=NonNegativeReals) m.c1 = Constraint(expr=m.v1 == 0) # Test nonlinear solution falling outside bounds m.c4 = Constraint(expr=m.v1**3 == -8) m.v1.set_value(1) calculate_variable_from_constraint(m.v1, m.c4) self.assertEqual(value(m.v1), -2)
def initialize(self, solver=None, optarg=None, outlvl=idaeslog.NOTSET, **kwargs): self.outlet_state.initialize(hold_state=False, solver=solver, optarg=optarg, outlvl=outlvl) for t in self.flowsheet().config.time: calculate_variable_from_constraint(self.outlet.flow_mol[t], self.efficiency_curve[t])
def test_compressor_fan(): m = pyo.ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() # Add property packages to flowsheet library m.fs.prop_fluegas = FlueGasParameterBlock() m.fs.unit = PressureChanger( default={ "property_package": m.fs.prop_fluegas, "thermodynamic_assumption": ThermodynamicAssumption.isentropic, "compressor": True }) # # FLUE GAS Inlet from Primary Superheater FGrate = 425.813998 # mol/s # # Use FG molar composition to set component flow rates (baseline report) m.fs.unit.control_volume.properties_in[0].flow_mol_comp["H2O"].\ fix(FGrate*8.69/100) m.fs.unit.control_volume.properties_in[0].flow_mol_comp["CO2"].\ fix(FGrate*14.49/100) m.fs.unit.control_volume.properties_in[0].flow_mol_comp["N2"].\ fix(FGrate*74.34/100) m.fs.unit.control_volume.properties_in[0].flow_mol_comp["O2"].\ fix(FGrate*2.47/100) m.fs.unit.control_volume.properties_in[0].flow_mol_comp["NO"].\ fix(FGrate*0.0006) m.fs.unit.control_volume.properties_in[0].flow_mol_comp["SO2"]\ .fix(FGrate*0.002) m.fs.unit.control_volume.properties_in[0].temperature.fix(200.335) m.fs.unit.control_volume.properties_in[0].pressure.fix(98658.6) m.fs.unit.deltaP.fix(101325 - 98658.6) m.fs.unit.efficiency_isentropic.fix(0.9) m.fs.unit.initialize() m.fs.unit.get_costing(mover_type='fan') calculate_variable_from_constraint(m.fs.unit.costing.purchase_cost, m.fs.unit.costing.cp_cost_eq) assert degrees_of_freedom(m) == 0 # Check unit config arguments assert isinstance(m.fs.unit.costing.purchase_cost, pyo.Var) assert isinstance(m.fs.unit.costing.base_cost, pyo.Var) results = solver.solve(m, tee=True) assert results.solver.termination_condition == \ pyo.TerminationCondition.optimal assert results.solver.status == pyo.SolverStatus.ok assert (pytest.approx(pyo.value(m.fs.unit.costing.base_cost), abs=1e-2) == 4543.6428) assert (pytest.approx(pyo.value(m.fs.unit.costing.purchase_cost), abs=1e-2) == 22106.9807)
def update_time_derivatives(fs,t): verbose = False debug = True m = fs.MB_fuel if verbose: print('\nTime derivative values: \n - - -') for z in m.z: if z != m.z.first(): for j in m.GasList: #if t > 0: pdb.set_trace() calculate_variable_from_constraint(m.dCgdt[z,j,t],m.eq_b1[z,j,t]) if verbose: print('\t\tdCgdt ',z,',',j,',',t,':\t',m.dCgdt[z,j,t].value) for j in m.SolidList: calculate_variable_from_constraint(m.dqdt[z,j,t],m.eq_b2[z,j,t]) if verbose: print('\t\tdqdt ',z,',',j,',',t,':\t',m.dqdt[z,j,t].value) calculate_variable_from_constraint(m.dTgdt[z,t],m.eq_d1[z,t]) if verbose: print('\t\tdTgdt ',z,',',t,':\t',m.dTgdt[z,t].value) calculate_variable_from_constraint(m.dTsdt[z,t],m.eq_d6[z,t]) if verbose: print('\t\tdTsdt ',z,',',t,':\t',m.dTsdt[z,t].value) #else: # for j in m.GasList: # m.dCgdt[z,j,t].set_value(0) # for j in m.SolidList: # m.dqdt[z,j,t].set_value(0) # m.dTgdt[z,t].set_value(0) # m.dTsdt[z,t].set_value(0) if verbose: print('- - -\n')
def test_costing(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = HeatExchanger( default={ "shell": { "property_package": m.fs.properties }, "tube": { "property_package": m.fs.properties }, "flow_pattern": HeatExchangerFlowPattern.countercurrent }) # Set inputs m.fs.unit.inlet_1.flow_mol[0].fix(100) m.fs.unit.inlet_1.enth_mol[0].fix(4000) m.fs.unit.inlet_1.pressure[0].fix(101325) m.fs.unit.inlet_2.flow_mol[0].fix(100) m.fs.unit.inlet_2.enth_mol[0].fix(3500) m.fs.unit.inlet_2.pressure[0].fix(101325) m.fs.unit.area.fix(1000) m.fs.unit.overall_heat_transfer_coefficient.fix(100) assert degrees_of_freedom(m) == 0 m.fs.unit.initialize() m.fs.unit.get_costing() calculate_variable_from_constraint(m.fs.unit.costing.base_cost, m.fs.unit.costing.base_cost_eq) calculate_variable_from_constraint(m.fs.unit.costing.purchase_cost, m.fs.unit.costing.cp_cost_eq) assert_units_consistent(m.fs.unit.costing) results = solver.solve(m) # Check for optimal solution assert results.solver.termination_condition == TerminationCondition.optimal assert results.solver.status == SolverStatus.ok assert m.fs.unit.costing.purchase_cost.value == \ pytest.approx(529738.6793, 1e-5)
def calculate_bubble_point_temperature(self, clear_components=True): """"To compute the bubble point temperature of the mixture.""" if hasattr(self, "eq_temperature_bubble"): # Do not delete components if the block already has the components clear_components = False calculate_variable_from_constraint(self.temperature_bubble, self.eq_temperature_bubble) return self.temperature_bubble.value if clear_components is True: self.del_component(self.eq_temperature_bubble) self.del_component(self._p_sat_bubbleT) self.del_component(self.temperature_bubble)
def initialize_build(self): calculate_variable_from_constraint(self.total_investment_cost, self.total_investment_cost_constraint) calculate_variable_from_constraint(self.maintenance_labor_chemical_operating_cost, self.maintenance_labor_chemical_operating_cost_constraint) calculate_variable_from_constraint(self.total_operating_cost, self.total_operating_cost_constraint) if hasattr(self, "LCOW"): calculate_variable_from_constraint(self.LCOW, self.LCOW_constraint)
def calculate_dew_point_pressure(self, clear_components=True): """"To compute the dew point pressure of the mixture.""" if hasattr(self, "eq_pressure_dew"): # Do not delete components if the block already has the components clear_components = False calculate_variable_from_constraint(self.pressure_dew, self.eq_pressure_dew) return self.pressure_dew.value # Delete the var/constraint created in this method that are part of the # IdealStateBlock if the user desires if clear_components is True: self.del_component(self.eq_pressure_dew) self.del_component(self._p_sat_dewP) self.del_component(self.pressure_dew)
def test_has_consistent_initial_conditions(self): nmpc = self.make_nmpc() with pytest.raises(ValueError): # Model has not been properly initialized nmpc.has_consistent_initial_conditions(nmpc.plant) t0 = nmpc.plant_time.first() nmpc.plant.rate[t0, :].set_value(0.0) nmpc.plant.flow_out[t0].set_value(nmpc.plant.flow_in[t0].value) for j in nmpc.plant.components: calculate_variable_from_constraint( nmpc.plant.dcdt[t0, j], nmpc.plant.material_balance[t0, j], ) assert nmpc.has_consistent_initial_conditions(nmpc.plant) nmpc.plant.flow_out[t0].set_value(0.0) assert not nmpc.has_consistent_initial_conditions(nmpc.plant)
def test_costing_book(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = HeatExchanger( default={ "shell": { "property_package": m.fs.properties }, "tube": { "property_package": m.fs.properties }, "flow_pattern": HeatExchangerFlowPattern.countercurrent }) # Set inputs m.fs.unit.inlet_1.flow_mol[0].fix(100) m.fs.unit.inlet_1.enth_mol[0].fix(4000) m.fs.unit.inlet_1.pressure[0].fix(101325) m.fs.unit.inlet_2.flow_mol[0].fix(100) m.fs.unit.inlet_2.enth_mol[0].fix(3500) m.fs.unit.inlet_2.pressure[0].fix(101325) m.fs.unit.area.fix(1000) m.fs.unit.overall_heat_transfer_coefficient.fix(100) # costing m.fs.unit.get_costing(hx_type='floating_head', length_factor='20ft', year='2018') m.fs.unit.area.fix(669.738) # m2 m.fs.unit.costing.pressure_factor.fix(1.19) m.fs.unit.costing.material_factor.fix(4.05) m.fs.costing.CE_index = 550 m.fs.unit.costing.hx_os = 1.0 calculate_variable_from_constraint(m.fs.unit.costing.base_cost_per_unit, m.fs.unit.costing.base_cost_per_unit_eq) calculate_variable_from_constraint(m.fs.unit.costing.purchase_cost, m.fs.unit.costing.cp_cost_eq) assert value(m.fs.unit.costing.base_cost) == \ pytest.approx(78802.0518, 1e-5) assert m.fs.unit.costing.purchase_cost.value == \ pytest.approx(417765.1377, 1e-5)
def initialize_build(self): calculate_variable_from_constraint( self.total_investment_cost, self.total_investment_cost_constraint) calculate_variable_from_constraint( self.maintenance_labor_chemical_operating_cost, self.maintenance_labor_chemical_operating_cost_constraint, ) calculate_variable_from_constraint( self.total_operating_cost, self.total_operating_cost_constraint) for var, con in self._registered_LCOWs.values(): calculate_variable_from_constraint(var, con)
def test_warn_final_value_nonlinear(self): m = ConcreteModel() m.x = Var(bounds=(0, 1)) m.c3 = Constraint(expr=(m.x - 3.5)**2 == 0) with LoggingIntercept() as LOG: calculate_variable_from_constraint(m.x, m.c3) self.assertRegex( LOG.getvalue().strip(), r"Setting Var 'x' to a numeric value `[0-9\.]+` outside the " r"bounds \(0, 1\).") self.assertAlmostEqual(value(m.x), 3.5, 3) m.x.domain = Binary with LoggingIntercept() as LOG: calculate_variable_from_constraint(m.x, m.c3) self.assertRegex( LOG.getvalue().strip(), r"Setting Var 'x' to a value `[0-9\.]+` \(float\) not in " "domain Binary.") self.assertAlmostEqual(value(m.x), 3.5, 3)
def test_warn_final_value_linear(self): m = ConcreteModel() m.x = Var(bounds=(0, 1)) m.c1 = Constraint(expr=m.x == 10) m.c2 = Constraint(expr=5 * m.x == 10) with LoggingIntercept() as LOG: calculate_variable_from_constraint(m.x, m.c1) self.assertEqual( LOG.getvalue().strip(), "Setting Var 'x' to a numeric value `10` outside the " "bounds (0, 1).") self.assertEqual(value(m.x), 10) with LoggingIntercept() as LOG: calculate_variable_from_constraint(m.x, m.c2) self.assertEqual( LOG.getvalue().strip(), "Setting Var 'x' to a numeric value `2.0` outside the " "bounds (0, 1).") self.assertEqual(value(m.x), 2)
def test_constraint_as_tuple(self): m = ConcreteModel() m.x = Var() m.p = Param(initialize=15, mutable=True) calculate_variable_from_constraint(m.x, 5 * m.x == 5) self.assertEqual(value(m.x), 1) calculate_variable_from_constraint(m.x, (5 * m.x, 10)) self.assertEqual(value(m.x), 2) calculate_variable_from_constraint(m.x, (15, 5 * m.x, m.p)) self.assertEqual(value(m.x), 3) with self.assertRaisesRegex( ValueError, "Constraint 'tuple' is a Ranged Inequality " "with a variable upper bound."): calculate_variable_from_constraint(m.x, (15, 5 * m.x, m.x))
def set_input_values(self, input_values): solver = self._solver external_cons = self.external_cons external_vars = self.external_vars input_vars = self.input_vars for var, val in zip(input_vars, input_values): var.set_value(val) for block, inputs in self._scc_list: if len(block.vars) == 1: calculate_variable_from_constraint(block.vars[0], block.cons[0]) else: with TemporarySubsystemManager(to_fix=inputs): solver.solve(block) # Send updated variable values to NLP for dervative evaluation primals = self._nlp.get_primals() to_update = input_vars + external_vars indices = self._nlp.get_primal_indices(to_update) values = np.fromiter((var.value for var in to_update), float) primals[indices] = values self._nlp.set_primals(primals)
def initialize_t0(model): time = model.time t0 = time.first() calculate_variable_from_constraint( model.flow_out[t0], model.flow_eqn[t0], ) for j in model.components: calculate_variable_from_constraint( model.rate[t0, j], model.rate_eqn[t0, j], ) calculate_variable_from_constraint( model.dcdt[t0, j], model.material_balance[t0, j], )
def test_bound_violation(self): # Test Issue #2176: solving a constraint where the intermediate # value can step outside the bounds m = ConcreteModel() m.v1 = Var(initialize=1, domain=NonNegativeReals) m.c1 = Constraint(expr=m.v1 == 0) # Calculate value of v1 using constraint c1 calculate_variable_from_constraint(m.v1, m.c1) self.assertEqual(value(m.v1), 0) # Calculate value of v1 using a scaled constraint c2 m.c2 = Constraint(expr=m.v1 * 10 == 0) m.v1.set_value(1) calculate_variable_from_constraint(m.v1, m.c2) self.assertEqual(value(m.v1), 0) # Test linear solution falling outside bounds m.c3 = Constraint(expr=m.v1 * 10 == -1) m.v1.set_value(1) calculate_variable_from_constraint(m.v1, m.c3) self.assertEqual(value(m.v1), -0.1)
def test_pump(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.unit = PressureChanger( default={ "property_package": m.fs.properties, "thermodynamic_assumption": ThermodynamicAssumption.pump, "compressor": True }) # set inputs m.fs.unit.inlet.flow_mol[0].fix(10000) m.fs.unit.inlet.enth_mol[0].fix(4000) m.fs.unit.inlet.pressure[0].fix(101325) m.fs.unit.deltaP.fix(50000) m.fs.unit.efficiency_pump.fix(0.9) iscale.calculate_scaling_factors(m) m.fs.unit.initialize() assert degrees_of_freedom(m) == 0 m.fs.unit.get_costing(pump_type='centrifugal', Mat_factor='nickel', pump_motor_type_factor='enclosed') calculate_variable_from_constraint( m.fs.unit.costing.motor_purchase_cost, m.fs.unit.costing.cp_motor_cost_eq) calculate_variable_from_constraint( m.fs.unit.costing.pump_purchase_cost, m.fs.unit.costing.cp_pump_cost_eq) calculate_variable_from_constraint(m.fs.unit.costing.purchase_cost, m.fs.unit.costing.total_cost_eq) solver.solve(m, tee=True) assert m.fs.unit.costing.purchase_cost.value == \ pytest.approx(70141.395, 1e-5)
def test_nonlinear(self): m = ConcreteModel() m.x = Var() m.y = Var(initialize=0) m.c = Constraint(expr=m.x**2 == 16) m.x.set_value(1.0) # set an initial value calculate_variable_from_constraint(m.x, m.c, linesearch=False) self.assertAlmostEqual(value(m.x), 4) # test that infeasible constraint throws error m.d = Constraint(expr=m.x**2 == -1) m.x.set_value(1.25) # set the initial value with self.assertRaisesRegex(RuntimeError, r'Iteration limit \(10\) reached'): calculate_variable_from_constraint(m.x, m.d, iterlim=10, linesearch=False) # same problem should throw a linesearch error if linesearch is on m.x.set_value(1.25) # set the initial value with self.assertRaisesRegex(RuntimeError, "Linesearch iteration limit reached"): calculate_variable_from_constraint(m.x, m.d, iterlim=10, linesearch=True) # same problem should raise an error if initialized at 0 m.x = 0 with self.assertRaisesRegex( RuntimeError, "Initial value for variable results in a " "derivative value that is very close to zero."): calculate_variable_from_constraint(m.x, m.c) # same problem should raise a value error if we are asked to # solve for a variable that is not present with self.assertRaisesRegex(ValueError, "Variable derivative == 0"): calculate_variable_from_constraint(m.y, m.c) # should succeed with or without a linesearch m.e = Constraint(expr=(m.x - 2.0)**2 - 1 == 0) m.x.set_value(3.1) calculate_variable_from_constraint(m.x, m.e, linesearch=False) self.assertAlmostEqual(value(m.x), 3) m.x.set_value(3.1) calculate_variable_from_constraint(m.x, m.e, linesearch=True) self.assertAlmostEqual(value(m.x), 3) # we expect this to succeed with the linesearch m.f = Constraint(expr=1.0 / (1.0 + exp(-m.x)) - 0.5 == 0) m.x.set_value(3.0) calculate_variable_from_constraint(m.x, m.f, linesearch=True) self.assertAlmostEqual(value(m.x), 0) # we expect this to fail without a linesearch m.x.set_value(3.0) with self.assertRaisesRegex( RuntimeError, "Newton's method encountered a derivative " "that was too close to zero"): calculate_variable_from_constraint(m.x, m.f, linesearch=False) # Calculate the bubble point of Benzene. THe first step # computed by calculate_variable_from_constraint will make the # second term become complex, and the evaluation will fail. # This tests that the algorithm cleanly continues m = ConcreteModel() m.x = Var() m.pc = 48.9e5 m.tc = 562.2 m.psc = { 'A': -6.98273, 'B': 1.33213, 'C': -2.62863, 'D': -3.33399, } m.p = 101325 @m.Constraint() def f(m): return m.pc * \ exp((m.psc['A'] * (1 - m.x / m.tc) + m.psc['B'] * (1 - m.x / m.tc)**1.5 + m.psc['C'] * (1 - m.x / m.tc)**3 + m.psc['D'] * (1 - m.x / m.tc)**6 ) / (1 - (1 - m.x / m.tc))) - m.p == 0 m.x.set_value(298.15) calculate_variable_from_constraint(m.x, m.f, linesearch=False) self.assertAlmostEqual(value(m.x), 353.31855602) m.x.set_value(298.15) calculate_variable_from_constraint(m.x, m.f, linesearch=True) self.assertAlmostEqual(value(m.x), 353.31855602) # Starting with an invalid guess (above TC) should raise an # exception m.x.set_value(600) output = StringIO() with LoggingIntercept(output, 'pyomo', logging.WARNING): with self.assertRaises(TypeError): calculate_variable_from_constraint(m.x, m.f, linesearch=False) self.assertIn( 'Encountered an error evaluating the expression ' 'at the initial guess', output.getvalue()) # This example triggers an expression evaluation error if the # linesearch is turned off because the first step in Newton's # method will cause the LHS to become complex m = ConcreteModel() m.x = Var() m.c = Constraint(expr=(1 / m.x**3)**0.5 == 100) m.x = .1 calculate_variable_from_constraint(m.x, m.c, linesearch=True) self.assertAlmostEqual(value(m.x), 0.046415888) m.x = .1 output = StringIO() with LoggingIntercept(output, 'pyomo', logging.WARNING): with self.assertRaises(ValueError): # Note that the ValueError is different between Python 2 # and Python 3: in Python 2 it is a specific error # "negative number cannot be raised to a fractional # power", and We mock up that error in Python 3 by # raising a generic ValueError in # calculate_variable_from_constraint calculate_variable_from_constraint(m.x, m.c, linesearch=False) self.assertIn( "Newton's method encountered an error evaluating " "the expression.", output.getvalue()) # This is a completely contrived example where the linesearch # hits the iteration limit before Newton's method ever finds a # feasible step m = ConcreteModel() m.x = Var() m.c = Constraint(expr=m.x**0.5 == -1e-8) m.x = 1e-8 #197.932807183 with self.assertRaisesRegex( RuntimeError, "Linesearch iteration limit reached; " "remaining residual = {function evaluation error}"): calculate_variable_from_constraint(m.x, m.c, linesearch=True, alpha_min=.5)
def initialize(blk, flow_mol_phase_comp=None, temperature=None, pressure=None, state_vars_fixed=False, hold_state=False, outlvl=1, solver='ipopt', optarg={'tol': 1e-8}): """ Initialisation routine for property package. Keyword Arguments: flow_mol_phase_comp : value at which to initialize phase-component flows (default=None) pressure : value at which to initialize pressure (default=None) temperature : value at which to initialize temperature (default=None) outlvl : sets output level of initialisation routine * 0 = no output (default) * 1 = return solver state for each step in routine * 2 = include solver output infomation (tee=True) optarg : solver options dictionary object (default=None) state_vars_fixed: Flag to denote if state vars have already been fixed. - True - states have already been fixed by the control volume 1D. Control volume 0D does not fix the state vars, so will be False if this state block is used with 0D blocks. - False - states have not been fixed. The state block will deal with fixing/unfixing. solver : str indicating whcih solver to use during initialization (default = 'ipopt') hold_state : flag indicating whether the initialization routine should unfix any state variables fixed during initialization (default=False). - True - states varaibles are not unfixed, and a dict of returned containing flags for which states were fixed during initialization. - False - state variables are unfixed after initialization by calling the relase_state method Returns: If hold_states is True, returns a dict containing flags for which states were fixed during initialization. """ _log.info('Starting {} initialisation'.format(blk.name)) # Fix state variables if not already fixed if state_vars_fixed is False: Fflag = {} Pflag = {} Tflag = {} for k in blk.keys(): for p in blk[k]._params.phase_list: for j in blk[k]._params.component_list: if blk[k].flow_mol_phase_comp[p, j].fixed is True: Fflag[k, p, j] = True else: Fflag[k, p, j] = False if flow_mol_phase_comp is None: blk[k].flow_mol_phase_comp[p, j].fix( 1 / len(blk[k]._params.component_list)) else: blk[k].flow_mol_phase_comp[p, j].fix( flow_mol_phase_comp[p, j]) if blk[k].pressure.fixed is True: Pflag[k] = True else: Pflag[k] = False if pressure is None: blk[k].pressure.fix(101325.0) else: blk[k].pressure.fix(pressure) if blk[k].temperature.fixed is True: Tflag[k] = True else: Tflag[k] = False if temperature is None: blk[k].temperature.fix(325) else: blk[k].temperature.fix(temperature) # ----------------------------------------------------------------- # If input block, return flags, else release state flags = {"Fflag": Fflag, "Pflag": Pflag, "Tflag": Tflag} else: # Check when the state vars are fixed already result in dof 0 for k in blk.keys(): if degrees_of_freedom(blk[k]) != 0: raise Exception("State vars fixed but degrees of freedom " "for state block is not zero during " "initialization.") # Set solver options if outlvl > 1: stee = True else: stee = False if optarg is None: sopt = {'tol': 1e-8} else: sopt = optarg opt = SolverFactory('ipopt') opt.options = sopt # --------------------------------------------------------------------- # If present, initialize bubble and dew point calculations for k in blk.keys(): if hasattr(blk[k], "eq_temperature_dew"): calculate_variable_from_constraint(blk[k].temperature_dew, blk[k].eq_temperature_dew) if hasattr(blk[k], "eq_pressure_dew"): calculate_variable_from_constraint(blk[k].pressure_dew, blk[k].eq_pressure_dew) if outlvl > 0: _log.info("Dew and bubble points initialization for " "{} completed".format(blk.name)) # --------------------------------------------------------------------- # If flash, initialize T1 and Teq for k in blk.keys(): if (blk[k].config.has_phase_equilibrium and not blk[k].config.defined_state): blk[k]._t1.value = max(blk[k].temperature.value, blk[k].temperature_bubble.value) blk[k]._teq.value = min(blk[k]._t1.value, blk[k].temperature_dew.value) if outlvl > 0: _log.info("Equilibrium temperature initialization for " "{} completed".format(blk.name)) # --------------------------------------------------------------------- # Initialize flow rates and compositions # TODO : This will need ot be generalised more when we move to a # modular implementation for k in blk.keys(): # Deactivate equilibrium constraints, as state is fixed if hasattr(blk[k], 'equilibrium_constraint'): blk[k].equilibrium_constraint.deactivate() free_vars = 0 for k in blk.keys(): free_vars += number_unfixed_variables(blk[k]) if free_vars > 0: try: results = solve_indexed_blocks(opt, [blk], tee=stee) except: results = None else: results = None for k in blk.keys(): # Reactivate equilibrium constraints if hasattr(blk[k], 'equilibrium_constraint'): blk[k].equilibrium_constraint.activate() if outlvl > 0: if results is None or results.solver.termination_condition \ == TerminationCondition.optimal: _log.info("Property initialization for " "{} completed".format(blk.name)) else: _log.warning("Property initialization for " "{} failed".format(blk.name)) # --------------------------------------------------------------------- # Return state to initial conditions if state_vars_fixed is False: if hold_state is True: return flags else: blk.release_state(flags) if outlvl > 0: _log.info("Initialisation completed for {}".format(blk.name))
def initialize(blk, state_args=None, state_vars_fixed=False, hold_state=False, outlvl=1, solver='ipopt', optarg={'tol': 1e-8}): """ Initialisation routine for property package. Keyword Arguments: state_args : Dictionary with initial guesses for the state vars chosen. Note that if this method is triggered through the control volume, and if initial guesses were not provied at the unit model level, the control volume passes the inlet values as initial guess.The keys for the state_args dictionary are: flow_mol : value at which to initialize component flows pressure : value at which to initialize pressure temperature : value at which to initialize temperature mole_frac_comp: value at which to initialize the component mixture mole fraction outlvl : sets output level of initialisation routine * 0 = no output (default) * 1 = return solver state for each step in routine * 2 = include solver output infomation (tee=True) optarg : solver options dictionary object (default=None) state_vars_fixed: Flag to denote if state vars have already been fixed. - True - states have already been fixed by the control volume 1D. Control volume 0D does not fix the state vars, so will be False if this state block is used with 0D blocks. - False - states have not been fixed. The state block will deal with fixing/unfixing. solver : str indicating whcih solver to use during initialization (default = 'ipopt') hold_state : flag indicating whether the initialization routine should unfix any state variables fixed during initialization (default=False). - True - states varaibles are not unfixed, and a dict of returned containing flags for which states were fixed during initialization. - False - state variables are unfixed after initialization by calling the relase_state method Returns: If hold_states is True, returns a dict containing flags for which states were fixed during initialization. """ _log.info('Starting {} initialisation'.format(blk.name)) # Deactivate the constraints specific for outlet block i.e. # when defined state is False for k in blk.keys(): if blk[k].config.defined_state is False: blk[k].sum_mole_frac_out.deactivate() # Fix state variables if not already fixed if state_vars_fixed is False: Fflag = {} Xflag = {} Pflag = {} Tflag = {} for k in blk.keys(): if blk[k].flow_mol.fixed is True: Fflag[k] = True else: Fflag[k] = False if state_args is None: blk[k].flow_mol.fix(1.0) else: blk[k].flow_mol.fix(state_args["flow_mol"]) for j in blk[k]._params.component_list: if blk[k].mole_frac_comp[j].fixed is True: Xflag[k, j] = True else: Xflag[k, j] = False if state_args is None: blk[k].mole_frac_comp[j].fix( 1 / len(blk[k]._params.component_list)) else: blk[k].mole_frac_comp[j].fix( state_args["mole_frac_comp"][j]) if blk[k].pressure.fixed is True: Pflag[k] = True else: Pflag[k] = False if state_args is None: blk[k].pressure.fix(101325.0) else: blk[k].pressure.fix(state_args["pressure"]) if blk[k].temperature.fixed is True: Tflag[k] = True else: Tflag[k] = False if state_args is None: blk[k].temperature.fix(325) else: blk[k].temperature.fix(state_args["temperature"]) # --------------------------------------------------------------------- # If input block, return flags, else release state flags = { "Fflag": Fflag, "Xflag": Xflag, "Pflag": Pflag, "Tflag": Tflag } else: # Check when the state vars are fixed already result in dof 0 for k in blk.keys(): if degrees_of_freedom(blk[k]) != 0: raise Exception("State vars fixed but degrees of freedom " "for state block is not zero during " "initialization.") # Set solver options if outlvl > 1: stee = True else: stee = False if optarg is None: sopt = {'tol': 1e-8} else: sopt = optarg opt = SolverFactory('ipopt') opt.options = sopt # --------------------------------------------------------------------- # If present, initialize bubble and dew point calculations for k in blk.keys(): if hasattr(blk[k], "eq_temperature_bubble"): calculate_variable_from_constraint( blk[k].temperature_bubble, blk[k].eq_temperature_bubble) if hasattr(blk[k], "eq_temperature_dew"): calculate_variable_from_constraint(blk[k].temperature_dew, blk[k].eq_temperature_dew) if hasattr(blk[k], "eq_pressure_bubble"): calculate_variable_from_constraint(blk[k].pressure_bubble, blk[k].eq_pressure_bubble) if hasattr(blk[k], "eq_pressure_dew"): calculate_variable_from_constraint(blk[k].pressure_dew, blk[k].eq_pressure_dew) if outlvl > 0: _log.info("Dew and bubble points initialization for " "{} completed".format(blk.name)) # --------------------------------------------------------------------- # If flash, initialize T1 and Teq for k in blk.keys(): if blk[k].config.has_phase_equilibrium: blk[k]._t1.value = max(blk[k].temperature.value, blk[k].temperature_bubble.value) blk[k]._teq.value = min(blk[k]._t1.value, blk[k].temperature_dew.value) if outlvl > 0: _log.info("Equilibrium temperature initialization for " "{} completed".format(blk.name)) # --------------------------------------------------------------------- # Initialize flow rates and compositions # TODO : This will need ot be generalised more when we move to a # modular implementation for k in blk.keys(): if blk[k]._params.config.valid_phase == "Liq": blk[k].flow_mol_phase['Liq'].value = \ blk[k].flow_mol.value for j in blk[k]._params.component_list: blk[k].mole_frac_phase_comp['Liq', j].value = \ blk[k].mole_frac_comp[j].value elif blk[k]._params.config.valid_phase == "Vap": blk[k].flow_mol_phase['Vap'].value = \ blk[k].flow_mol.value for j in blk[k]._params.component_list: blk[k].mole_frac_phase_comp['Vap', j].value = \ blk[k].mole_frac_comp[j].value else: # Seems to work best with default values for phase flows for j in blk[k]._params.component_list: blk[k].mole_frac_phase_comp['Vap', j].value = \ blk[k].mole_frac_comp[j].value blk[k].mole_frac_phase_comp['Liq', j].value = \ blk[k].mole_frac_comp[j].value calculate_variable_from_constraint( blk[k].pressure_sat[j], blk[k].eq_pressure_sat[j]) # --------------------------------------------------------------------- # Solve phase equilibrium constraints for k in blk.keys(): for c in blk[k].component_objects(Constraint): # Deactivate all property constraints if c.local_name not in ("total_flow_balance", "component_flow_balances", "equilibrium_constraint", "sum_mole_frac", "_t1_constraint", "_teq_constraint", "eq_pressure_dew", "eq_pressure_bubble", "eq_temperature_dew", "eq_temperature_bubble", "eq_pressure_sat"): c.deactivate() results = solve_indexed_blocks(opt, [blk], tee=stee) if outlvl > 0: if results.solver.termination_condition \ == TerminationCondition.optimal: _log.info("Phase state initialization for " "{} completed".format(blk.name)) else: _log.warning("Phase state initialization for " "{} failed".format(blk.name)) # --------------------------------------------------------------------- # Initialize other properties for k in blk.keys(): for c in blk[k].component_objects(Constraint): # Activate all constraints except sum_mole_frac_out if c.local_name not in ("sum_mole_frac_out"): c.activate() if outlvl > 0: if results.solver.termination_condition \ == TerminationCondition.optimal: _log.info("Property initialization for " "{} completed".format(blk.name)) else: _log.warning("Property initialization for " "{} failed".format(blk.name)) # --------------------------------------------------------------------- # Return state to initial conditions for k in blk.keys(): if (blk[k].config.defined_state is False): blk[k].sum_mole_frac_out.activate() if state_vars_fixed is False: if hold_state is True: return flags else: blk.release_state(flags) if outlvl > 0: _log.info("Initialisation completed for {}".format(blk.name))
def initialize(blk, flow_mol_comp=None, temperature=None, pressure=None, hold_state=False, outlvl=0, state_vars_fixed=False, solver='ipopt', optarg={'tol': 1e-8}): ''' Initialisation routine for property package. Keyword Arguments: flow_mol_comp : value at which to initialize component flows (default=None) pressure : value at which to initialize pressure (default=None) temperature : value at which to initialize temperature (default=None) outlvl : sets output level of initialisation routine * 0 = no output (default) * 1 = return solver state for each step in routine * 2 = include solver output infomation (tee=True) state_vars_fixed: Flag to denote if state vars have already been fixed. - True - states have already been fixed by the control volume 1D. Control volume 0D does not fix the state vars, so will be False if this state block is used with 0D blocks. - False - states have not been fixed. The state block will deal with fixing/unfixing. optarg : solver options dictionary object (default=None) solver : str indicating whcih solver to use during initialization (default = 'ipopt') hold_state : flag indicating whether the initialization routine should unfix any state variables fixed during initialization (default=False). - True - states varaibles are not unfixed, and a dict of returned containing flags for which states were fixed during initialization. - False - state variables are unfixed after initialization by calling the relase_state method Returns: If hold_states is True, returns a dict containing flags for which states were fixed during initialization. ''' if state_vars_fixed is False: # Fix state variables if not already fixed Fcflag = {} Pflag = {} Tflag = {} for k in blk.keys(): for j in blk[k]._params.component_list: if blk[k].flow_mol_comp[j].fixed is True: Fcflag[k, j] = True else: Fcflag[k, j] = False if flow_mol_comp is None: blk[k].flow_mol_comp[j].fix(1.0) else: blk[k].flow_mol_comp[j].fix(flow_mol_comp[j]) if blk[k].pressure.fixed is True: Pflag[k] = True else: Pflag[k] = False if pressure is None: blk[k].pressure.fix(101325.0) else: blk[k].pressure.fix(pressure) if blk[k].temperature.fixed is True: Tflag[k] = True else: Tflag[k] = False if temperature is None: blk[k].temperature.fix(1500.0) else: blk[k].temperature.fix(temperature) for j in blk[k]._params.component_list: blk[k].mole_frac[j] = \ (value(blk[k].flow_mol_comp[j]) / sum(value(blk[k].flow_mol_comp[i]) for i in blk[k]._params.component_list)) # If input block, return flags, else release state flags = {"Fcflag": Fcflag, "Pflag": Pflag, "Tflag": Tflag} else: # Check when the state vars are fixed already result in dof 0 for k in blk.keys(): if degrees_of_freedom(blk[k]) != 0: raise Exception("State vars fixed but degrees of freedom " "for state block is not zero during " "initialization.") # Set solver options if outlvl > 1: stee = True else: stee = False opt = SolverFactory(solver) opt.options = optarg # --------------------------------------------------------------------- # Initialise values for k in blk.keys(): for j in blk[k]._params.component_list: if hasattr(blk[k], "cp_shomate_eqn"): calculate_variable_from_constraint( blk[k].cp_mol_comp[j], blk[k].cp_shomate_eqn[j]) if hasattr(blk[k], "enthalpy_shomate_eqn"): calculate_variable_from_constraint( blk[k].enth_mol_phase_comp["Vap", j], blk[k].enthalpy_shomate_eqn[j]) if hasattr(blk[k], "entropy_shomate_eqn"): calculate_variable_from_constraint( blk[k].entr_mol_phase_comp["Vap", j], blk[k].entropy_shomate_eqn[j]) if hasattr(blk[k], "partial_gibbs_energy_eqn"): calculate_variable_from_constraint( blk[k].gibbs_mol_phase_comp["Vap", j], blk[k].partial_gibbs_energy_eqn[j]) if hasattr(blk[k], "ideal_gas"): calculate_variable_from_constraint( blk[k].dens_mol_phase["Vap"], blk[k].ideal_gas) if hasattr(blk[k], "mixture_heat_capacity_eqn"): calculate_variable_from_constraint( blk[k].cp_mol, blk[k].mixture_heat_capacity_eqn) if hasattr(blk[k], "mixture_enthalpy_eqn"): calculate_variable_from_constraint(blk[k].enth_mol, blk[k].mixture_enthalpy_eqn) if hasattr(blk[k], "mixture_entropy_eqn"): calculate_variable_from_constraint(blk[k].entr_mol, blk[k].mixture_entropy_eqn) if hasattr(blk[k], "total_flow_eqn"): calculate_variable_from_constraint(blk[k].flow_mol, blk[k].total_flow_eqn) if hasattr(blk[k], "mixture_gibbs_eqn"): calculate_variable_from_constraint(blk[k].gibbs_mol, blk[k].mixture_gibbs_eqn) results = solve_indexed_blocks(opt, blk, tee=stee) if outlvl > 0: if results.solver.termination_condition \ == TerminationCondition.optimal: _log.info('{} Initialisation Step 1 Complete.'.format( blk.name)) else: _log.warning('{} Initialisation Step 1 Failed.'.format( blk.name)) # --------------------------------------------------------------------- if outlvl > 0: if outlvl > 0: _log.info('{} Initialisation Complete.'.format(blk.name)) if state_vars_fixed is False: if hold_state is True: return flags else: blk.release_state(flags)
def initialize(blk, outlvl=idaeslog.NOTSET, optarg={}, solver=None): ''' Initialisation routine for reaction package. Keyword Arguments: outlvl : sets output level of initialization routine optarg : solver options dictionary object (default={}) solver : str indicating whcih solver to use during initialization (default = None, use default solver) Returns: None ''' init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="reactions") solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="reactions") init_log.info_high('Starting initialization') # TODO - Update in the future as needed # Get a single representative block for getting config arguments for k in blk.keys(): break # Fix state variables if not already fixed # Fix state variables of the primary (solid) state block state_var_flags = fix_state_vars(blk[k].config.solid_state_block) # Fix values of secondary (gas) state block variables if not fixed, # as well as the solid density variable. # This is done to keep the initialization problem square Cflag = {} # Gas concentration flag Dflag = {} # Solid density flag for k in blk.keys(): for j in blk[k]._params.gas_component_list: if blk[k].gas_state_ref.dens_mol_comp[j].fixed is True: Cflag[k, j] = True else: Cflag[k, j] = False blk[k].gas_state_ref.dens_mol_comp[j].fix( blk[k].gas_state_ref.dens_mol_comp[j].value) if blk[k].solid_state_ref.dens_mass_skeletal.fixed is True: Dflag[k] = True else: Dflag[k] = False blk[k].solid_state_ref.dens_mass_skeletal.fix( blk[k].solid_state_ref.dens_mass_skeletal.value) # Create solver opt = get_solver(solver, optarg) # Initialise values for k in blk.keys(): if hasattr(blk[k], "OC_conv_eqn"): calculate_variable_from_constraint(blk[k].OC_conv, blk[k].OC_conv_eqn) if hasattr(blk[k], "OC_conv_temp_eqn"): calculate_variable_from_constraint(blk[k].OC_conv_temp, blk[k].OC_conv_temp_eqn) for j in blk[k]._params.rate_reaction_idx: if hasattr(blk[k], "rate_constant_eqn"): calculate_variable_from_constraint( blk[k].k_rxn[j], blk[k].rate_constant_eqn[j]) if hasattr(blk[k], "gen_rate_expression"): calculate_variable_from_constraint( blk[k].reaction_rate[j], blk[k].gen_rate_expression[j]) # Solve property block if non-empty free_vars = 0 for k in blk.keys(): free_vars += number_unfixed_variables_in_activated_equalities( blk[k]) if free_vars > 0: with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = solve_indexed_blocks(opt, [blk], tee=slc.tee) else: res = "" init_log.info_high("reactions initialization complete {}.".format( idaeslog.condition(res))) # --------------------------------------------------------------------- # Revert state vars and other variables to pre-initialization states # Revert state variables of the primary (solid) state block revert_state_vars(blk[k].config.solid_state_block, state_var_flags) for k in blk.keys(): for j in blk[k]._params.gas_component_list: if Cflag[k, j] is False: blk[k].gas_state_ref.dens_mol_comp[j].unfix() if Dflag[k] is False: blk[k].solid_state_ref.dens_mass_skeletal.unfix() init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="reactions") init_log.info_high('States released.')
def test_nonlinear(self): m = ConcreteModel() m.x = Var() m.y = Var(initialize=0) m.c = Constraint(expr=m.x**2 == 16) m.x.set_value(1.0) # set an initial value calculate_variable_from_constraint(m.x, m.c, linesearch=False) self.assertAlmostEqual(value(m.x), 4) # test that infeasible constraint throws error m.d = Constraint(expr=m.x**2 == -1) m.x.set_value(1.25) # set the initial value with self.assertRaisesRegexp( RuntimeError, 'Iteration limit \(10\) reached'): calculate_variable_from_constraint( m.x, m.d, iterlim=10, linesearch=False) # same problem should throw a linesearch error if linesearch is on m.x.set_value(1.25) # set the initial value with self.assertRaisesRegexp( RuntimeError, "Linesearch iteration limit reached"): calculate_variable_from_constraint( m.x, m.d, iterlim=10, linesearch=True) # same problem should raise an error if initialized at 0 m.x = 0 with self.assertRaisesRegexp( RuntimeError, "Initial value for variable results in a " "derivative value that is very close to zero."): calculate_variable_from_constraint(m.x, m.c) # same problem should raise a value error if we are asked to # solve for a variable that is not present with self.assertRaisesRegexp( ValueError, "Variable derivative == 0"): calculate_variable_from_constraint(m.y, m.c) # should succeed with or without a linesearch m.e = Constraint(expr=(m.x - 2.0)**2 - 1 == 0) m.x.set_value(3.1) calculate_variable_from_constraint(m.x, m.e, linesearch=False) self.assertAlmostEqual(value(m.x), 3) m.x.set_value(3.1) calculate_variable_from_constraint(m.x, m.e, linesearch=True) self.assertAlmostEqual(value(m.x), 3) # we expect this to succeed with the linesearch m.f = Constraint(expr=1.0/(1.0+exp(-m.x))-0.5 == 0) m.x.set_value(3.0) calculate_variable_from_constraint(m.x, m.f, linesearch=True) self.assertAlmostEqual(value(m.x), 0) # we expect this to fail without a linesearch m.x.set_value(3.0) with self.assertRaisesRegexp( RuntimeError, "Newton's method encountered a derivative " "that was too close to zero"): calculate_variable_from_constraint(m.x, m.f, linesearch=False) # Calculate the bubble point of Benzene. THe first step # computed by calculate_variable_from_constraint will make the # second term become complex, and the evaluation will fail. # This tests that the algorithm cleanly continues m = ConcreteModel() m.x = Var() m.pc = 48.9e5 m.tc = 562.2 m.psc = {'A': -6.98273, 'B': 1.33213, 'C': -2.62863, 'D': -3.33399, } m.p = 101325 @m.Constraint() def f(m): return m.pc * \ exp((m.psc['A'] * (1 - m.x / m.tc) + m.psc['B'] * (1 - m.x / m.tc)**1.5 + m.psc['C'] * (1 - m.x / m.tc)**3 + m.psc['D'] * (1 - m.x / m.tc)**6 ) / (1 - (1 - m.x / m.tc))) - m.p == 0 m.x.set_value(298.15) calculate_variable_from_constraint(m.x, m.f, linesearch=False) self.assertAlmostEqual(value(m.x), 353.31855602) m.x.set_value(298.15) calculate_variable_from_constraint(m.x, m.f, linesearch=True) self.assertAlmostEqual(value(m.x), 353.31855602) # Starting with an invalid guess (above TC) should raise an # exception m.x.set_value(600) output = six.StringIO() with LoggingIntercept(output, 'pyomo', logging.WARNING): if six.PY2: expectedException = ValueError else: expectedException = TypeError with self.assertRaises(expectedException): calculate_variable_from_constraint(m.x, m.f, linesearch=False) self.assertIn('Encountered an error evaluating the expression ' 'at the initial guess', output.getvalue()) # This example triggers an expression evaluation error if the # linesearch is turned off because the first step in Newton's # method will cause the LHS to become complex m = ConcreteModel() m.x = Var() m.c = Constraint(expr=(1/m.x**3)**0.5 == 100) m.x = .1 calculate_variable_from_constraint(m.x, m.c, linesearch=True) self.assertAlmostEqual(value(m.x), 0.046415888) m.x = .1 output = six.StringIO() with LoggingIntercept(output, 'pyomo', logging.WARNING): with self.assertRaises(ValueError): # Note that the ValueError is different between Python 2 # and Python 3: in Python 2 it is a specific error # "negative number cannot be raised to a fractional # power", and We mock up that error in Python 3 by # raising a generic ValueError in # calculate_variable_from_constraint calculate_variable_from_constraint(m.x, m.c, linesearch=False) self.assertIn("Newton's method encountered an error evaluating " "the expression.", output.getvalue()) # This is a completely contrived example where the linesearch # hits the iteration limit before Newton's method ever finds a # feasible step m = ConcreteModel() m.x = Var() m.c = Constraint(expr=m.x**0.5 == -1e-8) m.x = 1e-8#197.932807183 with self.assertRaisesRegexp( RuntimeError, "Linesearch iteration limit reached; " "remaining residual = {function evaluation error}"): calculate_variable_from_constraint(m.x, m.c, linesearch=True, alpha_min=.5)
def test_initialize_value(self): m = ConcreteModel() m.x = Var() m.y = Var(initialize=0) m.c = Constraint(expr=m.x == 5) m.x.set_value(None) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.x.set_value(None) m.x.setlb(3) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.x.set_value(None) m.x.setlb(-10) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.x.set_value(None) m.x.setub(10) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.x.set_value(None) m.x.setlb(3) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.x.set_value(None) m.x.setlb(None) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.x.set_value(None) m.x.setub(-10) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.lt = Constraint(expr=m.x <= m.y) with self.assertRaisesRegexp( ValueError, "Constraint must be an equality constraint"): calculate_variable_from_constraint(m.x, m.lt)
def test_initialize_value(self): m = ConcreteModel() m.x = Var() m.y = Var(initialize=0) m.c = Constraint(expr=m.x == 5) m.x.set_value(None) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.x.set_value(None) m.x.setlb(3) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.x.set_value(None) m.x.setlb(-10) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.x.set_value(None) m.x.setub(10) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.x.set_value(None) m.x.setlb(3) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.x.set_value(None) m.x.setlb(None) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.x.set_value(None) m.x.setub(-10) calculate_variable_from_constraint(m.x, m.c) self.assertEqual(value(m.x), 5) m.lt = Constraint(expr=m.x <= m.y) with self.assertRaisesRegex( ValueError, "Constraint must be an equality constraint"): calculate_variable_from_constraint(m.x, m.lt)
def initialize(blk, state_args=None, hold_state=False, state_vars_fixed=False, outlvl=idaeslog.NOTSET, solver=None, optarg=None): """ Initialization routine for property package. Keyword Arguments: state_args : Dictionary with initial guesses for the state vars chosen. Note that if this method is triggered through the control volume, and if initial guesses were not provided at the unit model level, the control volume passes the inlet values as initial guess. Keys for the state_args dictionary are: flow_mass, temperature, and mass_frac_comp outlvl : sets output level of initialization routine optarg : solver options dictionary object (default=None, use default solver options) solver : str indicating which solver to use during initialization (default = None, use default solver) hold_state : flag indicating whether the initialization routine should unfix any state variables fixed during initialization (default=False). - True - states varaibles are not unfixed, and a dict of returned containing flags for which states were fixed during initialization. - False - state variables are unfixed after initialization by calling the relase_state method Returns: If hold_states is True, returns a dict containing flags for which states were fixed during initialization. """ init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="properties") solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="properties") init_log.info_high('Starting initialization') # Deactivate the constraints specific for outlet block i.e. # when defined state is False for k in blk.keys(): if blk[k].config.defined_state is False: blk[k].sum_component_eqn.deactivate() # Fix state variables if not already fixed if state_vars_fixed is False: flags = fix_state_vars(blk, state_args) else: # Check when the state vars are fixed already result in dof 0 for k in blk.keys(): if degrees_of_freedom(blk[k]) != 0: raise Exception("State vars fixed but degrees of freedom " "for state block is not zero during " "initialization.") # Create solver opt = get_solver(solver, optarg) # --------------------------------------------------------------------- # Initialise values for k in blk.keys(): if hasattr(blk[k], "density_skeletal_constraint"): calculate_variable_from_constraint( blk[k].dens_mass_skeletal, blk[k].density_skeletal_constraint) if hasattr(blk[k], "mixture_heat_capacity_eqn"): calculate_variable_from_constraint( blk[k].cp_mass, blk[k].mixture_heat_capacity_eqn) if hasattr(blk[k], "mixture_enthalpy_eqn"): calculate_variable_from_constraint(blk[k].enth_mass, blk[k].mixture_enthalpy_eqn) for j in blk[k]._params.component_list: if hasattr(blk[k], "cp_shomate_eqn"): calculate_variable_from_constraint( blk[k].cp_mol_comp[j], blk[k].cp_shomate_eqn[j]) if hasattr(blk[k], "enthalpy_shomate_eqn"): calculate_variable_from_constraint( blk[k].enth_mol_comp[j], blk[k].enthalpy_shomate_eqn[j]) # Solve property block if non-empty free_vars = 0 for k in blk.keys(): free_vars += number_unfixed_variables_in_activated_equalities( blk[k]) if free_vars > 0: with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = solve_indexed_blocks(opt, [blk], tee=slc.tee) else: res = "" init_log.info_high("Initialization complete {}.".format( idaeslog.condition(res))) # --------------------------------------------------------------------- if state_vars_fixed is False: if hold_state is True: return flags else: blk.release_state(flags)