def test_atan(self): m = pe.Block(concrete=True) m.x = pe.Var() m.c = pe.Constraint(expr=pe.inequality(body=pe.atan(m.x), lower=-0.5, upper=0.5)) fbbt(m) self.assertAlmostEqual(pe.value(m.x.lb), math.tan(-0.5)) self.assertAlmostEqual(pe.value(m.x.ub), math.tan(0.5))
def test_GDP_nonlinear_objective(self): m = ConcreteModel() m.x = Var(bounds=(-1, 10)) m.y = Var(bounds=(2, 3)) m.d = Disjunction(expr=[ [m.x + m.y >= 5], [m.x - m.y <= 3] ]) m.o = Objective(expr=m.x ** 2) SolverFactory('gdpopt').solve( m, strategy='LOA', mip_solver=mip_solver, nlp_solver=nlp_solver ) self.assertAlmostEqual(value(m.o), 0) m = ConcreteModel() m.x = Var(bounds=(-1, 10)) m.y = Var(bounds=(2, 3)) m.d = Disjunction(expr=[ [m.x + m.y >= 5], [m.x - m.y <= 3] ]) m.o = Objective(expr=-m.x ** 2, sense=maximize) SolverFactory('gdpopt').solve( m, strategy='LOA', mip_solver=mip_solver, nlp_solver=nlp_solver ) self.assertAlmostEqual(value(m.o), 0)
def test_acos(self): m = pe.Block(concrete=True) m.x = pe.Var() m.c = pe.Constraint(expr=pe.inequality(body=pe.acos(m.x), lower=1, upper=2)) fbbt(m) self.assertAlmostEqual(pe.value(m.x.lb), math.cos(2)) self.assertAlmostEqual(pe.value(m.x.ub), math.cos(1))
def save_cost_components(m, outdir): """ Save values for all individual components of total system cost on NPV basis. """ cost_dict = dict() for annual_cost in m.Cost_Components_Per_Period: cost = getattr(m, annual_cost) # note: storing value() instead of the expression may save # some memory while this function runs cost_dict[annual_cost] = value(sum( cost[p] * m.bring_annual_costs_to_base_year[p] for p in m.PERIODS )) for tp_cost in m.Cost_Components_Per_TP: cost = getattr(m, tp_cost) cost_dict[tp_cost] = value(sum( cost[t] * m.tp_weight_in_year[t] * m.bring_annual_costs_to_base_year[m.tp_period[t]] for t in m.TIMEPOINTS )) write_table( m, cost_dict.keys(), output_file=os.path.join(outdir, "cost_components.tab"), headings=('component', 'npv_cost'), values=lambda m, c: (c, cost_dict[c]), digits=16 )
def test_ignore_nonlinear(self): m = ConcreteModel() m.v1 = Var() m.c1 = Constraint(expr=m.v1 * m.v1 >= 2) self.assertEqual(value(m.c1.lower), 2) self.assertFalse(m.c1.has_ub()) TransformationFactory('core.tighten_constraints_from_vars').apply_to(m) self.assertEqual(value(m.c1.lower), 2) self.assertFalse(m.c1.has_ub())
def test_pow(self): m = pe.ConcreteModel() m.x = pe.Var(initialize=2.0) m.y = pe.Var(initialize=3.0) e = m.x ** m.y derivs = reverse_ad(e) symbolic = reverse_sd(e) self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3) self.assertAlmostEqual(derivs[m.y], pe.value(symbolic[m.y]), tol+3) self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol) self.assertAlmostEqual(derivs[m.y], approx_deriv(e, m.y), tol)
def approx_deriv(expr, wrt, delta=0.001): numerator = 0 wrt.value += 2*delta numerator -= pe.value(expr) wrt.value -= delta numerator += 8*pe.value(expr) wrt.value -= 2*delta numerator -= 8*pe.value(expr) wrt.value -= delta numerator += pe.value(expr) wrt.value += 2*delta return numerator / (12*delta)
def test_less_than_constraint(self): m = ConcreteModel() m.v1 = Var(initialize=7, bounds=(7, 10)) m.v2 = Var(initialize=2, bounds=(2, 5)) m.v3 = Var(initialize=6, bounds=(6, 9)) m.v4 = Var(initialize=1, bounds=(1, 1)) m.c1 = Constraint(expr=m.v1 <= m.v2 + m.v3 + m.v4) self.assertEqual(value(m.c1.upper), 0) self.assertFalse(m.c1.has_lb()) TransformationFactory('core.tighten_constraints_from_vars').apply_to(m) self.assertEqual(value(m.c1.upper), 0) self.assertEqual(value(m.c1.lower), -8)
def test_unbounded_var(self): """test with unbounded variables""" m = ConcreteModel() m.v1 = Var(initialize=7) m.v2 = Var(initialize=2, bounds=(2, 5)) m.v3 = Var(initialize=6, bounds=(6, 9)) m.v4 = Var(initialize=1, bounds=(1, 1)) m.c1 = Constraint(expr=m.v1 <= 2 * m.v2 + m.v3 + m.v4) self.assertEqual(value(m.c1.upper), 0) self.assertFalse(m.c1.has_lb()) TransformationFactory('core.tighten_constraints_from_vars').apply_to(m) self.assertEqual(value(m.c1.upper), 0) self.assertFalse(m.c1.has_lb())
def test_unbounded_one_direction(self): """Unbounded in one direction""" m = ConcreteModel() m.v1 = Var(initialize=7, bounds=(-float('inf'), 10)) m.v2 = Var(initialize=2, bounds=(2, 5)) m.v3 = Var(initialize=6, bounds=(6, 9)) m.v4 = Var(initialize=1, bounds=(1, 1)) m.c1 = Constraint(expr=m.v1 <= 2 * m.v2 + m.v3 + m.v4) self.assertEqual(value(m.c1.upper), 0) self.assertFalse(m.c1.has_lb()) TransformationFactory('core.tighten_constraints_from_vars').apply_to(m) self.assertEqual(value(m.c1.upper), -1) self.assertFalse(m.c1.has_lb())
def test_constraint_bound_tightening(self): # Check for no coefficients m = ConcreteModel() m.v1 = Var(initialize=7, bounds=(7, 10)) m.v2 = Var(initialize=2, bounds=(2, 5)) m.v3 = Var(initialize=6, bounds=(6, 9)) m.v4 = Var(initialize=1, bounds=(1, 1)) m.c1 = Constraint(expr=m.v1 >= m.v2 + m.v3 + m.v4 + 1) self.assertEqual(value(m.c1.upper), 0) self.assertFalse(m.c1.has_lb()) TransformationFactory('core.tighten_constraints_from_vars').apply_to(m) self.assertEqual(value(m.c1.upper), 0) self.assertEqual(value(m.c1.lower), 0)
def test_constraint_with_coef(self): """Test with coefficient on constraint.""" m = ConcreteModel() m.v1 = Var(initialize=7, bounds=(7, 10)) m.v2 = Var(initialize=2, bounds=(2, 5)) m.v3 = Var(initialize=6, bounds=(6, 9)) m.v4 = Var(initialize=1, bounds=(1, 1)) m.c1 = Constraint(expr=m.v1 <= 2 * m.v2 + m.v3 + m.v4) self.assertEqual(value(m.c1.upper), 0) self.assertFalse(m.c1.has_lb()) TransformationFactory('core.tighten_constraints_from_vars').apply_to(m) self.assertEqual(value(m.c1.upper), -1) self.assertEqual(value(m.c1.lower), -13)
def test_nested(self): m = pe.ConcreteModel() m.x = pe.Var(initialize=2) m.y = pe.Var(initialize=3) m.p = pe.Param(initialize=0.5, mutable=True) e = pe.exp(m.x**m.p + 3.2*m.y - 12) derivs = reverse_ad(e) symbolic = reverse_sd(e) self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3) self.assertAlmostEqual(derivs[m.y], pe.value(symbolic[m.y]), tol+3) self.assertAlmostEqual(derivs[m.p], pe.value(symbolic[m.p]), tol+3) self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol) self.assertAlmostEqual(derivs[m.y], approx_deriv(e, m.y), tol) self.assertAlmostEqual(derivs[m.p], approx_deriv(e, m.p), tol)
def test_add(self): x_bounds = [(-2.5, 2.8), (-2.5, -0.5), (0.5, 2.8), (-2.5, 0), (0, 2.8), (-2.5, -1), (1, 2.8), (-1, -0.5), (0.5, 1)] c_bounds = [(-2.5, 2.8), (-2.5, -0.5), (0.5, 2.8), (-2.5, 0), (0, 2.8), (-2.5, -1), (1, 2.8), (-1, -0.5), (0.5, 1)] for xl, xu in x_bounds: for cl, cu in c_bounds: m = pe.Block(concrete=True) m.x = pe.Var(bounds=(xl, xu)) m.y = pe.Var() m.p = pe.Param(mutable=True) m.p.value = 1 m.c = pe.Constraint(expr=pe.inequality(body=m.x+m.y+(m.p+1), lower=cl, upper=cu)) new_bounds = fbbt(m) self.assertEqual(new_bounds[m.x], (pe.value(m.x.lb), pe.value(m.x.ub))) self.assertEqual(new_bounds[m.y], (pe.value(m.y.lb), pe.value(m.y.ub))) x = np.linspace(pe.value(m.x.lb), pe.value(m.x.ub), 100) z = np.linspace(pe.value(m.c.lower), pe.value(m.c.upper), 100) if m.y.lb is None: yl = -np.inf else: yl = m.y.lb if m.y.ub is None: yu = np.inf else: yu = m.y.ub for _x in x: _y = z - _x - m.p.value - 1 self.assertTrue(np.all(yl <= _y)) self.assertTrue(np.all(yu >= _y))
def test_cos(self): m = pe.Block(concrete=True) m.x = pe.Var(bounds=(0, math.pi)) m.c = pe.Constraint(expr=pe.inequality(body=pe.cos(m.x), lower=-0.5, upper=0.5)) fbbt(m) self.assertAlmostEqual(pe.value(m.x.lb), math.acos(0.5)) self.assertAlmostEqual(pe.value(m.x.ub), math.acos(-0.5)) m = pe.Block(concrete=True) m.x = pe.Var() m.c = pe.Constraint(expr=pe.inequality(body=pe.cos(m.x), lower=-0.5, upper=0.5)) fbbt(m) self.assertEqual(m.x.lb, None) self.assertEqual(m.x.ub, None)
def get_value(obj): """ Retrieve value of one element of a Variable or Expression, converting division-by-zero to nan and uninitialized values to None. """ try: val = value(obj) except ZeroDivisionError: # diagnostic expressions sometimes have 0 denominator, # e.g., AverageFuelCosts for unused fuels; val = float("nan") except ValueError: # If variables are not used in constraints or the # objective function, they will never get values, and # give a ValueError at this point. # Note: for variables this could instead use 0 if allowed, or # otherwise the closest bound. if getattr(obj, 'value', 0) is None: val = None # Pyomo will print an error before it raises the ValueError, # but we say more here to help users figure out what's going on. print ( "WARNING: variable {} has not been assigned a value. This " "usually indicates a coding error: either the variable is " "not needed or it has accidentally been omitted from all " "constraints and the objective function.".format(obj.name) ) else: # Caught some other ValueError raise return val
def propagate_solution(self, augmented_model, original_model): for avar in augmented_model.component_objects(ctype=aml.Var, descend_into=True): cuid = aml.ComponentUID(avar) original_v = cuid.find_component_on(original_model) for k in avar: original_v[k].value = aml.value(avar[k])
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_as_good_with_iteration_rand(self): # initialize model with data m = build_model() # create ipopt solver optsolver = SolverFactory('ipopt') optsolver.solve(m) for i in range(10): m2 = build_model() SolverFactory('multistart').solve(m2, iterations=10) m_objectives = m.component_data_objects(Objective, active=True) m_obj = next(m_objectives, None) m2_objectives = m2.component_data_objects(Objective, active=True) m2_obj = next(m2_objectives,None) self.assertTrue((value(m2_obj.expr)) >= (value(m_obj.expr) - .001)) del m2
def write_table_old(model, *indexes, **kwargs): # there may be a way to accept specific named keyword arguments and also an # open-ended list of positional arguments (*indexes), but I don't know what that is. output_file = kwargs["output_file"] headings = kwargs["headings"] values = kwargs["values"] print "Writing {file} ...".format(file=output_file), sys.stdout.flush() # display the part line to the user start=time.time() # create a master indexing set # this is a list of lists, even if only one list was specified idx = itertools.product(*indexes) with open(output_file, 'wb') as f: w = csv.writer(f, dialect="ampl-tab") # write header row w.writerow(list(headings)) # write the data w.writerows( tuple(value(v) for v in values(model, *x)) for x in idx ) print "time taken: {dur:.2f}s".format(dur=time.time()-start)
def test_atan(self): m = pe.ConcreteModel() m.x = pe.Var(initialize=2.0) e = pe.atan(m.x) derivs = reverse_ad(e) symbolic = reverse_sd(e) self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3) self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_set_expr_inline(self): """Test expr= option (inline expression)""" model = ConcreteModel() model.A = RangeSet(1,4) model.x = Var(model.A,initialize=2) model.c = Constraint(expr=(0, sum(model.x[i] for i in model.A), 1)) self.assertEqual(model.c(), 8) self.assertEqual(value(model.c.body), 8)
def test_fixed_var_propagate(self): """Test for transitivity in a variable equality set.""" m = ConcreteModel() m.v1 = Var(initialize=1) m.v2 = Var(initialize=2) m.v3 = Var(initialize=3) m.v4 = Var(initialize=4) m.c1 = Constraint(expr=m.v1 == m.v2) m.c2 = Constraint(expr=m.v2 == m.v3) m.c3 = Constraint(expr=m.v3 == m.v4) m.v2.fix() m.s = RangeSet(4) m.x = Var(m.s, initialize=5) m.c = Constraint(m.s) m.c.add(1, expr=m.x[1] == m.x[3]) m.c.add(2, expr=m.x[2] == m.x[4]) m.c.add(3, expr=m.x[2] == m.x[3]) m.c.add(4, expr=m.x[1] == 1) m.y = Var([1, 2], initialize=3) m.c_too = Constraint(expr=m.y[1] == m.y[2]) m.z1 = Var() m.z2 = Var() m.ignore_me = Constraint(expr=m.y[1] + m.z1 + m.z2 <= 0) TransformationFactory('contrib.propagate_fixed_vars').apply_to(m) self.assertTrue(m.v1.fixed) self.assertTrue(m.v2.fixed) self.assertTrue(m.v3.fixed) self.assertTrue(m.v4.fixed) self.assertEquals(value(m.v4), 2) self.assertTrue(m.x[1].fixed) self.assertTrue(m.x[2].fixed) self.assertTrue(m.x[3].fixed) self.assertTrue(m.x[4].fixed) self.assertEquals(value(m.x[4]), 1) self.assertFalse(m.y[1].fixed) self.assertFalse(m.y[2].fixed) self.assertFalse(m.z1.fixed) self.assertFalse(m.z2.fixed)
def format_row(row): row = [value(v) for v in row] sig_digits = "{0:." + str(digits) + "g}" for (i, v) in enumerate(row): if isinstance(v, float): if abs(v) < 1e-10: row[i] = 0 else: row[i] = sig_digits.format(v) return tuple(row)
def test_log(self): c_bounds = [(-2.5, 2.8), (-2.5, -0.5), (0.5, 2.8), (-2.5, 0), (0, 2.8), (-2.5, -1), (1, 2.8), (-1, -0.5), (0.5, 1)] for cl, cu in c_bounds: m = pe.Block(concrete=True) m.x = pe.Var() m.c = pe.Constraint(expr=pe.inequality(body=pe.log(m.x), lower=cl, upper=cu)) fbbt(m) z = np.linspace(pe.value(m.c.lower), pe.value(m.c.upper), 100) if m.x.lb is None: xl = -np.inf else: xl = pe.value(m.x.lb) if m.x.ub is None: xu = np.inf else: xu = pe.value(m.x.ub) x = np.exp(z) self.assertTrue(np.all(xl <= x)) self.assertTrue(np.all(xu >= x))
def test_LOA_8PP_maxBinary(self): """Test logic-based OA with max_binary initialization.""" exfile = import_file( join(exdir, 'eight_process', 'eight_proc_model.py')) eight_process = exfile.build_eight_process_flowsheet() SolverFactory('gdpopt').solve( eight_process, strategy='LOA', init_strategy='max_binary', mip_solver=mip_solver, nlp_solver=nlp_solver) self.assertTrue(fabs(value(eight_process.profit.expr) - 68) <= 1E-2)
def test_solve_constant_obj(self): m = ConcreteModel() m.x = Var(bounds=(-5, 5)) m.c = Constraint(expr=m.x >= 1) m.o = Objective(expr=1) output = StringIO() with LoggingIntercept(output, 'pyomo.contrib.gdpopt', logging.INFO): SolverFactory('gdpopt').solve(m, mip_solver=mip_solver) self.assertIn("Your model is an LP (linear program).", output.getvalue().strip()) self.assertAlmostEqual(value(m.o.expr), 1)
def test_GLOA_nonconvex_HENS(self): exfile = import_file(join(exdir, 'small_lit', 'nonconvex_HEN.py')) model = exfile.build_gdp_model() SolverFactory('gdpopt').solve( model, strategy='GLOA', mip_solver=mip_solver, nlp_solver=global_nlp_solver, nlp_solver_args=global_nlp_solver_args, tee=False) objective_value = value(model.objective.expr) self.assertAlmostEqual(objective_value * 1E-5, 1.14385, 2)
def test_LOA_strip_pack_maxBinary(self): """Test LOA with strip packing using max_binary initialization.""" exfile = import_file( join(exdir, 'strip_packing', 'strip_packing_concrete.py')) strip_pack = exfile.build_rect_strip_packing_model() SolverFactory('gdpopt').solve( strip_pack, strategy='LOA', init_strategy='max_binary', mip_solver=mip_solver, nlp_solver=nlp_solver) self.assertTrue( fabs(value(strip_pack.total_length.expr) - 11) <= 1E-2)
def test_LOA_strip_pack_default_init(self): """Test logic-based outer approximation with strip packing.""" exfile = import_file( join(exdir, 'strip_packing', 'strip_packing_concrete.py')) strip_pack = exfile.build_rect_strip_packing_model() SolverFactory('gdpopt').solve( strip_pack, strategy='LOA', mip_solver=mip_solver, nlp_solver=nlp_solver) self.assertTrue( fabs(value(strip_pack.total_length.expr) - 11) <= 1E-2)
def test_solution(self, btx_ftpz, btx_fctp): # liq_out port assert (pytest.approx(0.463370, abs=1e-3) == value( btx_ftpz.fs.unit.liq_out.flow_mol[0])) assert (pytest.approx(0.33313, abs=1e-3) == value( btx_ftpz.fs.unit.liq_out.mole_frac_comp[0, "benzene"])) assert (pytest.approx(0.66686, abs=1e-3) == value( btx_ftpz.fs.unit.liq_out.mole_frac_comp[0, "toluene"])) assert (pytest.approx(370.567, abs=1e-3) == value( btx_ftpz.fs.unit.liq_out.temperature[0])) assert (pytest.approx(101325, abs=1e-3) == value( btx_ftpz.fs.unit.liq_out.pressure[0])) # vap_out port assert (pytest.approx(1.5366, abs=1e-3) == value( btx_ftpz.fs.unit.vap_out.flow_mol[0])) assert (pytest.approx(0.55031, abs=1e-3) == value( btx_ftpz.fs.unit.vap_out.mole_frac_comp[0, "benzene"])) assert (pytest.approx(0.44968, abs=1e-3) == value( btx_ftpz.fs.unit.vap_out.mole_frac_comp[0, "toluene"])) assert (pytest.approx(370.567, abs=1e-3) == value( btx_ftpz.fs.unit.vap_out.temperature[0])) assert (pytest.approx(101325, abs=1e-3) == value( btx_ftpz.fs.unit.vap_out.pressure[0])) # liq_out port assert (pytest.approx(0.15436, abs=1e-3) == value( btx_fctp.fs.unit.liq_out.flow_mol_comp[0, "benzene"])) assert (pytest.approx(0.30900, abs=1e-3) == value( btx_fctp.fs.unit.liq_out.flow_mol_comp[0, "toluene"])) assert (pytest.approx(370.567, abs=1e-3) == value( btx_fctp.fs.unit.liq_out.temperature[0])) assert (pytest.approx(101325, abs=1e-3) == value( btx_fctp.fs.unit.liq_out.pressure[0])) # vap_out port assert (pytest.approx(0.84560, abs=1e-3) == value( btx_fctp.fs.unit.vap_out.flow_mol_comp[0, "benzene"])) assert (pytest.approx(0.69097, abs=1e-3) == value( btx_fctp.fs.unit.vap_out.flow_mol_comp[0, "toluene"])) assert (pytest.approx(370.567, abs=1e-3) == value( btx_fctp.fs.unit.vap_out.temperature[0])) assert (pytest.approx(101325, abs=1e-3) == value( btx_fctp.fs.unit.vap_out.pressure[0]))
def check_recycle_model(self, m, rel=False): for arc in m.component_data_objects(Arc): self.assertTrue(self.is_converged(arc, rel=rel)) for port in m.component_data_objects(Port): self.assertTrue( self.intensive_equal(port, temperature=value( m.feed.outlet.temperature), pressure=value(m.feed.outlet.pressure))) if rel: # in == out for i in m.feed.outlet.flow: s = value(m.prod.inlet.flow[i]) d = value(m.feed.outlet.flow[i]) self.assertAlmostEqual((s - d) / s, 0, places=5) for i in m.feed.outlet.expr_idx: s = value(m.prod.inlet.expr_idx[i]) d = value(m.feed.outlet.expr_idx[i]) self.assertAlmostEqual((s - d) / s, 0, places=5) s = value(m.prod.inlet.expr) d = value(m.feed.outlet.expr) self.assertAlmostEqual((s - d) / s, 0, places=5) # check the expressions work, should be negative in prod for i in m.feed.outlet.expr_idx: s = value(-m.prod.actual_var_idx_in[i]) d = value(m.feed.expr_var_idx_out[i]) self.assertAlmostEqual((s - d) / s, 0, places=5) s = value(-m.prod.actual_var_in) d = value(m.feed.expr_var_out) self.assertAlmostEqual((s - d) / s, 0, places=5) else: # in == out for i in m.feed.outlet.flow: self.assertAlmostEqual(value(m.prod.inlet.flow[i]), value(m.feed.outlet.flow[i]), places=5) for i in m.feed.outlet.expr_idx: self.assertAlmostEqual(value(m.prod.inlet.expr_idx[i]), value(m.feed.outlet.expr_idx[i]), places=5) self.assertAlmostEqual(value(m.prod.inlet.expr), value(m.feed.outlet.expr), places=5) # check the expressions work, should be negative in prod for i in m.feed.outlet.expr_idx: self.assertAlmostEqual(value(-m.prod.actual_var_idx_in[i]), value(m.feed.expr_var_idx_out[i]), places=5) self.assertAlmostEqual(value(-m.prod.actual_var_in), value(m.feed.expr_var_out), places=5)
def test_external_grey_box_react_example_maximize_cb_outputs_scaling(self): ex = import_file( os.path.join(example_dir, 'external_grey_box', 'react_example', 'maximize_cb_ratio_residuals.py')) aoptions = { 'nlp_scaling_method': 'user-scaling', 'output_file': '_cyipopt-external-greybox-react-scaling.log', 'file_print_level': 10 } m = ex.maximize_cb_ratio_residuals_with_output_scaling( additional_options=aoptions) self.assertAlmostEqual(pyo.value(m.reactor.inputs['sv']), 1.26541996, places=3) self.assertAlmostEqual(pyo.value(m.reactor.inputs['cb']), 1071.7410089, places=2) self.assertAlmostEqual(pyo.value(m.reactor.outputs['cb_ratio']), 0.15190409266, places=3) with open('_cyipopt-external-greybox-react-scaling.log', 'r') as fd: solver_trace = fd.read() os.remove('_cyipopt-external-greybox-react-scaling.log') self.assertIn('nlp_scaling_method = user-scaling', solver_trace) self.assertIn( 'output_file = _cyipopt-external-greybox-react-scaling.log', solver_trace) self.assertIn('objective scaling factor = 1', solver_trace) self.assertIn('x scaling provided', solver_trace) self.assertIn('c scaling provided', solver_trace) self.assertIn('d scaling provided', solver_trace) self.assertIn('DenseVector "x scaling vector" with 7 elements:', solver_trace) self.assertIn('x scaling vector[ 2]= 1.2000000000000000e+00', solver_trace) self.assertIn('x scaling vector[ 7]= 1.7000000000000000e+00', solver_trace) self.assertIn('x scaling vector[ 6]= 1.1000000000000001e+00', solver_trace) self.assertIn('x scaling vector[ 1]= 1.3000000000000000e+00', solver_trace) self.assertIn('x scaling vector[ 3]= 1.3999999999999999e+00', solver_trace) self.assertIn('x scaling vector[ 4]= 1.5000000000000000e+00', solver_trace) self.assertIn('x scaling vector[ 5]= 1.6000000000000001e+00', solver_trace) self.assertIn('DenseVector "c scaling vector" with 6 elements:', solver_trace) self.assertIn('c scaling vector[ 1]= 4.2000000000000000e+01', solver_trace) self.assertIn('c scaling vector[ 2]= 1.0000000000000001e-01', solver_trace) self.assertIn('c scaling vector[ 3]= 2.0000000000000001e-01', solver_trace) self.assertIn('c scaling vector[ 4]= 2.9999999999999999e-01', solver_trace) self.assertIn('c scaling vector[ 5]= 4.0000000000000002e-01', solver_trace) self.assertIn('c scaling vector[ 6]= 1.0000000000000000e+01', solver_trace)
def _set_rate_rxn_scaling(rxn_params, unit, min_scale=1e-3): for i in rxn_params.rate_reaction_idx: scale = value(unit.control_volume.reactions[0.0].reaction_rate[i].expr) iscale.set_scaling_factor( unit.control_volume.rate_reaction_extent[0.0, i], 1000 / scale)
def test_vars(self, frame): # Check that all necessary variables have been constructed and have # the correct values assert isinstance(frame.props[1].flow_mol, Expression) assert value(frame.props[1].flow_mol) == 300 assert isinstance(frame.props[1].flow_mol_comp, Var) assert len(frame.props[1].flow_mol_comp) == 3 for i in frame.props[1].flow_mol_comp: assert i in frame.props[1].params.component_list assert frame.props[1].flow_mol_comp[i].value == 100 assert frame.props[1].flow_mol_comp[i].lb == 0 assert frame.props[1].flow_mol_comp[i].ub == 200 assert check_units_equivalent(frame.props[1].flow_mol_comp, pyunits.mol / pyunits.s) assert isinstance(frame.props[1].mole_frac_comp, Var) assert len(frame.props[1].mole_frac_comp) == 3 for i in frame.props[1].mole_frac_comp: assert i in frame.props[1].params.component_list assert frame.props[1].mole_frac_comp[i].value == 1 / 3 assert check_units_equivalent(frame.props[1].mole_frac_comp, None) assert isinstance(frame.props[1].pressure, Var) assert frame.props[1].pressure.value == 3e5 assert frame.props[1].pressure.lb == 1e5 assert frame.props[1].pressure.ub == 5e5 assert check_units_equivalent(frame.props[1].pressure, pyunits.Pa) assert isinstance(frame.props[1].temperature, Var) assert frame.props[1].temperature.value == 345 assert frame.props[1].temperature.lb == 290 assert frame.props[1].temperature.ub == 400 assert check_units_equivalent(frame.props[1].temperature, pyunits.K) assert isinstance(frame.props[1].flow_mol_phase, Var) assert len(frame.props[1].flow_mol_phase) == 3 for i in frame.props[1].flow_mol_phase: assert i in frame.props[1].params.phase_list assert frame.props[1].flow_mol_phase[i].value == 100 / 3 assert frame.props[1].flow_mol_phase[i].lb == 0 assert frame.props[1].flow_mol_phase[i].ub == 200 assert check_units_equivalent(frame.props[1].flow_mol_phase, pyunits.mol / pyunits.s) assert isinstance(frame.props[1].phase_frac, Var) assert len(frame.props[1].phase_frac) == 3 for i in frame.props[1].phase_frac: assert i in frame.props[1].params.phase_list assert frame.props[1].phase_frac[i].value == 1 / 3 assert check_units_equivalent(frame.props[1].phase_frac, None) assert isinstance(frame.props[1].mole_frac_phase_comp, Var) assert len(frame.props[1].mole_frac_phase_comp) == 9 for i in frame.props[1].mole_frac_phase_comp: assert i in [("p1", "c1"), ("p1", "c2"), ("p1", "c3"), ("p2", "c1"), ("p2", "c2"), ("p2", "c3"), ("p3", "c1"), ("p3", "c2"), ("p3", "c3")] assert frame.props[1].mole_frac_phase_comp[i].value == 1 / 3 assert check_units_equivalent(frame.props[1].mole_frac_phase_comp, None)
def xhat_closest_to_xbar(self, verbose=False, restore_nonants=True): """ Get a truncated z score and look for the closest overall. Returns: obj (float or None): objective value, none if infeasible. snamedict (str): closest scenarios """ def _vb(msg): if verbose and self.rank == 0: print("(rank0) xhat_looper: " + msg) localmindist = np.zeros(1, dtype='d') globalmindist = np.zeros(1, dtype='d') localwinnername = None for k, s in self.opt.local_scenarios.items(): dist = 0 for ndn_i, xvar in s._nonant_indexes.items(): diff = pyo.value(xvar) variance = pyo.value(s._xsqbars[ndn_i]) \ - pyo.value(s._xbars[ndn_i])*pyo.value(s._xbars[ndn_i]) if variance > 0: stdev = np.sqrt(variance) dist += min(3, abs(diff) / stdev) if localwinnername is None: localmindist[0] = dist localwinnername = k elif dist < localmindist[0]: localmindist[0] = dist localwinnername = k self.comms["ROOT"].Allreduce([localmindist, mpi.DOUBLE], [globalmindist, mpi.DOUBLE], op=mpi.MIN) # ties are possible, so break the tie localwinrank = np.zeros(1, dtype='d') # could use a python variable. globalwinrank = np.zeros(1, dtype='d') if globalmindist[0] < localmindist[0]: localwinrank[0] = -1 # we lost else: localwinrank[0] = self.rank self.comms["ROOT"].Allreduce([localwinrank, mpi.DOUBLE], [globalwinrank, mpi.DOUBLE], op=mpi.MAX) # We only used the rank to break a possible tie. if self.rank == int(globalwinrank[0]): globalwinnername = localwinnername else: globalwinnername = None sroot = globalwinrank[0] sname = self.comms["ROOT"].bcast(globalwinnername, root=sroot) _vb("Trying scenario " + sname) _vb(" Solver options=" + str(self.solver_options)) # xxx TBD mult-stage snamedict = {"ROOT": sname} obj = self._try_one(snamedict, solver_options=self.solver_options, verbose=False, restore_nonants=restore_nonants) if obj is None: _vb(" Infeasible") else: _vb(" Feasible, returning " + str(obj)) return obj, snamedict
def propagate_state(destination=None, source=None, arc=None, direction="forward", overwrite_fixed=False): """ This method propagates values between Ports along Arcs. Values can be propagated in either direction using the direction argument. Args: destination (Port): Port to copy values to or None if specifying arc source (Port): Port to copy values from or None if specifying arc arc (Arc): If arc is provided, use arc to define source and destination direction (str): Direction in which to propagate values. Default = 'forward' Valid values: 'forward', 'backward'. overwrite_fixed (bool): If True overwrite fixed values, otherwise do not overwrite fixed values. Returns: None """ _log = idaeslog.getLogger(__name__) # Allow an arc to be passed as a positional arg if destination is not None and source is None and destination.ctype is Arc: arc = destination if source in ("forward", "backward"): direction = source destination = None source = None # Check that only arc or source and destination are passed if arc is None and (destination is None or source is None): raise RuntimeError( "In propagate_state(), must provide source and destination or arc") if arc is not None: if destination is not None or source is not None: raise RuntimeError("In propagate_state(), provide only arc or " "source and destination") try: source = arc.src destination = arc.dest except AttributeError: _log.error("In propagate_state(), unexpected type of arc " "argument. Value must be a Pyomo Arc") raise if direction == "forward": pass elif direction == "backward": source, destination = destination, source else: raise ValueError("Unexpected value for direction argument: ({}). " "Value must be either 'forward' or 'backward'." .format(direction)) try: destination_vars = destination.vars except AttributeError: _log.error("In propagate_state(), unexpected type of destination " "port argument. Value must be a Pyomo Port") raise try: source_vars = source.vars except AttributeError: _log.error("In propagate_state(), unexpected type of destination " "source argument. Value must be a Pyomo Port") raise # Copy values for k, v in destination_vars.items(): try: for i in v: if v[i].is_variable_type() and ((not v[i].fixed) or overwrite_fixed): v[i].value = value(source_vars[k][i]) elif not v[i].is_variable_type(): raise TypeError( f"propagate_state() is can only change the value of " f"variables and cannot set a {v[i].ctype}. This " f"likely indicates either a malformed port or a misuse " f"of propagate_state.") except KeyError as e: raise KeyError( "In propagate_state, variables have incompatible index sets") from e
def initialize( self, state_args={}, outlvl=idaeslog.NOTSET, solver="ipopt", optarg={ "tol": 1e-6, "max_iter": 30 }, calculate_cf=False, ): """ Initialize the inlet turbine stage model. This deactivates the specialized constraints, then does the isentropic turbine initialization, then reactivates the constraints and solves. This initializtion uses a flow value guess, so some reasonable flow guess should be sepecified prior to initializtion. Args: state_args (dict): Initial state for property initialization outlvl (int): Amount of output (0 to 3) 0 is lowest solver (str): Solver to use for initialization optarg (dict): Solver arguments dictionary calculate_cf (bool): If True, use the flow and pressure ratio to calculate the flow coefficient. """ init_log = idaeslog.getInitLogger(self.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(self.name, outlvl, tag="unit") # sp is what to save to make sure state after init is same as the start sp = StoreSpec.value_isfixed_isactive(only_fixed=True) istate = to_json(self, return_dict=True, wts=sp) # Setup for initializtion step 1 self.inlet_flow_constraint.deactivate() self.efficiency_correlation.deactivate() self.eff_nozzle.fix() self.blade_reaction.fix() self.flow_coeff.fix() self.blade_velocity.fix() self.inlet.fix() self.outlet.unfix() for t in self.flowsheet().config.time: self.efficiency_isentropic[t] = 0.9 super().initialize(outlvl=outlvl, solver=solver, optarg=optarg) # Free eff_isen and activate sepcial constarints self.inlet_flow_constraint.activate() self.efficiency_correlation.activate() if calculate_cf: self.ratioP.fix() self.flow_coeff.unfix() for t in self.flowsheet().config.time: g = self.control_volume.properties_in[t].heat_capacity_ratio mw = self.control_volume.properties_in[t].mw flow = self.control_volume.properties_in[t].flow_mol Tin = self.control_volume.properties_in[t].temperature Pin = self.control_volume.properties_in[t].pressure Pratio = self.ratioP[t] self.flow_coeff[t].value = value(flow * mw * sqrt( (Tin - 273.15) / (g / (g - 1) * (Pratio**(2.0 / g) - Pratio**((g + 1) / g)))) / Pin) slvr = SolverFactory(solver) slvr.options = optarg with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = slvr.solve(self, tee=slc.tee) init_log.info("Initialization Complete: {}".format( idaeslog.condition(res))) # reload original spec if calculate_cf: cf = {} for t in self.flowsheet().config.time: cf[t] = value(self.flow_coeff[t]) from_json(self, sd=istate, wts=sp) if calculate_cf: # cf was probably fixed, so will have to set the value agian here # if you ask for it to be calculated. for t in self.flowsheet().config.time: self.flow_coeff[t] = cf[t]
def test_conservation(self, iron_oc): # Conservation of material check dt, T = 36, 3600 # size of time interval and time domain # first, check if Final Mass - Initial Mass = Total Amount Reacted mbal_solid_total = value( (iron_oc.fs.unit.mass_solids[T] - iron_oc.fs.unit.mass_solids[0]) - (sum(iron_oc.fs.unit.reactions[t].reaction_rate[r] * iron_oc.fs.unit.config.reaction_package .rate_reaction_stoichiometry[r, "Sol", j] * iron_oc.fs.unit.solids[t]._params.mw_comp[j] * iron_oc.fs.unit.volume_solid[t] * dt for t in list(iron_oc.fs.time)[1:] for j in ('Al2O3', 'Fe2O3', 'Fe3O4') for r in iron_oc.fs.unit.config.reaction_package .rate_reaction_idx))) assert abs(mbal_solid_total) <= 1e-2 # second, check if Change in Mass = Amount Reacted at each time t mbal_solid = [] for t in list(iron_oc.fs.time)[1:]: # skip t = 0 mbal_solid.append(value( (iron_oc.fs.unit.mass_solids[t] - iron_oc.fs.unit.mass_solids[t - dt]) - (sum(iron_oc.fs.unit.reactions[t].reaction_rate[r] * iron_oc.fs.unit.config.reaction_package .rate_reaction_stoichiometry[r, "Sol", j] * iron_oc.fs.unit.solids[t]._params.mw_comp[j] * iron_oc.fs.unit.volume_solid[t] * dt for j in ('Al2O3', 'Fe2O3', 'Fe3O4') for r in iron_oc.fs.unit.config.reaction_package .rate_reaction_idx)))) for val in mbal_solid: assert abs(val) <= 1e-2 # Reaction stoichiometric ratio (gas is fixed, can only check solids) # Overall reducer reactions for methane combustion: # CH4 + 12Fe2O3 => 8Fe3O4 + CO2 + 2H2O fe2o3_reacted = value( (iron_oc.fs.unit.mass_solids[0] * iron_oc.fs.unit.solids[0].mass_frac_comp['Fe2O3'] - iron_oc.fs.unit.mass_solids[T] * iron_oc.fs.unit.solids[T].mass_frac_comp['Fe2O3']) / iron_oc.fs.unit.solids[0]._params.mw_comp['Fe2O3']) fe3o4_produced = value( (iron_oc.fs.unit.mass_solids[T] * iron_oc.fs.unit.solids[T].mass_frac_comp['Fe3O4'] - iron_oc.fs.unit.mass_solids[0] * iron_oc.fs.unit.solids[0].mass_frac_comp['Fe3O4']) / iron_oc.fs.unit.solids[0]._params.mw_comp['Fe3O4']) stoichiometric_ratio = fe2o3_reacted/fe3o4_produced assert (pytest.approx(1.5, abs=1e-6) == stoichiometric_ratio) # Conservation of energy check # first, check if Final Energy - Initial Energy = Reaction Enthalpy ebal_solid_total = value( (iron_oc.fs.unit.mass_solids[T] * iron_oc.fs.unit.solids[T].enth_mass - iron_oc.fs.unit.mass_solids[0] * iron_oc.fs.unit.solids[0].enth_mass) - (-sum(iron_oc.fs.unit.reactions[t].reaction_rate[r] * iron_oc.fs.unit.reactions[t].dh_rxn[r] * iron_oc.fs.unit.volume_solid[t] * dt for t in list(iron_oc.fs.time)[1:] for r in iron_oc.fs.unit.config.reaction_package. rate_reaction_idx))) assert abs(ebal_solid_total) <= 1e-2 # second, check if Change in Energy = Change in Holdup at each time t ebal_solid = [] for t in list(iron_oc.fs.time)[1:]: # skip t = 0 ebal_solid.append(value( (iron_oc.fs.unit.mass_solids[t] * iron_oc.fs.unit.solids[t].enth_mass - iron_oc.fs.unit.mass_solids[t - dt] * iron_oc.fs.unit.solids[t - dt].enth_mass) - (-sum(iron_oc.fs.unit.reactions[t].reaction_rate[r] * iron_oc.fs.unit.reactions[t].dh_rxn[r] * iron_oc.fs.unit.volume_solid[t] * dt for r in iron_oc.fs.unit.config.reaction_package. rate_reaction_idx)))) for val in ebal_solid: assert abs(val) <= 1e-2
def test_solution(self, frame): m = frame # specified conditions assert pytest.approx(0.035, rel=1e-3) == value(m.fs.stream[0].flow_mass_phase_comp['Liq', 'TDS']) assert pytest.approx(0.965, rel=1e-3) == value(m.fs.stream[0].flow_mass_phase_comp['Liq', 'H2O']) assert pytest.approx(273.15 + 25, rel=1e-3) == value(m.fs.stream[0].temperature) assert pytest.approx(101325, rel=1e-3) == value(m.fs.stream[0].pressure) # calculated properties assert pytest.approx(0.035, rel=1e-3) == value(m.fs.stream[0].mass_frac_phase_comp['Liq', 'TDS']) assert pytest.approx(0.965, rel=1e-3) == value(m.fs.stream[0].mass_frac_phase_comp['Liq', 'H2O']) assert pytest.approx(1023.6, rel=1e-3) == value(m.fs.stream[0].dens_mass_phase['Liq']) assert pytest.approx(996, rel=1e-3) == value(m.fs.stream[0].dens_mass_solvent) assert pytest.approx(9.770e-4, rel=1e-3) == value(m.fs.stream[0].flow_vol_phase['Liq']) assert pytest.approx(9.770e-4, rel=1e-3) == value(m.fs.stream[0].flow_vol) assert pytest.approx(987.7, rel=1e-3) == value(m.fs.stream[0].conc_mass_phase_comp['Liq', 'H2O']) assert pytest.approx(35.82, rel=1e-3) == value(m.fs.stream[0].conc_mass_phase_comp['Liq', 'TDS']) assert pytest.approx(53.57, rel=1e-3) == value(m.fs.stream[0].flow_mol_phase_comp['Liq', 'H2O']) assert pytest.approx(1.1145, rel=1e-3) == value(m.fs.stream[0].flow_mol_phase_comp['Liq', 'TDS']) assert pytest.approx(0.9796, rel=1e-3) == value(m.fs.stream[0].mole_frac_phase_comp['Liq', 'H2O']) assert pytest.approx(0.02038, rel=1e-3) == value(m.fs.stream[0].mole_frac_phase_comp['Liq', 'TDS']) assert pytest.approx(1.1549, rel=1e-3) == value(m.fs.stream[0].molality_comp['TDS']) assert pytest.approx(9.588e-4, rel=1e-3) == value(m.fs.stream[0].visc_d_phase['Liq']) assert pytest.approx(0.9068, rel=1e-3) == value(m.fs.stream[0].osm_coeff) assert pytest.approx(2.588e6, rel=1e-3) == value(m.fs.stream[0].pressure_osm) assert pytest.approx(9.974e4, rel=1e-3) == value(m.fs.stream[0].enth_mass_phase['Liq']) assert pytest.approx(9.974e4, rel=1e-3) == value(m.fs.stream[0].enth_flow) assert pytest.approx(3111, rel=1e-3) == value(m.fs.stream[0].pressure_sat) assert pytest.approx(4000.77, rel=1e-3) == value(m.fs.stream[0].cp_phase['Liq']) assert pytest.approx(0.6086, rel=1e-3) == value(m.fs.stream[0].therm_cond_phase['Liq']) assert pytest.approx(2.356e6, rel=1e-3) == value(m.fs.stream[0].dh_vap)
def export_results(scenario_directory, subproblem, stage, m, d): """ :param scenario_directory: :param subproblem: :param stage: :param m: :param d: :return: """ df = pd.read_csv( os.path.join(scenario_directory, str(subproblem), str(stage), "inputs", "transmission_lines.tab"), sep="\t", usecols=["TRANSMISSION_LINES", "tx_capacity_type", "tx_operational_type"] ) # Required capacity modules are the unique set of tx capacity types # This list will be used to know which capacity modules to load # Module-specific results required_tx_capacity_modules = df.tx_capacity_type.unique() # Import needed transmission capacity type modules for expression rules imported_tx_capacity_modules = load_tx_capacity_type_modules( required_tx_capacity_modules ) # Add model components for each of the transmission capacity modules for op_m in required_tx_capacity_modules: if hasattr(imported_tx_capacity_modules[op_m], "export_module_specific_results"): imported_tx_capacity_modules[op_m].export_module_specific_results( m, d, scenario_directory, subproblem, stage ) else: pass # Export transmission capacity with open(os.path.join(scenario_directory, str(subproblem), str(stage), "results", "transmission_capacity.csv"), "w", newline="") as f: writer = csv.writer(f) writer.writerow(["tx_line", "period", "load_zone_from", "load_zone_to", "transmission_min_capacity_mw", "transmission_max_capacity_mw"]) for (tx_line, p) in m.TX_OPR_PRDS: writer.writerow([ tx_line, p, m.load_zone_from[tx_line], m.load_zone_to[tx_line], value(m.Tx_Min_Capacity_MW[tx_line, p]), value(m.Tx_Max_Capacity_MW[tx_line, p]) ]) # Export transmission capacity costs with open(os.path.join(scenario_directory, str(subproblem), str(stage), "results", "costs_transmission_capacity.csv"), "w", newline="") as f: writer = csv.writer(f) writer.writerow( ["tx_line", "period", "hours_in_full_period", "hours_in_subproblem_period", "load_zone_from", "load_zone_to", "capacity_cost"] ) for (l, p) in m.TX_OPR_PRDS: writer.writerow([ l, p, m.hours_in_full_period[p], m.hours_in_subproblem_period[p], m.load_zone_from[l], m.load_zone_to[l], value(m.Tx_Capacity_Cost_in_Prd[l, p]) ])
def test_boiler_hx(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = PhysicalParameterTestBlock() m.fs.prop_steam = iapws95.Iapws95ParameterBlock() m.fs.prop_fluegas = FlueGasParameterBlock() m.fs.unit = BoilerHeatExchanger( default={ "side_1_property_package": m.fs.prop_steam, "side_2_property_package": m.fs.prop_fluegas, "has_pressure_change": True, "has_holdup": False, "delta_T_method": DeltaTMethod.counterCurrent, "tube_arrangement": TubeArrangement.inLine, "side_1_water_phase": "Liq", "has_radiation": True }) # Set inputs h = value(iapws95.htpx(773.15 * pyunits.K, 2.5449e7 * pyunits.Pa)) print(h) m.fs.unit.side_1_inlet.flow_mol[0].fix(24678.26) # mol/s m.fs.unit.side_1_inlet.enth_mol[0].fix(h) # J/mol m.fs.unit.side_1_inlet.pressure[0].fix(2.5449e7) # Pascals # FLUE GAS Inlet from Primary Superheater FGrate = 28.3876e3 * 0.18 # mol/s equivalent of ~1930.08 klb/hr # Use FG molar composition to set component flow rates (baseline report) m.fs.unit.side_2_inlet.flow_mol_comp[0, "H2O"].fix(FGrate * 8.69 / 100) m.fs.unit.side_2_inlet.flow_mol_comp[0, "CO2"].fix(FGrate * 14.49 / 100) m.fs.unit.side_2_inlet.flow_mol_comp[0, "N2"].fix(FGrate * 74.34 / 100) m.fs.unit.side_2_inlet.flow_mol_comp[0, "O2"].fix(FGrate * 2.47 / 100) m.fs.unit.side_2_inlet.flow_mol_comp[0, "NO"].fix(FGrate * 0.0006) m.fs.unit.side_2_inlet.flow_mol_comp[0, "SO2"].fix(FGrate * 0.002) m.fs.unit.side_2_inlet.temperature[0].fix(1102.335) m.fs.unit.side_2_inlet.pressure[0].fix(100145) # Primary Superheater ITM = 0.0254 # inch to meter conversion m.fs.unit.tube_di.fix((2.5 - 2 * 0.165) * ITM) m.fs.unit.tube_thickness.fix(0.165 * ITM) m.fs.unit.pitch_x.fix(3 * ITM) # gas path transverse width 54.78 ft / number of columns m.fs.unit.pitch_y.fix(54.78 / 108 * 12 * ITM) m.fs.unit.tube_length.fix(53.13 * 12 * ITM) m.fs.unit.tube_nrow.fix(20 * 2) m.fs.unit.tube_ncol.fix(108) m.fs.unit.nrow_inlet.fix(4) m.fs.unit.delta_elevation.fix(50) m.fs.unit.tube_r_fouling = 0.000176 # (0.001 h-ft^2-F/BTU) m.fs.unit.tube_r_fouling = 0.003131 # (0.03131 - 0.1779 h-ft^2-F/BTU) if m.fs.unit.config.has_radiation is True: m.fs.unit.emissivity_wall.fix(0.7) # wall emissivity # correction factor for overall heat transfer coefficient m.fs.unit.fcorrection_htc.fix(1.5) # correction factor for pressure drop calc tube side m.fs.unit.fcorrection_dp_tube.fix(1.0) # correction factor for pressure drop calc shell side m.fs.unit.fcorrection_dp_shell.fix(1.0) assert degrees_of_freedom(m) == 0 m.fs.unit.initialize() # Create a solver solver = SolverFactory('ipopt') results = solver.solve(m) # Check for optimal solution assert results.solver.termination_condition == \ TerminationCondition.optimal assert results.solver.status == SolverStatus.ok assert value(m.fs.unit.side_1.properties_out[0].temperature) == \ pytest.approx(588.07, 1) assert value(m.fs.unit.side_2.properties_out[0].temperature) == \ pytest.approx(573.07, 1)
def test_midpoint_var_init(self): """Test midpoint initialization.""" m = ConcreteModel() m.v1 = Var() m.v2 = Var() m.v3 = Var() m.v4 = Var() m.v5 = Var(initialize=2) m.v5.fix() m.v6 = Var(initialize=3) m.v2.setlb(2) m.v3.setub(2) m.v4.setlb(0) m.v4.setub(2) TransformationFactory('contrib.init_vars_midpoint').apply_to(m) self.assertEquals(value(m.v1), 0) self.assertEquals(value(m.v2), 2) self.assertEquals(value(m.v3), 2) self.assertEquals(value(m.v4), 1) self.assertEquals(value(m.v5), 2) self.assertEquals(value(m.v6), 3) TransformationFactory('contrib.init_vars_midpoint').apply_to( m, overwrite=True) self.assertEquals(value(m.v1), 0) self.assertEquals(value(m.v2), 2) self.assertEquals(value(m.v3), 2) self.assertEquals(value(m.v4), 1) self.assertEquals(value(m.v5), 2) self.assertEquals(value(m.v6), 0)
def _build_pw_mccormick_relaxation(b, x, y, w, x_pts, relaxation_side=RelaxationSide.BOTH): """ This function creates piecewise envelopes to relax "w = x*y". Note that the partitioning is done on "x" only. This is the "nf4r" from Gounaris, Misener, and Floudas (2009). Parameters ---------- b: pyo.ConcreteModel or pyo.Block x: pyomo.core.base.var._GeneralVarData The "x" variable in x*y y: pyomo.core.base.var._GeneralVarData The "y" variable in x*y w: pyomo.core.base.var._GeneralVarData The "w" variable that is replacing x*y x_pts: list of floats A list of floating point numbers to define the points over which the piecewise representation will generated. This list must be ordered, and it is expected that the first point (x_pts[0]) is equal to x.lb and the last point (x_pts[-1]) is equal to x.ub relaxation_side : minlp.minlp_defn.RelaxationSide Provide the desired side for the relaxation (OVER, UNDER, or BOTH) """ xlb = pyo.value(x.lb) xub = pyo.value(x.ub) ylb = pyo.value(y.lb) yub = pyo.value(y.ub) check_var_pts(x, x_pts=x_pts) check_var_pts(y) if x.is_fixed() and y.is_fixed(): b.xy_fixed_eq = pyo.Constraint(expr=w == pyo.value(x) * pyo.value(y)) elif x.is_fixed(): b.x_fixed_eq = pyo.Constraint(expr=w == pyo.value(x) * y) elif y.is_fixed(): b.y_fixed_eq = pyo.Constraint(expr=w == x * pyo.value(y)) elif len(x_pts) == 2: _build_mccormick_relaxation(b, x=x, y=y, w=w, relaxation_side=relaxation_side) else: # create the lambda variables (binaries for the pw representation) b.interval_set = pyo.Set(initialize=range(1, len(x_pts))) b.lam = pyo.Var(b.interval_set, within=pyo.Binary) # create the delta y variables b.delta_y = pyo.Var(b.interval_set, bounds=(0, None)) # create the "sos1" constraint b.lam_sos1 = pyo.Constraint(expr=sum(b.lam[n] for n in b.interval_set) == 1.0) # create the x interval constraints b.x_interval_lb = pyo.Constraint( expr=sum(x_pts[n - 1] * b.lam[n] for n in b.interval_set) <= x) b.x_interval_ub = pyo.Constraint( expr=x <= sum(x_pts[n] * b.lam[n] for n in b.interval_set)) # create the y constraints b.y_con = pyo.Constraint(expr=y == ylb + sum(b.delta_y[n] for n in b.interval_set)) def delta_yn_ub_rule(m, n): return b.delta_y[n] <= (yub - ylb) * b.lam[n] b.delta_yn_ub = pyo.Constraint(b.interval_set, rule=delta_yn_ub_rule) # create the relaxation constraints if relaxation_side == RelaxationSide.UNDER or relaxation_side == RelaxationSide.BOTH: b.w_lb1 = pyo.Constraint( expr=(w >= yub * x + sum(x_pts[n] * b.delta_y[n] for n in b.interval_set) - (yub - ylb) * sum(x_pts[n] * b.lam[n] for n in b.interval_set))) b.w_lb2 = pyo.Constraint( expr=w >= ylb * x + sum(x_pts[n - 1] * b.delta_y[n] for n in b.interval_set)) if relaxation_side == RelaxationSide.OVER or relaxation_side == RelaxationSide.BOTH: b.w_ub1 = pyo.Constraint( expr=(w <= yub * x + sum(x_pts[n - 1] * b.delta_y[n] for n in b.interval_set) - (yub - ylb) * sum(x_pts[n - 1] * b.lam[n] for n in b.interval_set))) b.w_ub2 = pyo.Constraint( expr=w <= ylb * x + sum(x_pts[n] * b.delta_y[n] for n in b.interval_set))
def test_initialize_by_time_element(): horizon = 6 time_set = [0, horizon] ntfe = 60 # For a finite element every six seconds ntcp = 2 m = ConcreteModel(name='CSTR model for testing') m.fs = FlowsheetBlock(default={'dynamic': True, 'time_set': time_set}) m.fs.properties = AqueousEnzymeParameterBlock() m.fs.reactions = EnzymeReactionParameterBlock( default={'property_package': m.fs.properties}) m.fs.cstr = CSTR(default={"property_package": m.fs.properties, "reaction_package": m.fs.reactions, "material_balance_type": MaterialBalanceType.componentTotal, "energy_balance_type": EnergyBalanceType.enthalpyTotal, "momentum_balance_type": MomentumBalanceType.none, "has_heat_of_reaction": True}) # Time discretization disc = TransformationFactory('dae.collocation') disc.apply_to(m, wrt=m.fs.time, nfe=ntfe, ncp=ntcp, scheme='LAGRANGE-RADAU') # Fix geometry variables m.fs.cstr.volume[0].fix(1.0) # Fix initial conditions: for p, j in m.fs.properties.phase_list*m.fs.properties.component_list: if j == 'Solvent': continue m.fs.cstr.control_volume.material_holdup[0, p, j].fix(0) # Fix inlet conditions # This is a huge hack because I didn't know that the proper way to # have multiple inlets to a CSTR was to use a mixer. # I 'combine' both my inlet streams before sending them to the CSTR. for t, j in m.fs.time*m.fs.properties.component_list: if t <= 2: if j == 'E': m.fs.cstr.inlet.conc_mol[t, j].fix(11.91*0.1/2.2) elif j == 'S': m.fs.cstr.inlet.conc_mol[t, j].fix(12.92*2.1/2.2) elif j != 'Solvent': m.fs.cstr.inlet.conc_mol[t, j].fix(0) elif t <= 4: if j == 'E': m.fs.cstr.inlet.conc_mol[t, j].fix(5.95*0.1/2.2) elif j == 'S': m.fs.cstr.inlet.conc_mol[t, j].fix(12.92*2.1/2.2) elif j != 'Solvent': m.fs.cstr.inlet.conc_mol[t, j].fix(0) else: if j == 'E': m.fs.cstr.inlet.conc_mol[t, j].fix(8.95*0.1/2.2) elif j == 'S': m.fs.cstr.inlet.conc_mol[t, j].fix(16.75*2.1/2.2) elif j != 'Solvent': m.fs.cstr.inlet.conc_mol[t, j].fix(0) m.fs.cstr.inlet.conc_mol[:, 'Solvent'].fix(1.) m.fs.cstr.inlet.flow_vol.fix(2.2) m.fs.cstr.inlet.temperature.fix(300) # Fix outlet conditions m.fs.cstr.outlet.flow_vol.fix(2.2) m.fs.cstr.outlet.temperature[m.fs.time.first()].fix(300) assert degrees_of_freedom(m) == 0 initialize_by_time_element(m.fs, m.fs.time, solver=solver) assert degrees_of_freedom(m) == 0 # Assert that the result looks how we expect assert m.fs.cstr.outlet.conc_mol[0, 'S'].value == 0 assert abs(m.fs.cstr.outlet.conc_mol[2, 'S'].value - 11.389) < 1e-2 assert abs(m.fs.cstr.outlet.conc_mol[4, 'P'].value - 0.2191) < 1e-3 assert abs(m.fs.cstr.outlet.conc_mol[6, 'E'].value - 0.0327) < 1e-3 assert abs(m.fs.cstr.outlet.temperature[6].value - 289.7) < 1 # Assert that model is still fixed and deactivated as expected assert ( m.fs.cstr.control_volume.material_holdup[m.fs.time.first(), 'aq', 'S'].fixed) for t in m.fs.time: if t != m.fs.time.first(): assert (not m.fs.cstr.control_volume.material_holdup[t, 'aq', 'S'].fixed) assert not m.fs.cstr.outlet.temperature[t].fixed assert ( m.fs.cstr.control_volume.material_holdup_calculation[t, 'aq', 'C'].active) assert m.fs.cstr.control_volume.properties_out[t].active assert not m.fs.cstr.outlet.conc_mol[t, 'S'].fixed assert m.fs.cstr.inlet.conc_mol[t, 'S'].fixed # Assert that constraints are feasible after initialization for con in m.fs.component_data_objects(Constraint, active=True): assert value(con.body) - value(con.upper) < 1e-5 assert value(con.lower) - value(con.body) < 1e-5 results = solver.solve(m.fs) assert results.solver.termination_condition == TerminationCondition.optimal
def check(_T, _rho, func, val, rel=1e-4): val = pytest.approx(val, rel=rel) assert value(func(delta(_rho), tau(_T))) == val
def create_model(thermo_config=None, reaction_config=None): # Create a pyomo model object model = ConcreteModel() # Add an idaes flowsheet object to that model model.fs = FlowsheetBlock(default={"dynamic": False}) # Add the generic properties object to that flowsheet # and pass the custom configuation dictionary to it model.fs.thermo_params = GenericParameterBlock(default=thermo_config) # Add the generic reactions object to that flowsheet # and pass the corresponding properties/params object to it # along with the reaction_config dictionary model.fs.rxn_params = GenericReactionParameterBlock( default={ "property_package": model.fs.thermo_params, **reaction_config }) # Add the unit model for an Equilibrium Reactor to the flowsheet model.fs.unit = EquilibriumReactor( default={ "property_package": model.fs.thermo_params, "reaction_package": model.fs.rxn_params, "has_rate_reactions": False, "has_equilibrium_reactions": True, "has_heat_transfer": False, "has_heat_of_reaction": False, "has_pressure_change": False }) ## Use this function to ensure the units and unit conversions are all correct ## This will throw an error if things are wrong #assert_units_consistent(model) print("Degrees of freedom = " + str(degrees_of_freedom(model))) # After building this model, there will be 9 degrees of freedom that MUST be # fixed before calling the solver. Those degrees of freedom are based on # the 'state_definition' defined in the 'thermo_config' dictionary and # the number of components declared. # # For our problem: # --------------- # 'state_definition' == 'FTPx' # Corresponds to: # --------------- # model.fs.unit.inlet.flow_mol - mol/s # model.fs.unit.inlet.pressure - Pa # model.fs.unit.inlet.temperature - K # model.fs.unit.inlet.mole_frac_comp[0, "name_of_component"] # (This one is repeated for each named component in 'thermo_config') # (The first value is the time stamp associated with the inlet, # which in our case is 0 because we are not a dynamic flowsheet) # # 'components' == ['H2O', 'H +', 'OH -', 'H2CO3', 'HCO3 -', 'CO3 2-'] # Corresponds to: # --------------- # model.fs.unit.inlet.mole_frac_comp[0, "H2O"] - unitless # model.fs.unit.inlet.mole_frac_comp[0, "CO2"] - unitless # (Sum of all mole_frac_comp should equal 1.) model.fs.unit.inlet.flow_mol.fix(10) model.fs.unit.inlet.pressure.fix(101325.0) model.fs.unit.inlet.temperature.fix(300.0) # Set molefractions for ions... (this may change later) model.fs.unit.inlet.mole_frac_comp[0, "H +"].fix(0.) model.fs.unit.inlet.mole_frac_comp[0, "OH -"].fix(0.) model.fs.unit.inlet.mole_frac_comp[0, "HCO3 -"].fix(0.) model.fs.unit.inlet.mole_frac_comp[0, "CO3 2-"].fix(0.) # To come up with molefractions, we can start be pulling the water density from # our thermo_config as follows (NOTE: it will have same units as before) # [This approximation is valid for all aqueous chemistry] # # Units: kmol/m**3 == mol/L total_carbonate = 0.00206 total_molar_density = calc_water_density(300) model.fs.unit.inlet.mole_frac_comp[0, "H2CO3"].fix(total_carbonate / total_molar_density) # Perform a summation of all non-H2O molefractions to find the H2O molefraction sum = 0 for i in model.fs.unit.inlet.mole_frac_comp: # NOTE: i will be a tuple with format (time, component) if i[1] != "H2O": sum += value(model.fs.unit.inlet.mole_frac_comp[i[0], i[1]]) # Fix the inlet H2O molefraction based on remaining fraction model.fs.unit.inlet.mole_frac_comp[0, "H2O"].fix(1 - sum) #Setup scaling factors (optional) model.fs.thermo_params.default_scaling_factor[("mole_frac_comp", "H +")] = 1e7 model.fs.thermo_params.default_scaling_factor[("mole_frac_comp", "OH -")] = 1e7 model.fs.thermo_params.default_scaling_factor[("mole_frac_comp", "HCO3 -")] = 1e7 model.fs.thermo_params.default_scaling_factor[("mole_frac_comp", "CO3 2-")] = 1e7 model.fs.thermo_params.default_scaling_factor[("mole_frac_comp", "H2CO3")] = 1e7 model.fs.thermo_params.default_scaling_factor[("mole_frac_comp", "H2O")] = 1 # # TODO: ERROR! Cannot use this simple method to calculate scaling factors # Model does not like it when I do this. I believe I have to give # scaling factors for everything in the model for it to work properly. #iscale.calculate_scaling_factors(model.fs.unit) print("Degrees of freedom = " + str(degrees_of_freedom(model))) return model
def test_solve_sat_density(self, model): """ The density calculations should be tested by the thermo expression tests, but they are pretty fundimental to everything else, so test them a little more on their own. """ # test saturated liquid and vapor density solve (critical part of the # phase equlibrium calc) te = model.te data = read_sat_data(self.pdata_sat, self.mw) for i, T in enumerate(data["T"]): if T > self.Tc - 0.1: # if this goes over the critical temperature this makes no # sense # also really close to the critical temperature for various # reasons we'll diverge a bit from what we are comparing to pass else: tol = 1e-2 # test p, x spec rhol = value(te.rho_liq(p=data["P"][i] * pyunits.Pa, x=0)) rhov = value(te.rho_vap(p=data["P"][i] * pyunits.Pa, x=1)) assert rhol == pytest.approx(value(data["rhol"][i]), rel=tol) assert rhov == pytest.approx(value(data["rhov"][i]), rel=tol) # test t, x spec rhol = value(te.rho_liq(T=T * pyunits.K, x=0)) rhov = value(te.rho_vap(T=T * pyunits.K, x=1)) assert rhol == pytest.approx(value(data["rhol"][i]), rel=tol) assert rhov == pytest.approx(value(data["rhov"][i]), rel=tol) # Ignore the phase equilibrium and use T,P data to calc densities if T > 296: tol = 1e-1 # data needs more sig fig rhol = value( te.rho_liq(p=data["P"][i] * pyunits.Pa, T=T * pyunits.K, x=0)) rhov = value( te.rho_vap(p=data["P"][i] * pyunits.Pa, T=T * pyunits.K, x=1)) assert rhol == pytest.approx(value(data["rhol"][i]), rel=tol) assert rhov == pytest.approx(value(data["rhov"][i]), rel=tol)
import pyomo.environ as pyo from pyomo.opt import SolverFactory model = pyo.ConcreteModel() model.nVars = pyo.Param(initialize=4) model.N = pyo.RangeSet(model.nVars) model.x = pyo.Var(model.N, within=pyo.Binary) model.obj = pyo.Objective(expr=pyo.summation(model.x), sense=minimize) model.cuts = pyo.ConstraintList() opt = SolverFactory('glpk') opt.solve(model) # Iterate, adding a cut to exclude the previously found solution for i in range(5): expr = 0 for j in model.x: if pyo.value(model.x[j]) < 0.5: expr += model.x[j] else: expr += (1 - model.x[j]) model.cuts.add(expr >= min(i, 4)) results = opt.solve(model) print("\n===== iteration", i) model.display()
online_cb.receive_data(p_t={"p_t":p_t_samples[i],"RHS":RHS_t_samples[i]},x_t=x_t_samples[i]) ## The next few statements do some basic checks. They aren't comprehensive, but ## ## they are useful to showcase because they indicate some approaches to debugging pyomo models ## ## See documentation for sources regarding the pyomo package and its documentation (and some sites I found helpful) ## # Asserting that the parameters p_t and RHS_t both gets put into the BMPS_subproblem # assert online_cb.BMPS_subproblem.A.extract_values() == p_t_samples[i] assert online_cb.BMPS_subproblem.b.extract_values() == RHS_t_samples[i] # Doing Some constraint Checking # for constr in online_cb.BMPS_subproblem.component_objects(pyo.Constraint): assert constr._constructed == True, "Error in constraint construction (body)" for c in constr: lb = pyo.value(constr[c].lower) ub = pyo.value(constr[c].upper) assert ((lb is not None) or (ub is not None)), "Error in constraint construction (LHS/RHS)" ### Step 4: Finish out the Iteration by "solving subproblem", "performing gradient ### ### descent step", and calculating the learning rate (BMPS, 2018) online_cb.next_iteration(part_for_BMPS=2) #pdb.set_trace() ## Save some data ## c_t_dict_vecs[i] = copy.deepcopy(online_cb.c_t_BMPS) xbar_dict_vecs[i] = copy.deepcopy(online_cb.xbar_t_BMPS) print("Run time (seconds) for the script: ")
# define variables model.x = pyo.Var(bounds=(0, 10)) model.y = pyo.Var(bounds=(0, 10)) x = model.x y = model.y # define constraints model.C1 = pyo.Constraint(expr=-x + 2 * y * x <= 8) model.C2 = pyo.Constraint(expr=2 * x + y <= 14) model.C3 = pyo.Constraint(expr=2 * x - y <= 10) # define objective function model.obj = pyo.Objective(expr=x + y * x, sense=maximize) # solver selection and run opt = SolverFactory('ipopt') opt.solve(model) # print model model.pprint() # collect results x_value = pyo.value(x) y_value = pyo.value(y) # display results print( '\n---------------------------------------------------------------------') print('x=', x_value) print('y=', y_value)
def tpid(form): """This test is pretty course-grained, but it should cover everything""" # First calculate the two steady states that should be achieved in the test # don't worry these steady state problems solve super fast m_steady, solver = create_model() m_steady.fs.tank_pressure[0].fix(3e5) m_steady.fs.valve_1.valve_opening[0].unfix() solver.solve(m_steady, tee=True) s1_valve = pyo.value(m_steady.fs.valve_1.valve_opening[0]) solver.solve(m_steady, tee=True) m_steady.fs.valve_1.inlet.pressure.fix(5.5e5) solver.solve(m_steady, tee=True) s2_valve = pyo.value(m_steady.fs.valve_1.valve_opening[0]) # Next create a model for the 0 to 5 sec time period m_dynamic, solver = create_model( steady_state=False, time_set=[0, 5], nfe=10, calc_integ=True, form=form, ) # Turn on control and solve since the setpoint is different than the # steady-state solution, stuff happens, also pressure step at t=5 m_dynamic.fs.ctrl.activate() m_dynamic.fs.valve_1.valve_opening.unfix() m_dynamic.fs.valve_1.valve_opening[0].fix() # Add a step change right at the end of the interval, to make sure we can # get a continuous solution across the two models _add_inlet_pressure_step(m_dynamic, time=4.5, value=5.5e5) iscale.calculate_scaling_factors(m_dynamic) solver.solve(m_dynamic, tee=True) # Now create a model for the 5 to 10 second interval and set the inital # conditions of the first model to the final (unsteady) state of the # previous time interval model m_dynamic2, solver = create_model( steady_state=False, time_set=[5, 10], nfe=10, calc_integ=False, form=form, ) m_dynamic2.fs.valve_1.valve_opening.fix( m_dynamic.fs.valve_1.valve_opening[5].value) m_dynamic2.fs.valve_1.inlet.enth_mol.fix( m_dynamic.fs.valve_1.inlet.enth_mol[5].value) m_dynamic2.fs.valve_1.inlet.pressure.fix( m_dynamic.fs.valve_1.inlet.pressure[5].value) for i in m_dynamic2.fs.tank.control_volume.material_accumulation: if i[0] == 5: m_dynamic2.fs.tank.control_volume.material_accumulation[i].value =\ m_dynamic.fs.tank.control_volume.material_accumulation[i].value for i in m_dynamic2.fs.tank.control_volume.energy_accumulation: if i[0] == 5: m_dynamic2.fs.tank.control_volume.energy_accumulation[i].value =\ m_dynamic.fs.tank.control_volume.energy_accumulation[i].value m_dynamic2.fs.ctrl.err_d0.fix(pyo.value(m_dynamic.fs.ctrl.err_d[5])) m_dynamic2.fs.ctrl.err_i0.fix(pyo.value(m_dynamic.fs.ctrl.err_i_end)) iscale.calculate_scaling_factors(m_dynamic2) # As a lazy form of initialization, solve the steady state problem before # turning on the controller. solver.solve(m_dynamic2, tee=True) # Now turn on control and solve again. m_dynamic2.fs.ctrl.activate() m_dynamic2.fs.valve_1.valve_opening.unfix() m_dynamic2.fs.valve_1.valve_opening[5].fix() solver.solve(m_dynamic2, tee=True) # Check that the model hit steady state about. The tolerance is loose # because I used a low nfe in an attempt to speed it up t = m_dynamic.fs.time.get_lower_element_boundary(4.45) assert s1_valve == pytest.approx(pyo.value( m_dynamic.fs.valve_1.valve_opening[t]), abs=5e-3) # The second should hit steady state pretty quick if the two models # line up smoothly. t = m_dynamic2.fs.time.get_lower_element_boundary(7) assert s2_valve == pytest.approx(pyo.value( m_dynamic2.fs.valve_1.valve_opening[t]), abs=5e-3) stitch_time = stitch_dynamic(m_dynamic.fs.time, m_dynamic2.fs.time) stitch_valve = stitch_dynamic(m_dynamic.fs.valve_1.valve_opening, m_dynamic2.fs.valve_1.valve_opening) # test the stitch function used to plot time dependent variables across # the two models for i, t in enumerate(m_dynamic.fs.time): assert t == stitch_time[i] assert m_dynamic.fs.valve_1.valve_opening[t] == stitch_valve[i] for j, t in enumerate(m_dynamic2.fs.time): i = j + len(m_dynamic.fs.time) assert t == stitch_time[i] assert m_dynamic2.fs.valve_1.valve_opening[t] == stitch_valve[i]
def initialize(blk, state_args={}, outlvl=idaeslog.NOTSET, solver='ipopt', optarg={'tol': 1e-6}): ''' water tank initialization routine. Keyword Arguments: state_args : a dict of arguments to be passed to the property package(s) for the control_volume of the model to provide an initial state for initialization (see documentation of the specific property package) (default = None). outlvl : sets output level of initialisation routine * 0 = no output (default) * 1 = return solver state for each step in routine * 2 = return solver state for each step in subroutines * 3 = include solver output infomation (tee=True) optarg : solver options dictionary object (default={'tol': 1e-6}) solver : str indicating whcih solver to use during initialization (default = 'ipopt') Returns: None ''' init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="unit") opt = SolverFactory(solver) opt.options = optarg init_log.info_low("Starting initialization...") flags = blk.control_volume.initialize(state_args=state_args, outlvl=outlvl, optarg=optarg, solver=solver) init_log.info_high("Initialization Step 1 Complete.") # Fix outlet pressure for t in blk.flowsheet().config.time: blk.control_volume.properties_out[t].pressure.\ fix(value(blk.control_volume.properties_in[t].pressure)) blk.pressure_change_eqn.deactivate() # solve model with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = opt.solve(blk, tee=slc.tee) init_log.info_high( "Initialization Step 2 {}.".format(idaeslog.condition(res)) ) # Unfix outlet pressure for t in blk.flowsheet().config.time: blk.control_volume.properties_out[t].pressure.unfix() blk.pressure_change_eqn.activate() with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = opt.solve(blk, tee=slc.tee) init_log.info_high( "Initialization Step 3 {}.".format(idaeslog.condition(res)) ) blk.control_volume.release_state(flags, outlvl) init_log.info("Initialization Complete.")
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 ['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 == FTPx assertStructuredAlmostEqual( model.params.config.state_bounds, { "flow_mol": (0, 100, 1000, pyunits.mol / pyunits.s), "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 model.params.benzene.mw.value == 78.1136E-3 assert model.params.benzene.pressure_crit.value == 48.9e5 assert model.params.benzene.temperature_crit.value == 562.2 assert model.params.toluene.mw.value == 92.1405E-3 assert model.params.toluene.pressure_crit.value == 41e5 assert model.params.toluene.temperature_crit.value == 591.8 assert_units_consistent(model)
def test_thermo_expression_writter(self, model): te = model.te data = read_data(self.pdata, self.mw) for i, T in enumerate(data["T"]): p = data["P"][i] * pyunits.Pa h = data["H"][i] * pyunits.J / pyunits.mol s = data["S"][i] * pyunits.J / pyunits.mol / pyunits.K u = data["U"][i] * pyunits.J / pyunits.mol if data["phase"][i] == "vapor": x = 1 else: x = 0 if value(p) < self.Pmin or value(p) > self.Pmax: continue if T < self.Tmin or T > self.Tmax: continue if i % self.onein: continue # Test state variable with P in the set, these are pretty reliable assert value(te.s(h=h, p=p)) == pytest.approx(value(s), rel=0.05) assert value(te.h(u=u, p=p)) == pytest.approx(value(h), rel=0.05) assert value(te.h(T=T * pyunits.K, p=p, x=x)) == pytest.approx(value(h), rel=0.05) assert value(te.h(s=s, p=p)) == pytest.approx(value(h), rel=0.05) if value(p) < 2e6 or T < 290: # need data with more significant figure to test here # generally p(s, T) prbably isn't that useful for liquids # so I'll come back to it later with high precision data. continue assert value(te.p(s=s, T=T * pyunits.K)) == pytest.approx(value(p), rel=0.1)
def CTT_week(self,events:dict,timeslots:Dict[str,List[int]],week: int): m = pe.ConcreteModel() #Only include timeslots that are not banned T = [item for key,sublist in timeslots.items() for item in sublist if item not in self.banned_keys] E = [key for key in events] R = [key for key in self.rooms] Index_old = [(e,t,r) for e in E for t in T for r in R] #Remove unnecessary indexes Index = self.remove_busy_room(self.remove_var_close_to_banned(Index_old)) #minimize teacher duties per day m.x = pe.Var(Index, domain = pe.Binary) A = self.teacher_conflict_graph.get("week "+str(week)) teacher_duties = set([event for t in A for event in t]) teacher_expr = sum(sum(m.x[e,t,r] for t in times for e in teacher_duties for r in R if (e,t,r) in Index)-1 for times in timeslots.values()) # #One event per day per course: # m.one_event_one_day = pe.ConstraintList() # for course_events in self.courses.values(): # for day in timeslots.values(): # if any((e,t,r) in Index for e in course_events for t in day for r in R): # m.one_event_one_day.add(sum(m.x[e,t,r] for e in course_events for t in day for r in R if (e,t,r) in Index)<=1) # def obj_rule(m): A = self.student_conflict_graph.get("week "+str(week)) starting_index = self.split_timeslots.get("week "+str(week)).get("day 0")[0] expr = 0 for u,v in A: for t in T: if any((u,l,r) in Index and (v,l,r) in Index for r in R for l in range(max(starting_index,t-self.events.get(u).get("duration")+1),t+1)): expr += sum(m.x[u,l,r]+m.x[v,l,r] for r in R for l in range(max(starting_index,t-self.events.get(u).get("duration")+1),t+1) if (u,l,r) in Index and (v,l,r) in Index) return expr m.obj=pe.Objective(rule=obj_rule,sense = pe.minimize) # m.obj=pe.Objective(expr = teacher_expr, sense = pe.minimize) # m.obj=pe.Objective(expr = 0, sense = pe.minimize) #All events must happen m.events_must_happen = pe.ConstraintList() for e in E: m.events_must_happen.add(sum(m.x[e,t,r] for _,t,r in list(filter(lambda x: e == x[0],Index)))==1) #No teacher conflicts m.teacher_conflict = pe.ConstraintList() starting_index = self.split_timeslots.get("week "+str(week)).get("day 0")[0] print("Start: ",starting_index) for u,v in A: for t in T: if any((u,l,r) in Index and (v,l,r) in Index for r in R for l in range(max(starting_index,t-self.events.get(u).get("duration")+1),t+1)): m.teacher_conflict.add(sum(m.x[u,l,r]+m.x[v,l,r] for r in R for l in range(max(starting_index,t-self.events.get(u).get("duration")+1),t+1) if (u,l,r) in Index and (v,l,r) in Index) <= 1) # #One event per day per course: # m.one_event_one_day = pe.ConstraintList() # for course_events in self.courses.values(): # for day in timeslots.values(): # if any((e,t,r) in Index for e in course_events for t in day for r in R): # m.one_event_one_day.add(sum(m.x[e,t,r] for e in course_events for t in day for r in R if (e,t,r) in Index)<=1) #Room conflicts def room_conf(m,t,r): starting_index = self.split_timeslots.get("week "+str(week)).get("day 0")[0] if any((e,l,r) in Index for e in E for l in range(max(starting_index,t-self.events.get(e).get("duration")+1),t+1)): return sum(m.x[e,l,r] for e in E for l in range(max(starting_index,t-self.events.get(e).get("duration")+1),t+1) if (e,l,r) in Index) <= 1 else: return pe.Constraint.Skip m.room_conflicts = pe.Constraint(T,R,rule=room_conf) #Precedence constraints m.precedence = pe.ConstraintList() for u,v in self.precedence_graph.get("week "+str(week)): for t in T: if any((u,l,r) in Index for l in range(timeslots.get("day 0")[0],t) for r in R): m.precedence.add(sum(m.x[u,l,r]-m.x[v,l,r] for l in range(timeslots.get("day 0")[0],t+1) for r in R if (v,l,r) in Index and (u,l,r) in Index) >= 0) solver = pyomo.opt.SolverFactory('glpk') results = solver.solve(m,tee=True) print("HERE: ",pe.value(m.obj)) for e in E: print("HERE: ",pe.value(m.x[e,timeslots["day 4"][0],0])) return [(e,t,r) for e,t,r in Index if pe.value(m.x[e,t,r]) ==1]
start = time.time() #try: SolverFactory('mindtpy').solve(filename1.m, strategy='OA', iterlim=5) end = time.time() sys.stdout = old_stdout f.write(mystdout.getvalue()) deltat = end - start f.write("\nTime elapsed: {}".format(dt)) f.close() timetable.append([filename, end - start]) subprocess.call(['mv ' + newname + ' ../' + solvername + 'results'], shell=True) trcdata = filename + ', MindtPy, IPOPT, Gurobi' + str( dt ) + ', 0, eqnum?, varnum?, dvarnum?, nznum?, nlnz?, 0, modelstatus?, solvestatus?,' + str( value(filename1.m.obj)) + ', objest?,' + str( deltat) + ', 5, domviolations, numnodes,' + 'user' trcname = name + '_' + solvername + '.trc' with open(trcname, "w+") as trace: trace.write(trcdata) subprocess.call(['mv ' + trcname + ' ../' + solvername + 'results'], shell=True) #except Exception as inst: # errortable.append([filename, inst]) # continue with open('1-instancetable' + solvername + '.csv', 'w+') as table: writer = csv.writer(table) [writer.writerow(r) for r in timetable] with open('2-errortable' + solvername + '.csv', 'w+') as errors:
def initialize(self, state_args={}, outlvl=0, solver='ipopt', optarg={ 'tol': 1e-6, 'max_iter': 30 }): """ Initialize the outlet turbine stage model. This deactivates the specialized constraints, then does the isentropic turbine initialization, then reactivates the constraints and solves. Args: state_args (dict): Initial state for property initialization outlvl (int): Amount of output (0 to 3) 0 is lowest solver (str): Solver to use for initialization optarg (dict): Solver arguments dictionary """ stee = True if outlvl >= 3 else False # sp is what to save to make sure state after init is same as the start # saves value, fixed, and active state, doesn't load originally free # values, this makes sure original problem spec is same but initializes # the values of free vars sp = StoreSpec.value_isfixed_isactive(only_fixed=True) istate = to_json(self, return_dict=True, wts=sp) # Deactivate special constraints self.stodola_equation.deactivate() self.isentropic_enthalpy.deactivate() self.efficiency_correlation.deactivate() self.deltaP.unfix() self.ratioP.unfix() # Fix turbine parameters + eff_isen self.eff_dry.fix() self.design_exhaust_flow_vol.fix() self.flow_coeff.fix() # fix inlet and free outlet for t in self.flowsheet().config.time: for k, v in self.inlet.vars.items(): v[t].fix() for k, v in self.outlet.vars.items(): v[t].unfix() # If there isn't a good guess for efficiency or outlet pressure # provide something reasonable. eff = self.efficiency_isentropic[t] eff.fix( eff.value if value(eff) > 0.3 and value(eff) < 1.0 else 0.8) # for outlet pressure try outlet pressure, pressure ratio, delta P, # then if none of those look reasonable use a pressure ratio of 0.8 # to calculate outlet pressure Pout = self.outlet.pressure[t] Pin = self.inlet.pressure[t] prdp = value((self.deltaP[t] - Pin) / Pin) if value(Pout / Pin) > 0.9 or value(Pout / Pin) < 0.01: if value(self.ratioP[t]) < 0.9 and value( self.ratioP[t]) > 0.01: Pout.fix(value(Pin * self.ratioP)) elif prdp < 0.9 and prdp > 0.01: Pout.fix(value(prdp * Pin)) else: Pout.fix(value(Pin * 0.3)) else: Pout.fix() self.deltaP[:] = value(Pout - Pin) self.ratioP[:] = value(Pout / Pin) for t in self.flowsheet().config.time: self.properties_isentropic[t].pressure.value = \ value(self.outlet.pressure[t]) self.properties_isentropic[t].flow_mol.value = \ value(self.inlet.flow_mol[t]) self.properties_isentropic[t].enth_mol.value = \ value(self.inlet.enth_mol[t]*0.95) self.outlet.flow_mol[t].value = \ value(self.inlet.flow_mol[t]) self.outlet.enth_mol[t].value = \ value(self.inlet.enth_mol[t]*0.95) # Make sure the initialization problem has no degrees of freedom # This shouldn't happen here unless there is a bug in this dof = degrees_of_freedom(self) try: assert (dof == 0) except: _log.exception("degrees_of_freedom = {}".format(dof)) raise # one bad thing about reusing this is that the log messages aren't # really compatible with being nested inside another initialization super(TurbineOutletStageData, self).initialize(state_args=state_args, outlvl=outlvl, solver=solver, optarg=optarg) # Free eff_isen and activate sepcial constarints self.efficiency_isentropic.unfix() self.outlet.pressure.unfix() self.stodola_equation.activate() self.isentropic_enthalpy.activate() self.efficiency_correlation.activate() slvr = SolverFactory(solver) slvr.options = optarg res = slvr.solve(self, tee=stee) if outlvl > 0: if res.solver.termination_condition == TerminationCondition.optimal: _log.info("{} Initialization Complete.".format(self.name)) else: _log.warning( """{} Initialization Failed. The most likely cause of initialization failure for the Turbine inlet stages model is that the flow coefficient is not compatible with flow rate guess.""".format(self.name)) # reload original spec from_json(self, sd=istate, wts=sp)
def test_T350_P1_x5(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={'dynamic': False}) m.fs.props = BT_PR.BTParameterBlock( default={'valid_phase': ('Vap', 'Liq')}) m.fs.state = m.fs.props.build_state_block( default={'defined_state': True}) m.fs.state.flow_mol.fix(100) m.fs.state.mole_frac_comp["benzene"].fix(0.5) m.fs.state.mole_frac_comp["toluene"].fix(0.5) m.fs.state.temperature.fix(350) m.fs.state.pressure.fix(1e5) # Trigger build of enthalpy and entropy m.fs.state.enth_mol_phase m.fs.state.entr_mol_phase m.fs.state.initialize(outlvl=0) solver.solve(m) assert pytest.approx(value(m.fs.state._teq), abs=1e-1) == 365 assert 0.0035346 == pytest.approx( value(m.fs.state.compress_fact_phase["Liq"]), 1e-5) assert 0.966749 == pytest.approx( value(m.fs.state.compress_fact_phase["Vap"]), 1e-5) assert pytest.approx( value(m.fs.state.fug_coeff_phase_comp["Liq", "benzene"]), 1e-5) == 0.894676 assert pytest.approx( value(m.fs.state.fug_coeff_phase_comp["Liq", "toluene"]), 1e-5) == 0.347566 assert pytest.approx( value(m.fs.state.fug_coeff_phase_comp["Vap", "benzene"]), 1e-5) == 0.971072 assert pytest.approx( value(m.fs.state.fug_coeff_phase_comp["Vap", "toluene"]), 1e-5) == 0.959791 assert pytest.approx( value(m.fs.state.mole_frac_phase_comp["Liq", "benzene"]), 1e-5) == 0.5 assert pytest.approx( value(m.fs.state.mole_frac_phase_comp["Liq", "toluene"]), 1e-5) == 0.5 assert pytest.approx( value(m.fs.state.mole_frac_phase_comp["Vap", "benzene"]), 1e-5) == 0.70584 assert pytest.approx( value(m.fs.state.mole_frac_phase_comp["Vap", "toluene"]), 1e-5) == 0.29416 assert pytest.approx(value(m.fs.state.enth_mol_phase["Liq"]), 1e-5) == 38942.8 assert pytest.approx(value(m.fs.state.enth_mol_phase["Vap"]), 1e-5) == 78048.7 assert pytest.approx(value(m.fs.state.entr_mol_phase["Liq"]), 1e-5) == -367.558 assert pytest.approx(value(m.fs.state.entr_mol_phase["Vap"]), 1e-5) == -269.0553
def test_solution_equilibrium(self, equilibrium_reactions_config): model = equilibrium_reactions_config assert pytest.approx(297.9, rel=1e-5) == value( model.fs.unit.outlet.temperature[0]) assert pytest.approx(10.0002, rel=1e-5) == value( model.fs.unit.outlet.flow_mol[0]) assert pytest.approx(101325, rel=1e-5) == value( model.fs.unit.outlet.pressure[0]) total_molar_density = \ value(model.fs.unit.control_volume.properties_out[0.0].dens_mol_phase['Liq'])/1000 assert pytest.approx(54.612040964248116, rel=1e-5) == total_molar_density total_salt = value(model.fs.unit.outlet.mole_frac_comp[ 0, "Na_+"]) * total_molar_density * 23 total_salt += value(model.fs.unit.outlet.mole_frac_comp[ 0, "Cl_-"]) * total_molar_density * 35.44 total_salt += value(model.fs.unit.outlet.mole_frac_comp[ 0, "NaHCO3"]) * total_molar_density * 84 psu = total_salt / (total_molar_density * 18) * 1000 assert pytest.approx(32.66105, rel=1e-5) == psu total_carbonate = value(model.fs.unit.outlet.mole_frac_comp[ 0, "NaHCO3"]) * total_molar_density total_carbonate += value( model.fs.unit.outlet.mole_frac_comp[0, "H2CO3"]) * total_molar_density total_carbonate += value(model.fs.unit.outlet.mole_frac_comp[ 0, "HCO3_-"]) * total_molar_density total_carbonate += value(model.fs.unit.outlet.mole_frac_comp[ 0, "CO3_2-"]) * total_molar_density assert pytest.approx(0.0020528746175810923, rel=1e-5) == total_carbonate carbonate_alk = value(model.fs.unit.outlet.mole_frac_comp[ 0, "HCO3_-"]) * total_molar_density carbonate_alk += 2 * value(model.fs.unit.outlet.mole_frac_comp[ 0, "CO3_2-"]) * total_molar_density carbonate_alk += value( model.fs.unit.outlet.mole_frac_comp[0, "OH_-"]) * total_molar_density carbonate_alk -= value( model.fs.unit.outlet.mole_frac_comp[0, "H_+"]) * total_molar_density carbonate_alk = carbonate_alk * 50000 assert pytest.approx(79.389737, rel=1e-4) == carbonate_alk pH = -value( log10(model.fs.unit.outlet.mole_frac_comp[0, "H_+"] * total_molar_density)) pOH = -value( log10(model.fs.unit.outlet.mole_frac_comp[0, "OH_-"] * total_molar_density)) assert pytest.approx(8.31763834, rel=1e-4) == pH assert pytest.approx(5.6916662, rel=1e-4) == pOH