def test_disc_multidimen_index(self): m = self.m.clone() m.s2 = Set(initialize=[('A', 'B'), ('C', 'D'), ('E', 'F')]) m.v2 = Var(m.t, m.s2) m.dv2 = DerivativeVar(m.v2) m.v3 = Var(m.s2, m.t) m.dv3 = DerivativeVar(m.v3) disc = TransformationFactory('dae.finite_difference') disc.apply_to(m, nfe=5) self.assertTrue(hasattr(m, 'dv1_disc_eq')) self.assertTrue(hasattr(m, 'dv2_disc_eq')) self.assertTrue(hasattr(m, 'dv3_disc_eq')) self.assertTrue(len(m.dv2_disc_eq) == 15) self.assertTrue(len(m.v2) == 18) self.assertTrue(len(m.dv3_disc_eq) == 15) self.assertTrue(len(m.v3) == 18) expected_disc_points = [0, 2.0, 4.0, 6.0, 8.0, 10] disc_info = m.t.get_discretization_info() self.assertTrue(disc_info['scheme'] == 'BACKWARD Difference') for idx, val in enumerate(list(m.t)): self.assertAlmostEqual(val, expected_disc_points[idx])
def test_disc_single_index_backward(self): m = self.m.clone() disc = TransformationFactory('dae.finite_difference') disc.apply_to(m, nfe=5) self.assertTrue(hasattr(m, 'dv1_disc_eq')) self.assertTrue(len(m.dv1_disc_eq) == 5) self.assertTrue(len(m.v1) == 6) expected_disc_points = [0, 2.0, 4.0, 6.0, 8.0, 10] disc_info = m.t.get_discretization_info() self.assertTrue(disc_info['scheme'] == 'BACKWARD Difference') for idx, val in enumerate(list(m.t)): self.assertAlmostEqual(val, expected_disc_points[idx]) self.assertTrue(hasattr(m, '_pyomo_dae_reclassified_derivativevars')) self.assertTrue(m.dv1 in m._pyomo_dae_reclassified_derivativevars) output = \ """\ dv1_disc_eq : Size=5, Index=t, Active=True Key : Lower : Body : Upper : Active 2.0 : 0.0 : dv1[2.0] - 0.5*(v1[2.0] - v1[0]) : 0.0 : True 4.0 : 0.0 : dv1[4.0] - 0.5*(v1[4.0] - v1[2.0]) : 0.0 : True 6.0 : 0.0 : dv1[6.0] - 0.5*(v1[6.0] - v1[4.0]) : 0.0 : True 8.0 : 0.0 : dv1[8.0] - 0.5*(v1[8.0] - v1[6.0]) : 0.0 : True 10 : 0.0 : dv1[10] - 0.5*(v1[10] - v1[8.0]) : 0.0 : True """ out = StringIO() m.dv1_disc_eq.pprint(ostream=out) self.assertEqual(output, out.getvalue())
def test_disc_invalid_options(self): m = self.m.clone() with self.assertRaises(TypeError): TransformationFactory('dae.finite_difference').apply_to(m, wrt=m.s) with self.assertRaises(ValueError): TransformationFactory('dae.finite_difference').apply_to(m, nfe=-1) with self.assertRaises(ValueError): TransformationFactory('dae.finite_difference').apply_to(m, scheme='foo') with self.assertRaises(ValueError): TransformationFactory('dae.finite_difference').apply_to(m, foo=True) TransformationFactory('dae.finite_difference').apply_to(m, wrt=m.t) with self.assertRaises(ValueError): TransformationFactory('dae.finite_difference').apply_to(m, wrt=m.t) m = self.m.clone() disc = TransformationFactory('dae.finite_difference') disc.apply_to(m) with self.assertRaises(ValueError): disc.apply_to(m)
def test_disc_multi_index(self): m = self.m.clone() m.v2 = Var(m.t, m.s) m.dv2 = DerivativeVar(m.v2) disc = TransformationFactory('dae.collocation') disc.apply_to(m, nfe=5, ncp=3) self.assertTrue(hasattr(m, 'dv1_disc_eq')) self.assertTrue(hasattr(m, 'dv2_disc_eq')) self.assertTrue(len(m.dv2_disc_eq) == 45) self.assertTrue(len(m.v2) == 48) expected_tau_points = [0.0, 0.1550510257216822, 0.64494897427831788, 1.0] expected_disc_points = [0, 0.310102, 1.289898, 2.0, 2.310102, 3.289898, 4.0, 4.310102, 5.289898, 6.0, 6.310102, 7.289898, 8.0, 8.310102, 9.289898, 10] disc_info = m.t.get_discretization_info() self.assertTrue(disc_info['scheme'] == 'LAGRANGE-RADAU') for idx, val in enumerate(disc_info['tau_points']): self.assertAlmostEqual(val, expected_tau_points[idx]) for idx, val in enumerate(list(m.t)): self.assertAlmostEqual(val, expected_disc_points[idx]) self.assertTrue( hasattr(m, '_pyomo_dae_reclassified_derivativevars')) self.assertTrue(m.dv1 in m._pyomo_dae_reclassified_derivativevars) self.assertTrue(m.dv2 in m._pyomo_dae_reclassified_derivativevars)
def _test_disc_first(self, tname): ofile = join(currdir, tname + '.' + self.sim_mod + '.out') bfile = join(currdir, tname + '.' + self.sim_mod + '.txt') setup_redirect(ofile) # create model exmod = import_file(join(exdir, tname + '.py')) m = exmod.create_model() # Discretize model discretizer = TransformationFactory('dae.collocation') discretizer.apply_to(m, nfe=10, ncp=5) # Simulate model sim = Simulator(m, package=self.sim_mod) if hasattr(m, 'var_input'): tsim, profiles = sim.simulate(numpoints=100, varying_inputs=m.var_input) else: tsim, profiles = sim.simulate(numpoints=100) # Initialize model sim.initialize_model() self._print(m, profiles) reset_redirect() if not os.path.exists(bfile): os.rename(ofile, bfile) # os.system('diff ' + ofile + ' ' + bfile) self.assertFileEqualsBaseline(ofile, bfile, tolerance=0.01)
def test_var_bound_propagate_revert(self): """Test to make sure bound propagation revert works.""" m = ConcreteModel() m.v1 = Var(initialize=1, bounds=(1, 3)) m.v2 = Var(initialize=2, bounds=(0, 8)) m.v3 = Var(initialize=3, bounds=(2, 4)) m.v4 = Var(initialize=4, bounds=(0, 5)) m.c1 = Constraint(expr=m.v1 == m.v2) m.c2 = Constraint(expr=m.v2 == m.v3) m.c3 = Constraint(expr=m.v3 == m.v4) xfrm = TransformationFactory('contrib.propagate_eq_var_bounds') xfrm.apply_to(m, tmp=True) self.assertEquals(value(m.v1.lb), 2) self.assertEquals(value(m.v1.lb), value(m.v2.lb)) self.assertEquals(value(m.v1.lb), value(m.v3.lb)) self.assertEquals(value(m.v1.lb), value(m.v4.lb)) self.assertEquals(value(m.v1.ub), 3) self.assertEquals(value(m.v1.ub), value(m.v2.ub)) self.assertEquals(value(m.v1.ub), value(m.v3.ub)) self.assertEquals(value(m.v1.ub), value(m.v4.ub)) xfrm.revert(m) self.assertEquals(value(m.v1.lb), 1) self.assertEquals(value(m.v2.lb), 0) self.assertEquals(value(m.v3.lb), 2) self.assertEquals(value(m.v4.lb), 0) self.assertEquals(value(m.v1.ub), 3) self.assertEquals(value(m.v2.ub), 8) self.assertEquals(value(m.v3.ub), 4) self.assertEquals(value(m.v4.ub), 5)
def test_disc_multi_index2(self): m = self.m.clone() m.t2 = ContinuousSet(bounds=(0, 5)) m.v2 = Var(m.t, m.t2) m.dv2dt = DerivativeVar(m.v2, wrt=m.t) m.dv2dt2 = DerivativeVar(m.v2, wrt=m.t2) disc = TransformationFactory('dae.collocation') disc.apply_to(m, nfe=2, ncp=2) self.assertTrue(hasattr(m, 'dv2dt_disc_eq')) self.assertTrue(hasattr(m, 'dv2dt2_disc_eq')) self.assertTrue(len(m.dv2dt_disc_eq) == 20) self.assertTrue(len(m.dv2dt2_disc_eq) == 20) self.assertTrue(len(m.v2) == 25) expected_t_disc_points = [0, 1.666667, 5.0, 6.666667, 10] expected_t2_disc_points = [0, 0.833333, 2.5, 3.333333, 5] for idx, val in enumerate(list(m.t)): self.assertAlmostEqual(val, expected_t_disc_points[idx]) for idx, val in enumerate(list(m.t2)): self.assertAlmostEqual(val, expected_t2_disc_points[idx]) self.assertTrue(hasattr(m, '_pyomo_dae_reclassified_derivativevars')) self.assertTrue(m.dv1 in m._pyomo_dae_reclassified_derivativevars) self.assertTrue(m.dv2dt in m._pyomo_dae_reclassified_derivativevars) self.assertTrue(m.dv2dt2 in m._pyomo_dae_reclassified_derivativevars)
def test_disc_second_order_radau(self): m = self.m.clone() m.dv1dt2 = DerivativeVar(m.v1, wrt=(m.t, m.t)) disc = TransformationFactory('dae.collocation') disc.apply_to(m, nfe=2, ncp=2) self.assertTrue(hasattr(m, 'dv1dt2_disc_eq')) self.assertTrue(len(m.dv1dt2_disc_eq) == 4) self.assertTrue(len(m.v1) == 5) self.assertTrue(hasattr(m, '_pyomo_dae_reclassified_derivativevars')) self.assertTrue(m.dv1 in m._pyomo_dae_reclassified_derivativevars) self.assertTrue(m.dv1dt2 in m._pyomo_dae_reclassified_derivativevars) repn_baseline = {id(m.dv1dt2[5.0]): 1, id(m.v1[0]): -0.24, id(m.v1[1.666667]): 0.36, id(m.v1[5.0]): -0.12} repn = generate_standard_repn(m.dv1dt2_disc_eq[5.0].body) repn_gen = repn_to_rounded_dict(repn, 5) self.assertEqual(repn_baseline, repn_gen) repn_baseline = {id(m.dv1dt2[10]): 1, id(m.v1[5.0]): -0.24, id(m.v1[6.666667]): 0.36, id(m.v1[10]): -0.12} repn = generate_standard_repn(m.dv1dt2_disc_eq[10.0].body) repn_gen = repn_to_rounded_dict(repn, 5) self.assertEqual(repn_baseline, repn_gen)
def test_disc_second_order_legendre(self): m = self.m.clone() m.dv1dt2 = DerivativeVar(m.v1, wrt=(m.t, m.t)) disc = TransformationFactory('dae.collocation') disc.apply_to(m, nfe=2, ncp=2, scheme='LAGRANGE-LEGENDRE') self.assertTrue(hasattr(m, 'dv1dt2_disc_eq')) self.assertTrue(hasattr(m, 'v1_t_cont_eq')) self.assertTrue(len(m.dv1dt2_disc_eq) == 4) self.assertTrue(len(m.v1_t_cont_eq) == 2) self.assertTrue(len(m.v1) == 7) self.assertTrue(hasattr(m, '_pyomo_dae_reclassified_derivativevars')) self.assertTrue(m.dv1 in m._pyomo_dae_reclassified_derivativevars) self.assertTrue(m.dv1dt2 in m._pyomo_dae_reclassified_derivativevars) repn_baseline = {id(m.dv1dt2[1.056624]): 1, id(m.v1[0]): -0.48, id(m.v1[1.056624]): 0.65569, id(m.v1[3.943376]): -0.17569} repn = generate_standard_repn(m.dv1dt2_disc_eq[1.056624].body) repn_gen = repn_to_rounded_dict(repn, 5) self.assertEqual(repn_baseline, repn_gen) repn_baseline = {id(m.dv1dt2[6.056624]): 1, id(m.v1[5.0]): -0.48, id(m.v1[6.056624]): 0.65569, id(m.v1[8.943376]): -0.17569} repn = generate_standard_repn(m.dv1dt2_disc_eq[6.056624].body) repn_gen = repn_to_rounded_dict(repn, 5) self.assertEqual(repn_baseline, repn_gen)
def test_var_bound_propagate_crossover(self): """Test for error message when variable bound crosses over.""" m = ConcreteModel() m.v1 = Var(initialize=1, bounds=(1, 3)) m.v2 = Var(initialize=5, bounds=(4, 8)) m.c1 = Constraint(expr=m.v1 == m.v2) xfrm = TransformationFactory('contrib.propagate_eq_var_bounds') with self.assertRaises(ValueError): xfrm.apply_to(m)
def test_disc_single_index_legendre(self): m = self.m.clone() disc = TransformationFactory('dae.collocation') disc.apply_to(m, nfe=5, ncp=3, scheme='LAGRANGE-LEGENDRE') self.assertTrue(hasattr(m, 'dv1_disc_eq')) self.assertTrue(hasattr(m, 'v1_t_cont_eq')) self.assertTrue(len(m.dv1_disc_eq) == 15) self.assertTrue(len(m.v1_t_cont_eq) == 5) self.assertTrue(len(m.v1) == 21) expected_tau_points = [0.0, 0.11270166537925834, 0.49999999999999989, 0.88729833462074226] expected_disc_points = [0, 0.225403, 1.0, 1.774597, 2.0, 2.225403, 3.0, 3.774597, 4.0, 4.225403, 5.0, 5.774597, 6.0, 6.225403, 7.0, 7.774597, 8.0, 8.225403, 9.0, 9.774597, 10] disc_info = m.t.get_discretization_info() self.assertTrue(disc_info['scheme'] == 'LAGRANGE-LEGENDRE') for idx, val in enumerate(disc_info['tau_points']): self.assertAlmostEqual(val, expected_tau_points[idx]) for idx, val in enumerate(list(m.t)): self.assertAlmostEqual(val, expected_disc_points[idx]) self.assertTrue(hasattr(m, '_pyomo_dae_reclassified_derivativevars')) self.assertTrue(m.dv1 in m._pyomo_dae_reclassified_derivativevars) repn_baseline = {id(m.dv1[3.0]): 1, id(m.v1[2.0]): -1.5, id(m.v1[2.225403]): 2.86374, id(m.v1[3.0]): -1.0, id(m.v1[3.774597]): -0.36374} repn = generate_standard_repn(m.dv1_disc_eq[3.0].body) repn_gen = repn_to_rounded_dict(repn, 5) self.assertEqual(repn_baseline, repn_gen) repn_baseline = {id(m.dv1[5.0]): 1, id(m.v1[4.0]): -1.5, id(m.v1[4.225403]): 2.86374, id(m.v1[5.0]): -1.0, id(m.v1[5.774597]): -0.36374} repn = generate_standard_repn(m.dv1_disc_eq[5.0].body) repn_gen = repn_to_rounded_dict(repn, 5) self.assertEqual(repn_baseline, repn_gen)
def test_fixed_var_revert(self): """Test for reversion of fixed variables.""" m = ConcreteModel() m.v1 = Var(initialize=1) m.v2 = Var(initialize=2) m.v1.setub(2) m.v1.setlb(2) xfrm = TransformationFactory('contrib.detect_fixed_vars') xfrm.apply_to(m, tmp=True) self.assertTrue(m.v1.fixed) self.assertFalse(m.v2.fixed) xfrm.revert(m) self.assertFalse(m.v1.fixed) self.assertEqual(value(m.v1), 1)
def test_disc_single_index_radau(self): m = self.m.clone() disc = TransformationFactory('dae.collocation') disc.apply_to(m, nfe=5, ncp=3) self.assertTrue(hasattr(m, 'dv1_disc_eq')) self.assertTrue(len(m.dv1_disc_eq) == 15) self.assertTrue(len(m.v1) == 16) expected_tau_points = [0.0, 0.1550510257216822, 0.64494897427831788, 1.0] expected_disc_points = [0, 0.310102, 1.289898, 2.0, 2.310102, 3.289898, 4.0, 4.310102, 5.289898, 6.0, 6.310102, 7.289898, 8.0, 8.310102, 9.289898, 10] disc_info = m.t.get_discretization_info() self.assertTrue(disc_info['scheme'] == 'LAGRANGE-RADAU') for idx, val in enumerate(disc_info['tau_points']): self.assertAlmostEqual(val, expected_tau_points[idx]) for idx, val in enumerate(list(m.t)): self.assertAlmostEqual(val, expected_disc_points[idx]) self.assertTrue(hasattr(m, '_pyomo_dae_reclassified_derivativevars')) self.assertTrue(m._pyomo_dae_reclassified_derivativevars[0] is m.dv1) repn_baseline = {id(m.dv1[2.0]): 1.0, id(m.v1[0]): 1.5, id(m.v1[0.310102]): -2.76599, id(m.v1[1.289898]): 3.76599, id(m.v1[2.0]): -2.5} repn = generate_standard_repn(m.dv1_disc_eq[2.0].body) repn_gen = repn_to_rounded_dict(repn, 5) self.assertEqual(repn_baseline, repn_gen) repn_baseline = {id(m.dv1[4.0]): 1.0, id(m.v1[2.0]): 1.5, id(m.v1[2.310102]): -2.76599, id(m.v1[3.289898]): 3.76599, id(m.v1[4.0]): -2.5} repn = generate_standard_repn(m.dv1_disc_eq[4.0].body) repn_gen = repn_to_rounded_dict(repn, 5) self.assertEqual(repn_baseline, repn_gen)
def test_disc_second_order_central(self): m = self.m.clone() m.dv1dt2 = DerivativeVar(m.v1, wrt=(m.t, m.t)) disc = TransformationFactory('dae.finite_difference') disc.apply_to(m, nfe=2, scheme='CENTRAL') self.assertTrue(hasattr(m, 'dv1dt2_disc_eq')) self.assertTrue(len(m.dv1dt2_disc_eq) == 1) self.assertTrue(len(m.v1) == 3) output = \ """\ dv1dt2_disc_eq : Size=1, Index=t, Active=True Key : Lower : Body : Upper : Active 5.0 : 0.0 : dv1dt2[5.0] - 0.04*(v1[10] - 2*v1[5.0] + v1[0]) : 0.0 : True """ out = StringIO() m.dv1dt2_disc_eq.pprint(ostream=out) self.assertEqual(output, out.getvalue())
def test_deactivate_trivial_constraints_revert(self): """Test for reversion of trivial constraint deactivation.""" m = ConcreteModel() m.v1 = Var(initialize=1) m.v2 = Var(initialize=2) m.v3 = Var(initialize=3) m.c = Constraint(expr=m.v1 <= m.v2) m.c2 = Constraint(expr=m.v2 >= m.v3) m.c3 = Constraint(expr=m.v1 <= 5) m.v1.fix() xfrm = TransformationFactory( 'contrib.deactivate_trivial_constraints') xfrm.apply_to(m, tmp=True) self.assertTrue(m.c.active) self.assertTrue(m.c2.active) self.assertFalse(m.c3.active) xfrm.revert(m) self.assertTrue(m.c3.active)
def test_var_fix_revert(self): """Test to make sure that variable fixing reversion works.""" 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() fvp = TransformationFactory('contrib.propagate_fixed_vars') fvp.apply_to(m, tmp=True) self.assertTrue(m.v1.fixed) self.assertTrue(m.v2.fixed) self.assertTrue(m.v3.fixed) self.assertTrue(m.v4.fixed) fvp.revert(m) self.assertFalse(m.v1.fixed) self.assertTrue(m.v2.fixed) self.assertFalse(m.v3.fixed) self.assertFalse(m.v4.fixed)
def test_disc_second_order_backward(self): m = self.m.clone() m.dv1dt2 = DerivativeVar(m.v1, wrt=(m.t, m.t)) disc = TransformationFactory('dae.finite_difference') disc.apply_to(m, nfe=2) self.assertTrue(hasattr(m, 'dv1dt2_disc_eq')) self.assertTrue(len(m.dv1dt2_disc_eq) == 1) self.assertTrue(len(m.v1) == 3) self.assertTrue(hasattr(m, '_pyomo_dae_reclassified_derivativevars')) self.assertTrue(m.dv1 in m._pyomo_dae_reclassified_derivativevars) self.assertTrue(m.dv1dt2 in m._pyomo_dae_reclassified_derivativevars) output = \ """\ dv1dt2_disc_eq : Size=1, Index=t, Active=True Key : Lower : Body : Upper : Active 10 : 0.0 : dv1dt2[10] - 0.04*(v1[10] - 2*v1[5.0] + v1[0]) : 0.0 : True """ out = StringIO() m.dv1dt2_disc_eq.pprint(ostream=out) self.assertEqual(output, out.getvalue())
def test_disc_multi_index2(self): m = self.m.clone() m.t2 = ContinuousSet(bounds=(0, 5)) m.v2 = Var(m.t, m.t2) m.dv2dt = DerivativeVar(m.v2, wrt=m.t) m.dv2dt2 = DerivativeVar(m.v2, wrt=m.t2) disc = TransformationFactory('dae.finite_difference') disc.apply_to(m, nfe=2) self.assertTrue(hasattr(m, 'dv2dt_disc_eq')) self.assertTrue(hasattr(m, 'dv2dt2_disc_eq')) self.assertTrue(len(m.dv2dt_disc_eq) == 6) self.assertTrue(len(m.dv2dt2_disc_eq) == 6) self.assertTrue(len(m.v2) == 9) expected_t_disc_points = [0, 5.0, 10] expected_t2_disc_points = [0, 2.5, 5] for idx, val in enumerate(list(m.t)): self.assertAlmostEqual(val, expected_t_disc_points[idx]) for idx, val in enumerate(list(m.t2)): self.assertAlmostEqual(val, expected_t2_disc_points[idx])
def test_discretize_twice(self): m = self.m.clone() disc1 = TransformationFactory('dae.finite_difference') disc1.apply_to(m, nfe=5) disc2 = TransformationFactory('dae.finite_difference') with self.assertRaises(DAE_Error): disc2.apply_to(m, nfe=5)
def test_discretize_twice(self): m = self.m.clone() disc1 = TransformationFactory('dae.collocation') disc1.apply_to(m, nfe=5, ncp=3) disc2 = TransformationFactory('dae.collocation') with self.assertRaises(DAE_Error): disc2.apply_to(m, nfe=5, ncp=3)
def test_link_with_gdp_indicators(self): m = _generate_boolean_model(4) m.d1 = Disjunct() m.d2 = Disjunct() m.x = Var() m.dd = Disjunct([1, 2]) m.d1.c = Constraint(expr=m.x >= 2) m.d2.c = Constraint(expr=m.x <= 10) m.dd[1].c = Constraint(expr=m.x >= 5) m.dd[2].c = Constraint(expr=m.x <= 6) m.Y[1].associate_binary_var(m.d1.binary_indicator_var) m.Y[2].associate_binary_var(m.d2.binary_indicator_var) m.Y[3].associate_binary_var(m.dd[1].binary_indicator_var) m.Y[4].associate_binary_var(m.dd[2].binary_indicator_var) m.p = LogicalConstraint(expr=m.Y[1].implies(lor(m.Y[3], m.Y[4]))) m.p2 = LogicalConstraint(expr=atmost(2, *m.Y[:])) TransformationFactory('core.logical_to_linear').apply_to(m) _constrs_contained_within( self, [(1, m.dd[1].binary_indicator_var + m.dd[2].binary_indicator_var + 1 - m.d1.binary_indicator_var, None), (None, m.d1.binary_indicator_var + m.d2.binary_indicator_var + m.dd[1].binary_indicator_var + m.dd[2].binary_indicator_var, 2)], m.logic_to_linear.transformed_constraints)
def build(self): # Call UnitModel.build to setup dynamics super(HydrogenTurbineData, self).build() self.compressor = Compressor( default={"property_package": self.config.property_package}) self.stoic_reactor = StoichiometricReactor( default={ "property_package": self.config.property_package, "reaction_package": self.config.reaction_package, "has_heat_of_reaction": True, "has_heat_transfer": False, "has_pressure_change": False }) self.turbine = Turbine( default={"property_package": self.config.property_package}) # Declare var for reactor conversion self.stoic_reactor.conversion = Var(initialize=0.75, bounds=(0, 1)) self.stoic_reactor.conv_constraint = Constraint( expr=self.stoic_reactor.conversion * self.stoic_reactor.inlet.mole_frac_comp[0, "hydrogen"] == ( self.stoic_reactor.inlet.mole_frac_comp[0, "hydrogen"] - self.stoic_reactor.outlet.mole_frac_comp[0, "hydrogen"])) # Connect arcs self.comp_to_reactor = Arc(source=self.compressor.outlet, destination=self.stoic_reactor.inlet) self.reactor_to_turbine = Arc(source=self.stoic_reactor.outlet, destination=self.turbine.inlet) TransformationFactory("network.expand_arcs").apply_to(self)
def solve_flowsheet(**desal_kwargs): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) build(m, **desal_kwargs) TransformationFactory("network.expand_arcs").apply_to(m) # scale scale(m, **desal_kwargs) calculate_scaling_factors(m) # initialize m.fs.feed.initialize() propagate_state(m.fs.s_pretrt_tb) initialize(m, **desal_kwargs) check_dof(m) solve_block(m, tee=False, fail_flag=True) # report print('===================================' '\n Simulation ') report(m, **desal_kwargs) return m
def test_zero_term_removal(self): """Test for removing zero terms from linear constraints.""" m = ConcreteModel() m.v0 = Var() m.v1 = Var() m.v2 = Var() m.v3 = Var() m.c = Constraint(expr=m.v0 == m.v1 * m.v2 + m.v3) m.c2 = Constraint(expr=m.v1 * m.v2 + m.v3 <= m.v0) m.c3 = Constraint(expr=m.v0 <= m.v1 * m.v2 + m.v3) m.c4 = Constraint(expr=EXPR.inequality(1, m.v1 * m.v2 + m.v3, 3)) m.v1.fix(0) TransformationFactory('contrib.remove_zero_terms').apply_to(m) m.v1.unfix() # Check that the term no longer exists self.assertFalse( any(id(m.v1) == id(v) for v in EXPR.identify_variables(m.c.body))) self.assertFalse( any(id(m.v1) == id(v) for v in EXPR.identify_variables(m.c2.body))) self.assertFalse( any(id(m.v1) == id(v) for v in EXPR.identify_variables(m.c3.body))) self.assertFalse( any(id(m.v1) == id(v) for v in EXPR.identify_variables(m.c4.body)))
def test_get_stream_table_contents(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.props = PhysicalParameterTestBlock() m.fs.config.default_property_package = m.fs.props m.fs.unit1 = Heater() m.fs.unit2 = Heater() m.fs.stream = Arc(source=m.fs.unit1.outlet, destination=m.fs.unit2.inlet) TransformationFactory("network.expand_arcs").apply_to(m) df = m.fs._get_stream_table_contents() assert df.loc["pressure"]["stream"] == 1e5 assert df.loc["temperature"]["stream"] == 300 assert df.loc["component_flow_phase ('p1', 'c1')"]["stream"] == 2.0 assert df.loc["component_flow_phase ('p1', 'c2')"]["stream"] == 2.0 assert df.loc["component_flow_phase ('p2', 'c1')"]["stream"] == 2.0 assert df.loc["component_flow_phase ('p2', 'c2')"]["stream"] == 2.0 m.fs.report()
def test_induced_linearity_case2(self): m = ConcreteModel() m.x = Var([0], bounds=(-3, 8)) m.y = Var(RangeSet(4), domain=Binary) m.z = Var(domain=Integers, bounds=(-1, 2)) m.constr = Constraint(expr=m.x[0] == m.y[1] + 2 * m.y[2] + m.y[3] + 2 * m.y[4] + m.z) m.logical = ConstraintList() m.logical.add(expr=m.y[1] + m.y[2] == 1) m.logical.add(expr=m.y[3] + m.y[4] == 1) m.logical.add(expr=m.y[2] + m.y[4] <= 1) m.b = Var(bounds=(-2, 7)) m.c = Var() m.bilinear = Constraint(expr=(m.x[0] - 3) * (m.b + 2) - (m.c + 4) * m.b + exp(m.b**2) * m.x[0] <= m.c) TransformationFactory('contrib.induced_linearity').apply_to(m) xfrmed_blk = m._induced_linearity_info.x0_b_bilinear self.assertSetEqual(set(xfrmed_blk.valid_values), set([1, 2, 3, 4, 5])) select_one_repn = generate_standard_repn( xfrmed_blk.select_one_value.body) self.assertEqual( ComponentSet(select_one_repn.linear_vars), ComponentSet(xfrmed_blk.x_active[i] for i in xfrmed_blk.valid_values))
def test_deactivate_trivial_constraints_revert(self): """Test for reversion of trivial constraint deactivation.""" m = ConcreteModel() m.v1 = Var(initialize=1) m.v2 = Var(initialize=2) m.v3 = Var(initialize=3) m.c = Constraint(expr=m.v1 <= m.v2) m.c2 = Constraint(expr=m.v2 >= m.v3) m.c3 = Constraint(expr=m.v1 <= 5) m.v1.fix() xfrm = TransformationFactory('contrib.deactivate_trivial_constraints') xfrm.apply_to(m, tmp=True) self.assertTrue(m.c.active) self.assertTrue(m.c2.active) self.assertFalse(m.c3.active) xfrm.revert(m) self.assertTrue(m.c3.active)
def test_lookup_radau_collocation_points(self): # Save initial flag value colloc_numpy_avail = pyomo.dae.plugins.colloc.numpy_available # Numpy flag must be False to test lookup pyomo.dae.plugins.colloc.numpy_available = False m = self.m.clone() disc = TransformationFactory('dae.collocation') disc.apply_to(m, nfe=5, ncp=3) self.assertTrue(hasattr(m, 'dv1_disc_eq')) self.assertTrue(len(m.dv1_disc_eq) == 15) self.assertTrue(len(m.v1) == 16) expected_tau_points = [0.0, 0.1550510257216822, 0.64494897427831788, 1.0] expected_disc_points = [0, 0.310102, 1.289898, 2.0, 2.310102, 3.289898, 4.0, 4.310102, 5.289898, 6.0, 6.310102, 7.289898, 8.0, 8.310102, 9.289898, 10] disc_info = m.t.get_discretization_info() self.assertTrue(disc_info['scheme'] == 'LAGRANGE-RADAU') for idx, val in enumerate(disc_info['tau_points']): self.assertAlmostEqual(val, expected_tau_points[idx]) for idx, val in enumerate(list(m.t)): self.assertAlmostEqual(val, expected_disc_points[idx]) m = self.m.clone() with self.assertRaises(ValueError): disc = TransformationFactory('dae.collocation') disc.apply_to(m, ncp=15, scheme='LAGRANGE-RADAU') # Restore initial flag value pyomo.dae.plugins.colloc.numpy_available = colloc_numpy_avail
def test_lookup_legendre_collocation_points(self): # Save initial flag value colloc_numpy_avail = pyomo.dae.plugins.colloc.numpy_available # Numpy flag must be False to test lookup pyomo.dae.plugins.colloc.numpy_available = False m = self.m.clone() disc = TransformationFactory('dae.collocation') disc.apply_to(m, nfe=5, ncp=3, scheme='LAGRANGE-LEGENDRE') self.assertTrue(hasattr(m, 'dv1_disc_eq')) self.assertTrue(len(m.dv1_disc_eq) == 15) self.assertTrue(len(m.v1) == 21) expected_tau_points = [0.0, 0.11270166537925834, 0.49999999999999989, 0.88729833462074226] expected_disc_points = [0, 0.225403, 1.0, 1.774597, 2.0, 2.225403, 3.0, 3.774597, 4.0, 4.225403, 5.0, 5.774597, 6.0, 6.225403, 7.0, 7.774597, 8.0, 8.225403, 9.0, 9.774597, 10] disc_info = m.t.get_discretization_info() self.assertTrue(disc_info['scheme'] == 'LAGRANGE-LEGENDRE') for idx, val in enumerate(disc_info['tau_points']): self.assertAlmostEqual(val, expected_tau_points[idx]) for idx, val in enumerate(list(m.t)): self.assertAlmostEqual(val, expected_disc_points[idx]) m = self.m.clone() with self.assertRaises(ValueError): disc = TransformationFactory('dae.collocation') disc.apply_to(m, ncp=15, scheme='LAGRANGE-LEGENDRE') # Restore initial flag value pyomo.dae.plugins.colloc.numpy_available = colloc_numpy_avail
def test_no_strip_domain(self): """Test bounds stripping without domain change.""" m = ConcreteModel() m.v0 = Var(bounds=(2, 4)) m.v1 = Var(domain=NonNegativeReals) m.v2 = Var(domain=PositiveReals) m.v3 = Var(bounds=(-1, 1)) m.v4 = Var(domain=Binary) m.v5 = Var(domain=Integers, bounds=(15, 16)) xfrm = TransformationFactory('contrib.strip_var_bounds') xfrm.apply_to(m, strip_domains=False, reversible=True) self.assertEqual(m.v0.bounds, (None, None)) self.assertEqual(m.v1.bounds, (0, None)) self.assertEqual(m.v2.bounds, (0, None)) self.assertEqual(m.v3.bounds, (None, None)) self.assertEqual(m.v4.bounds, (0, 1)) self.assertEqual(m.v5.bounds, (None, None)) self.assertEqual(m.v0.domain, Reals) self.assertEqual(m.v1.domain, NonNegativeReals) self.assertEqual(m.v2.domain, PositiveReals) self.assertEqual(m.v3.domain, Reals) self.assertEqual(m.v4.domain, Binary) self.assertEqual(m.v5.domain, Integers) xfrm.revert(m) self.assertEqual(m.v0.bounds, (2, 4)) self.assertEqual(m.v1.bounds, (0, None)) self.assertEqual(m.v2.bounds, (0, None)) self.assertEqual(m.v3.bounds, (-1, 1)) self.assertEqual(m.v4.bounds, (0, 1)) self.assertEqual(m.v5.bounds, (15, 16)) self.assertEqual(m.v0.domain, Reals) self.assertEqual(m.v1.domain, NonNegativeReals) self.assertEqual(m.v2.domain, PositiveReals) self.assertEqual(m.v3.domain, Reals) self.assertEqual(m.v4.domain, Binary) self.assertEqual(m.v5.domain, Integers)
def test_lb_constraint_modified(self): m = self.makeModel() TransformationFactory('core.add_slack_variables').apply_to(m) self.checkRule3(m)
def test_reduce_colloc_invalid(self): m = self.m.clone() m.u = Var(m.t) m2 = m.clone() disc = TransformationFactory('dae.collocation') disc2 = TransformationFactory('dae.collocation') disc.apply_to(m, nfe=5, ncp=3) # No ContinuousSet specified with self.assertRaises(TypeError): disc.reduce_collocation_points(m, contset=None) # Component passed in is not a ContinuousSet with self.assertRaises(TypeError): disc.reduce_collocation_points(m, contset=m.s) # Call reduce_collocation_points method before applying discretization with self.assertRaises(RuntimeError): disc2.reduce_collocation_points(m2, contset=m2.t) # Call reduce_collocation_points on a ContinuousSet that hasn't been # discretized m2.tt = ContinuousSet(bounds=(0, 1)) disc2.apply_to(m2, wrt=m2.t) with self.assertRaises(ValueError): disc2.reduce_collocation_points(m2, contset=m2.tt) # No Var specified with self.assertRaises(TypeError): disc.reduce_collocation_points(m, contset=m.t, var=None) # Component passed in is not a Var with self.assertRaises(TypeError): disc.reduce_collocation_points(m, contset=m.t, var=m.s) # New ncp not specified with self.assertRaises(TypeError): disc.reduce_collocation_points(m, contset=m.t, var=m.v1, ncp=None) # Negative ncp specified with self.assertRaises(ValueError): disc.reduce_collocation_points(m, contset=m.t, var=m.v1, ncp=-3) # Too large ncp specified with self.assertRaises(ValueError): disc.reduce_collocation_points(m, contset=m.t, var=m.v1, ncp=10) # Passing Vars not indexed by the ContinuousSet m.v2 = Var() m.v3 = Var(m.s) m.v4 = Var(m.s, m.s) with self.assertRaises(IndexError): disc.reduce_collocation_points(m, contset=m.t, var=m.v2, ncp=1) with self.assertRaises(IndexError): disc.reduce_collocation_points(m, contset=m.t, var=m.v3, ncp=1) with self.assertRaises(IndexError): disc.reduce_collocation_points(m, contset=m.t, var=m.v4, ncp=1) # Calling reduce_collocation_points more than once disc.reduce_collocation_points(m, contset=m.t, var=m.u, ncp=1) with self.assertRaises(RuntimeError): disc.reduce_collocation_points(m, contset=m.t, var=m.u, ncp=1)
def build(number_of_stages=2): # ---building model--- m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = props.NaClParameterBlock() m.fs.costing = WaterTAPCosting() m.fs.NumberOfStages = Param(initialize=number_of_stages) m.fs.StageSet = RangeSet(m.fs.NumberOfStages) m.fs.LSRRO_StageSet = RangeSet(2, m.fs.NumberOfStages) m.fs.NonFinal_StageSet = RangeSet(m.fs.NumberOfStages-1) m.fs.feed = Feed(default={'property_package': m.fs.properties}) m.fs.product = Product(default={'property_package': m.fs.properties}) m.fs.disposal = Product(default={'property_package': m.fs.properties}) # Add the mixers m.fs.Mixers = Mixer(m.fs.NonFinal_StageSet, default={ "property_package": m.fs.properties, "momentum_mixing_type": MomentumMixingType.equality, # booster pump will match pressure "inlet_list": ['upstream', 'downstream']}) total_pump_work = 0 # Add the pumps m.fs.PrimaryPumps = Pump(m.fs.StageSet, default={"property_package": m.fs.properties}) for pump in m.fs.PrimaryPumps.values(): pump.costing = UnitModelCostingBlock(default={ "flowsheet_costing_block":m.fs.costing}) m.fs.costing.cost_flow(pyunits.convert(pump.work_mechanical[0], to_units=pyunits.kW), "electricity") # Add the equalizer pumps m.fs.BoosterPumps = Pump(m.fs.LSRRO_StageSet, default={"property_package": m.fs.properties}) for pump in m.fs.BoosterPumps.values(): pump.costing = UnitModelCostingBlock(default={ "flowsheet_costing_block":m.fs.costing}) m.fs.costing.cost_flow(pyunits.convert(pump.work_mechanical[0], to_units=pyunits.kW), "electricity") # Add the stages ROs m.fs.ROUnits = ReverseOsmosis0D(m.fs.StageSet, default={ "property_package": m.fs.properties, "has_pressure_change": True, "pressure_change_type": PressureChangeType.calculated, "mass_transfer_coefficient": MassTransferCoefficient.calculated, "concentration_polarization_type": ConcentrationPolarizationType.calculated}) for ro_unit in m.fs.ROUnits.values(): ro_unit.costing = UnitModelCostingBlock(default={ "flowsheet_costing_block":m.fs.costing}) # Add EnergyRecoveryDevice m.fs.EnergyRecoveryDevice = Pump(default={"property_package": m.fs.properties}) m.fs.EnergyRecoveryDevice.costing = UnitModelCostingBlock(default={ "flowsheet_costing_block":m.fs.costing, "costing_method_arguments":{"pump_type":PumpType.energy_recovery_device}}) m.fs.costing.cost_flow(pyunits.convert(m.fs.EnergyRecoveryDevice.work_mechanical[0], to_units=pyunits.kW), "electricity") # additional variables or expressions # system water recovery m.fs.water_recovery = Var( initialize=0.5, bounds=(0, 1), domain=NonNegativeReals, units=pyunits.dimensionless, doc='System Water Recovery') m.fs.eq_water_recovery = Constraint(expr=\ sum(m.fs.feed.flow_mass_phase_comp[0,'Liq',:]) * m.fs.water_recovery == \ sum(m.fs.product.flow_mass_phase_comp[0,'Liq',:]) ) # costing m.fs.costing.cost_process() product_flow_vol_total = m.fs.product.properties[0].flow_vol m.fs.costing.add_LCOW(product_flow_vol_total) m.fs.costing.add_specific_energy_consumption(product_flow_vol_total) # objective m.fs.objective = Objective(expr=m.fs.costing.LCOW) # connections # Connect the feed to the first pump m.fs.feed_to_pump = Arc(source=m.fs.feed.outlet, destination=m.fs.PrimaryPumps[1].inlet) # Connect the primary RO permeate to the product m.fs.primary_RO_to_product = Arc(source=m.fs.ROUnits[1].permeate, destination=m.fs.product.inlet) # Connect the Pump n to the Mixer n m.fs.pump_to_mixer = Arc(m.fs.NonFinal_StageSet, rule=lambda fs,n : {'source':fs.PrimaryPumps[n].outlet, 'destination':fs.Mixers[n].upstream}) # Connect the Mixer n to the Stage n m.fs.mixer_to_stage = Arc(m.fs.NonFinal_StageSet, rule=lambda fs,n : {'source':fs.Mixers[n].outlet, 'destination':fs.ROUnits[n].inlet}) # Connect the Stage n to the Pump n+1 m.fs.stage_to_pump = Arc(m.fs.NonFinal_StageSet, rule=lambda fs,n : {'source':fs.ROUnits[n].retentate, 'destination':fs.PrimaryPumps[n+1].inlet}) # Connect the Stage n to the Eq Pump n m.fs.stage_to_eq_pump = Arc(m.fs.LSRRO_StageSet, rule=lambda fs,n : {'source':fs.ROUnits[n].permeate, 'destination':fs.BoosterPumps[n].inlet}) # Connect the Eq Pump n to the Mixer n-1 m.fs.eq_pump_to_mixer = Arc(m.fs.LSRRO_StageSet, rule=lambda fs,n : {'source':fs.BoosterPumps[n].outlet, 'destination':fs.Mixers[n-1].downstream}) # Connect the Pump N to the Stage N last_stage = m.fs.StageSet.last() m.fs.pump_to_stage = Arc(source=m.fs.PrimaryPumps[last_stage].outlet, destination=m.fs.ROUnits[last_stage].inlet) # Connect Final Stage to EnergyRecoveryDevice Pump m.fs.stage_to_erd = Arc(source=m.fs.ROUnits[last_stage].retentate, destination=m.fs.EnergyRecoveryDevice.inlet) # Connect the EnergyRecoveryDevice to the disposal m.fs.erd_to_disposal = Arc(source=m.fs.EnergyRecoveryDevice.outlet, destination=m.fs.disposal.inlet) # additional bounding for b in m.component_data_objects(Block, descend_into=True): # NaCl solubility limit if hasattr(b, 'mass_frac_phase_comp'): b.mass_frac_phase_comp['Liq', 'NaCl'].setub(0.26) TransformationFactory("network.expand_arcs").apply_to(m) return m
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, 'time_units': pyunits.minute }) 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 check_optimal_termination(results)
def test_ConstraintDatatarget_target_transformed(self): m = self.makeModel() TransformationFactory('core.add_slack_variables').apply_to( m, targets=[m.rule1[2]]) self.checkTransformedRule1(m, 2)
def test_indexedtarget_nontarget_same_create_using(self): m = self.makeModel() m2 = TransformationFactory('core.add_slack_variables').create_using( m, targets=[m.rule1]) self.checkRule2(m2)
def test_nontarget_constraint_same_create_using(self): m = self.makeModel() m2 = TransformationFactory('core.add_slack_variables').create_using( m, targets=[m.rule1, m.rule3]) self.checkNonTargetCons(m2)
def column_model_dyn(self, request): """ Setup for dynamic column""" Fpar = request.param # Spacial domain finite elemets and finite element list x_nfe = 10 x_nfe_list = [i / x_nfe for i in range(x_nfe + 1)] # Time horizon t_nfe = 2 time_set = [0, 4] m = ConcreteModel() m.fs = FlowsheetBlock(default={ "dynamic": True, 'time_units': pyunits.s, "time_set": time_set }) # Set up property package m.fs.vapor_properties = VaporParameterBlock( default={'process_type': Fpar}) m.fs.liquid_properties = LiquidParameterBlock( default={'process_type': Fpar}) if Fpar == ProcessType.absorber: col_pressure = 107650 elif Fpar == ProcessType.stripper: col_pressure = 183430 # Create instance of column on flowsheet m.fs.unit = PackedColumn( default={ "process_type": Fpar, "finite_elements": x_nfe, "length_domain_set": x_nfe_list, "column_pressure": col_pressure, "transformation_method": "dae.finite_difference", "vapor_side": { "transformation_scheme": "BACKWARD", "property_package": m.fs.vapor_properties, "has_pressure_change": False, "pressure_drop_type": None }, "liquid_side": { "transformation_scheme": "FORWARD", "property_package": m.fs.liquid_properties } }) # Time discretization discretizer = TransformationFactory('dae.finite_difference') discretizer.apply_to(m.fs, wrt=m.fs.time, nfe=t_nfe, scheme='BACKWARD') # Fix inputs variables m.fs.unit.diameter_column.fix(0.64135) if Fpar == ProcessType.absorber: m.fs.unit.length_column.fix(18.15) # Rich loading at the bottom of column @ final time m.fs.unit.loading = Param(initialize=0.4927155969073804) for t in m.fs.time: # Vapor m.fs.unit.vapor_inlet.flow_mol[t].fix(21.48) m.fs.unit.vapor_inlet.temperature[t].fix(317.88) m.fs.unit.vapor_inlet.pressure[t].fix(col_pressure) m.fs.unit.vapor_inlet.mole_frac_comp[t, "CO2"].fix(0.11453) m.fs.unit.vapor_inlet.mole_frac_comp[t, "H2O"].fix(0.08526) m.fs.unit.vapor_inlet.mole_frac_comp[t, "N2"].fix(0.73821) m.fs.unit.vapor_inlet.mole_frac_comp[t, "O2"].fix(0.06200) # Liquid m.fs.unit.liquid_inlet.flow_mol[t].fix(37.55) m.fs.unit.liquid_inlet.temperature[t].fix(319.87) m.fs.unit.liquid_inlet.mole_frac_comp[t, "CO2"].fix(0.00963) m.fs.unit.liquid_inlet.mole_frac_comp[t, "H2O"].fix(0.87435) m.fs.unit.liquid_inlet.mole_frac_comp[t, "MEA"].fix(0.11602) # Initialize column m.fs.unit.initialize() elif Fpar == ProcessType.stripper: m.fs.unit.length_column.fix(12.1) # Lean loading at the bottom of column @ final time m.fs.unit.loading = Param(initialize=0.17982818165156983) for t in m.fs.time: # Vapor m.fs.unit.vapor_inlet.flow_mol[t].fix(17.496) m.fs.unit.vapor_inlet.temperature[t].fix(396.6) m.fs.unit.vapor_inlet.pressure[t].fix(col_pressure) m.fs.unit.vapor_inlet.mole_frac_comp[t, "CO2"].fix(0.0145) m.fs.unit.vapor_inlet.mole_frac_comp[t, "H2O"].fix(0.9855) # Liquid m.fs.unit.liquid_inlet.flow_mol[t].fix(84.48) m.fs.unit.liquid_inlet.temperature[t].fix(382.15) m.fs.unit.liquid_inlet.mole_frac_comp[t, "CO2"].fix(0.0331) m.fs.unit.liquid_inlet.mole_frac_comp[t, "H2O"].fix(0.8547) m.fs.unit.liquid_inlet.mole_frac_comp[t, "MEA"].fix(0.1122) # Initialize column m.fs.unit.initialize(homotopy_steps_h=[ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1 ]) return m
def test_dynamic_initialization(self): # Spacial domain finite elemets and finite element list x_nfe = 10 x_nfe_list = [i / x_nfe for i in range(x_nfe + 1)] # Time horizon t_nfe = 2 time_set = [0, 4] m = ConcreteModel() m.fs = FlowsheetBlock(default={ "dynamic": True, 'time_units': pyunits.s, "time_set": time_set }) # Set up property package m.fs.vapor_properties = VaporParameterBlock() m.fs.liquid_properties = LiquidParameterBlock() # Create instance of column on flowsheet m.fs.unit = PackedColumn( default={ "finite_elements": x_nfe, "length_domain_set": x_nfe_list, "transformation_method": "dae.finite_difference", "vapor_side": { "transformation_scheme": "BACKWARD", "property_package": m.fs.vapor_properties, "has_pressure_change": False, "pressure_drop_type": None }, "liquid_side": { "transformation_scheme": "FORWARD", "property_package": m.fs.liquid_properties } }) # Time discretization discretizer = TransformationFactory('dae.finite_difference') discretizer.apply_to(m.fs, wrt=m.fs.time, nfe=t_nfe, scheme='BACKWARD') # Fix input variables m.fs.unit.diameter_column.fix(0.64135) m.fs.unit.length_column.fix(18.15) for t in m.fs.time: # Vapor m.fs.unit.vapor_inlet.flow_mol[t].fix(21.48) m.fs.unit.vapor_inlet.temperature[t].fix(317.88) m.fs.unit.vapor_inlet.pressure[t].fix(107650) m.fs.unit.vapor_inlet.mole_frac_comp[t, "CO2"].fix(0.11453) m.fs.unit.vapor_inlet.mole_frac_comp[t, "H2O"].fix(0.08526) m.fs.unit.vapor_inlet.mole_frac_comp[t, "N2"].fix(0.73821) m.fs.unit.vapor_inlet.mole_frac_comp[t, "O2"].fix(0.06200) # Liquid m.fs.unit.liquid_inlet.flow_mol[t].fix(37.55) m.fs.unit.liquid_inlet.temperature[t].fix(319.87) m.fs.unit.liquid_inlet.mole_frac_comp[t, "CO2"].fix(0.00963) m.fs.unit.liquid_inlet.mole_frac_comp[t, "H2O"].fix(0.87435) m.fs.unit.liquid_inlet.mole_frac_comp[t, "MEA"].fix(0.11602) initialization_tester(m)
def test_obj_deactivated(self): m = self.makeModel() TransformationFactory('core.add_slack_variables').apply_to(m) # should have old objective deactivated. self.assertFalse(m.obj.active)
def test_nothing_to_do(self): m = ConcreteModel() m.p = LogicalConstraint() TransformationFactory('core.logical_to_linear').apply_to(m) self.assertIsNone(m.component('logic_to_linear'))
def test_nontarget_constraint_same(self): m = self.makeModel() TransformationFactory('core.add_slack_variables').apply_to( m, targets=[m.rule1, m.rule3]) self.checkNonTargetCons(m)
def test_xfrm_special_atoms_nonroot(self): m = ConcreteModel() m.s = RangeSet(3) m.Y = BooleanVar(m.s) m.p = LogicalConstraint( expr=m.Y[1].implies(atleast(2, m.Y[1], m.Y[2], m.Y[3]))) TransformationFactory('core.logical_to_linear').apply_to(m) Y_aug = m.logic_to_linear.augmented_vars self.assertEqual(len(Y_aug), 1) self.assertEqual(Y_aug[1].domain, BooleanSet) _constrs_contained_within( self, [(None, sum(m.Y[:].get_associated_binary()) - (1 + 2 * Y_aug[1].get_associated_binary()), 0), (1, (1 - m.Y[1].get_associated_binary()) + Y_aug[1].get_associated_binary(), None), (None, 2 - 2 * (1 - Y_aug[1].get_associated_binary()) - sum(m.Y[:].get_associated_binary()), 0)], m.logic_to_linear.transformed_constraints) m = ConcreteModel() m.s = RangeSet(3) m.Y = BooleanVar(m.s) m.p = LogicalConstraint( expr=m.Y[1].implies(atmost(2, m.Y[1], m.Y[2], m.Y[3]))) TransformationFactory('core.logical_to_linear').apply_to(m) Y_aug = m.logic_to_linear.augmented_vars self.assertEqual(len(Y_aug), 1) self.assertEqual(Y_aug[1].domain, BooleanSet) _constrs_contained_within( self, [(None, sum(m.Y[:].get_associated_binary()) - (1 - Y_aug[1].get_associated_binary() + 2), 0), (1, (1 - m.Y[1].get_associated_binary()) + Y_aug[1].get_associated_binary(), None), (None, 3 - 3 * Y_aug[1].get_associated_binary() - sum(m.Y[:].get_associated_binary()), 0)], m.logic_to_linear.transformed_constraints) m = ConcreteModel() m.s = RangeSet(3) m.Y = BooleanVar(m.s) m.p = LogicalConstraint( expr=m.Y[1].implies(exactly(2, m.Y[1], m.Y[2], m.Y[3]))) TransformationFactory('core.logical_to_linear').apply_to(m) Y_aug = m.logic_to_linear.augmented_vars self.assertEqual(len(Y_aug), 3) self.assertEqual(Y_aug[1].domain, BooleanSet) _constrs_contained_within(self, [ (1, (1 - m.Y[1].get_associated_binary()) + Y_aug[1].get_associated_binary(), None), (None, sum(m.Y[:].get_associated_binary()) - (1 - Y_aug[1].get_associated_binary() + 2), 0), (None, 2 - 2 * (1 - Y_aug[1].get_associated_binary()) - sum(m.Y[:].get_associated_binary()), 0), (1, sum(Y_aug[:].get_associated_binary()), None), (None, sum(m.Y[:].get_associated_binary()) - (1 + 2 * (1 - Y_aug[2].get_associated_binary())), 0), (None, 3 - 3 * (1 - Y_aug[3].get_associated_binary()) - sum(m.Y[:].get_associated_binary()), 0), ], m.logic_to_linear.transformed_constraints) # Note: x is now a variable m = ConcreteModel() m.s = RangeSet(3) m.Y = BooleanVar(m.s) m.x = Var(bounds=(1, 3)) m.p = LogicalConstraint( expr=m.Y[1].implies(exactly(m.x, m.Y[1], m.Y[2], m.Y[3]))) TransformationFactory('core.logical_to_linear').apply_to(m) Y_aug = m.logic_to_linear.augmented_vars self.assertEqual(len(Y_aug), 3) self.assertEqual(Y_aug[1].domain, BooleanSet) _constrs_contained_within(self, [ (1, (1 - m.Y[1].get_associated_binary()) + Y_aug[1].get_associated_binary(), None), (None, sum(m.Y[:].get_associated_binary()) - (m.x + 2 * (1 - Y_aug[1].get_associated_binary())), 0), (None, m.x - 3 * (1 - Y_aug[1].get_associated_binary()) - sum(m.Y[:].get_associated_binary()), 0), (1, sum(Y_aug[:].get_associated_binary()), None), (None, sum(m.Y[:].get_associated_binary()) - (m.x - 1 + 3 * (1 - Y_aug[2].get_associated_binary())), 0), (None, m.x + 1 - 4 * (1 - Y_aug[3].get_associated_binary()) - sum(m.Y[:].get_associated_binary()), 0), ], m.logic_to_linear.transformed_constraints)
def test_indexedtarget_nontarget_same(self): m = self.makeModel() TransformationFactory('core.add_slack_variables').apply_to( m, targets=[m.rule1]) self.checkRule2(m)
def build(self): super().build() config = self.config # sorter ref to config for less line splitting # All feedwater heaters have a condensing section _set_prop_pack(config.condense, config) self.condense = FWHCondensing0D(default=config.condense) # Add a mixer to add the drain stream from another feedwater heater if config.has_drain_mixer: mix_cfg = { # general unit model config "dynamic": config.dynamic, "has_holdup": config.has_holdup, "property_package": config.property_package, "property_package_args": config.property_package_args, "momentum_mixing_type": MomentumMixingType.none, "material_balance_type": MaterialBalanceType.componentTotal, "inlet_list": ["steam", "drain"], } self.drain_mix = Mixer(default=mix_cfg) @self.drain_mix.Constraint(self.drain_mix.flowsheet().config.time) def mixer_pressure_constraint(b, t): """ Constraint to set the drain mixer pressure to the pressure of the steam extracted from the turbine. The drain inlet should always be a higher pressure than the steam inlet. """ return b.steam_state[t].pressure == b.mixed_state[t].pressure # Connect the mixer to the condensing section inlet self.mix_out_arc = Arc(source=self.drain_mix.outlet, destination=self.condense.inlet_1) # Add a desuperheat section before the condensing section if config.has_desuperheat: _set_prop_pack(config.desuperheat, config) self.desuperheat = HeatExchanger(default=config.desuperheat) # set default area less than condensing section area, this will # almost always be overridden by the user fixing an area later self.desuperheat.area.value = 10 if config.has_drain_mixer: self.desuperheat_drain_arc = Arc( source=self.desuperheat.outlet_1, destination=self.drain_mix.steam) else: self.desuperheat_drain_arc = Arc( source=self.desuperheat.outlet_1, destination=self.condense.inlet_1) self.condense_out2_arc = Arc(source=self.condense.outlet_2, destination=self.desuperheat.inlet_2) # Add a drain cooling section after the condensing section if config.has_drain_cooling: _set_prop_pack(config.cooling, config) self.cooling = HeatExchanger(default=config.cooling) # set default area less than condensing section area, this will # almost always be overridden by the user fixing an area later self.cooling.area.value = 10 self.cooling_out2_arc = Arc(source=self.cooling.outlet_2, destination=self.condense.inlet_2) self.condense_out1_arc = Arc(source=self.condense.outlet_1, destination=self.cooling.inlet_1) TransformationFactory("network.expand_arcs").apply_to(self)
def test_trans_block_name_collision(self): m = self.makeModel() m._core_add_slack_variables = Block() TransformationFactory('core.add_slack_variables').apply_to(m) xblock = m.component("_core_add_slack_variables_4") self.assertIsInstance(xblock, Block)
def test_unallowable_type(self): m = ConcreteModel() m.c = Constraint() with self.assertRaises(GDP_Error): TransformationFactory('gdp.fix_disjuncts').apply_to(m.c)
def test_ConstraintDatatarget_target_transformed_create_using(self): m = self.makeModel() m2 = TransformationFactory('core.add_slack_variables').create_using( m, targets=[m.rule1[2]]) self.checkTransformedRule1(m2, 2)
def test_inactive_target(self): m = ConcreteModel() m.b = Block() m.b.deactivate() TransformationFactory('gdp.fix_disjuncts').apply_to(m.b)
m.use4implies6or7 = LogicalConstraint( expr=m.Y[4].implies(lor(m.Y[6], m.Y[7]))) m.use3implies8 = LogicalConstraint(expr=m.Y[3].implies(m.Y[8])) m.use6or7implies4 = LogicalConstraint( expr=lor(m.Y[6], m.Y[7]).implies(m.Y[4])) m.use6or7 = LogicalConstraint(expr=m.Y[6].xor(m.Y[7])) """Profit (objective) function definition""" m.profit = Objective(expr=sum(m.yCF[unit] for unit in m.units) + sum(m.flow[stream] * CV[stream] for stream in m.streams) + CONSTANT, sense=minimize) """Bound definitions""" # x (flow) upper bounds x_ubs = {3: 2, 5: 2, 9: 2, 10: 1, 14: 1, 17: 2, 19: 2, 21: 2, 25: 3} for i, x_ub in x_ubs.item(): m.flow[i].setub(x_ub) # Optimal solution uses units 2, 4, 6, 8 with objective value 68. return m if __name__ == "__main__": m = build_eight_process_flowsheet() from pyomo.environ import TransformationFactory TransformationFactory('core.logical_to_linear').apply_to(m) SolverFactory('gdpopt').solve(m, tee=True) update_boolean_vars_from_binary(m) m.Y.display() m.flow.display()
def test_indexed_target(self): m = ConcreteModel() m.s = RangeSet(2) m.b = Block(m.s) m.b[1].bb = Block() TransformationFactory('gdp.fix_disjuncts').apply_to(m.b)
def main(): """ Make the flowsheet object, fix some variables, and solve the problem """ # Create a Concrete Model as the top level object m = ConcreteModel() # Add a flowsheet object to the model m.fs = FlowsheetBlock(default={"dynamic": False}) # Add property packages to flowsheet library m.fs.thermo_params = thermo_props.SaponificationParameterBlock() m.fs.reaction_params = reaction_props.SaponificationReactionParameterBlock( default={"property_package": m.fs.thermo_params}) # Create unit models m.fs.Tank1 = CSTR( default={ "property_package": m.fs.thermo_params, "reaction_package": m.fs.reaction_params, "has_equilibrium_reactions": False, "has_heat_of_reaction": True, "has_heat_transfer": True, "has_pressure_change": False }) m.fs.Tank2 = CSTR( default={ "property_package": m.fs.thermo_params, "reaction_package": m.fs.reaction_params, "has_equilibrium_reactions": False, "has_heat_of_reaction": True, "has_heat_transfer": True, "has_pressure_change": False }) # Make Streams to connect units m.fs.stream = Arc(source=m.fs.Tank1.outlet, destination=m.fs.Tank2.inlet) TransformationFactory("network.expand_arcs").apply_to(m) # Set inlet and operating conditions, and some initial conditions. m.fs.Tank1.inlet.flow_vol[0].fix(1.0) m.fs.Tank1.inlet.conc_mol_comp[0, "H2O"].fix(55388.0) m.fs.Tank1.inlet.conc_mol_comp[0, "NaOH"].fix(100.0) m.fs.Tank1.inlet.conc_mol_comp[0, "EthylAcetate"].fix(100.0) m.fs.Tank1.inlet.conc_mol_comp[0, "SodiumAcetate"].fix(0.0) m.fs.Tank1.inlet.conc_mol_comp[0, "Ethanol"].fix(0.0) m.fs.Tank1.inlet.temperature.fix(303.15) m.fs.Tank1.inlet.pressure.fix(101325.0) m.fs.Tank1.volume.fix(1.0) m.fs.Tank1.heat_duty.fix(0.0) m.fs.Tank2.volume.fix(1.0) m.fs.Tank2.heat_duty.fix(0.0) # Initialize Units m.fs.Tank1.initialize() m.fs.Tank2.initialize( state_args={ "flow_vol": 1.0, "conc_mol_comp": { "H2O": 55388.0, "NaOH": 100.0, "EthylAcetate": 100.0, "SodiumAcetate": 0.0, "Ethanol": 0.0 }, "temperature": 303.15, "pressure": 101325.0 }) # Create a solver solver = SolverFactory('ipopt') results = solver.solve(m, tee=False) # Print results print(results) print() print("Results") print() print("Tank 1 Outlet") m.fs.Tank1.outlet.display() print() print("Tank 2 Outlet") m.fs.Tank2.outlet.display() # For testing purposes return (m, results)
def test_reduce_colloc_multi_index(self): m = self.m.clone() m.u = Var(m.t, m.s) m2 = m.clone() m3 = m.clone() disc = TransformationFactory('dae.collocation') disc.apply_to(m, nfe=5, ncp=3) disc.reduce_collocation_points(m, contset=m.t, var=m.u, ncp=1) self.assertTrue(hasattr(m, 'u_interpolation_constraints')) self.assertEqual(len(m.u_interpolation_constraints), 30) disc2 = TransformationFactory('dae.collocation') disc2.apply_to(m2, wrt=m2.t, nfe=5, ncp=3) disc2.reduce_collocation_points(m2, contset=m2.t, var=m2.u, ncp=3) self.assertFalse(hasattr(m2, 'u_interpolation_constraints')) disc3 = TransformationFactory('dae.collocation') disc3.apply_to(m3, wrt=m3.t, nfe=5, ncp=3) disc3.reduce_collocation_points(m3, contset=m3.t, var=m3.u, ncp=2) self.assertTrue(hasattr(m3, 'u_interpolation_constraints')) self.assertEqual(len(m3.u_interpolation_constraints), 15)