Ejemplo n.º 1
0
    def test_perfect_matching(self):
        model = make_gas_expansion_model()

        # These are the variables and constraints of the square,
        # nonsingular subsystem
        variables = []
        variables.extend(model.P.values())
        variables.extend(model.T[i] for i in model.streams
                         if i != model.streams.first())
        variables.extend(model.rho[i] for i in model.streams
                         if i != model.streams.first())
        variables.extend(model.F[i] for i in model.streams
                         if i != model.streams.first())

        constraints = list(model.component_data_objects(pyo.Constraint))

        imat = get_numeric_incidence_matrix(variables, constraints)
        con_idx_map = ComponentMap((c, i) for i, c in enumerate(constraints))

        n_var = len(variables)
        matching = maximum_matching(imat)
        matching = ComponentMap(
            (c, variables[matching[con_idx_map[c]]]) for c in constraints)
        values = ComponentSet(matching.values())
        self.assertEqual(len(matching), n_var)
        self.assertEqual(len(values), n_var)

        # The subset of variables and equations we have identified
        # do not have a unique perfect matching. But we at least know
        # this much.
        self.assertIs(matching[model.ideal_gas[0]], model.P[0])
Ejemplo n.º 2
0
    def test_imperfect_matching(self):
        model = make_gas_expansion_model()
        all_vars = list(model.component_data_objects(pyo.Var))
        all_cons = list(model.component_data_objects(pyo.Constraint))
        imat = get_numeric_incidence_matrix(all_vars, all_cons)

        n_eqn = len(all_cons)
        matching = maximum_matching(imat)
        values = set(matching.values())
        self.assertEqual(len(matching), n_eqn)
        self.assertEqual(len(values), n_eqn)
Ejemplo n.º 3
0
    def test_triangularize(self):
        N = 5
        model = make_gas_expansion_model(N)

        # These are the variables and constraints of the square,
        # nonsingular subsystem
        variables = []
        variables.extend(model.P.values())
        variables.extend(model.T[i] for i in model.streams
                         if i != model.streams.first())
        variables.extend(model.rho[i] for i in model.streams
                         if i != model.streams.first())
        variables.extend(model.F[i] for i in model.streams
                         if i != model.streams.first())

        constraints = list(model.component_data_objects(pyo.Constraint))

        imat = get_numeric_incidence_matrix(variables, constraints)
        con_idx_map = ComponentMap((c, i) for i, c in enumerate(constraints))
        var_idx_map = ComponentMap((v, i) for i, v in enumerate(variables))

        row_block_map, col_block_map = block_triangularize(imat)
        var_block_map = ComponentMap(
            (v, col_block_map[var_idx_map[v]]) for v in variables)
        con_block_map = ComponentMap(
            (c, row_block_map[con_idx_map[c]]) for c in constraints)

        var_values = set(var_block_map.values())
        con_values = set(con_block_map.values())
        self.assertEqual(len(var_values), N + 1)
        self.assertEqual(len(con_values), N + 1)

        self.assertEqual(var_block_map[model.P[0]], 0)

        for i in model.streams:
            if i != model.streams.first():
                self.assertEqual(var_block_map[model.rho[i]], i)
                self.assertEqual(var_block_map[model.T[i]], i)
                self.assertEqual(var_block_map[model.P[i]], i)
                self.assertEqual(var_block_map[model.F[i]], i)

                self.assertEqual(con_block_map[model.ideal_gas[i]], i)
                self.assertEqual(con_block_map[model.expansion[i]], i)
                self.assertEqual(con_block_map[model.mbal[i]], i)
                self.assertEqual(con_block_map[model.ebal[i]], i)
Ejemplo n.º 4
0
    def test_incidence_matrix(self):
        N = 5
        model = make_gas_expansion_model(N)
        all_vars = list(model.component_data_objects(pyo.Var))
        all_cons = list(model.component_data_objects(pyo.Constraint))
        imat = get_numeric_incidence_matrix(all_vars, all_cons)
        n_var = 4 * (N + 1)
        n_con = 4 * N + 1
        self.assertEqual(imat.shape, (n_con, n_var))

        var_idx_map = ComponentMap((v, i) for i, v in enumerate(all_vars))
        con_idx_map = ComponentMap((c, i) for i, c in enumerate(all_cons))

        # Map constraints to the variables they contain.
        csr_map = ComponentMap()
        csr_map.update((model.mbal[i],
                        ComponentSet([
                            model.F[i],
                            model.F[i - 1],
                            model.rho[i],
                            model.rho[i - 1],
                        ])) for i in model.streams
                       if i != model.streams.first())
        csr_map.update((model.ebal[i],
                        ComponentSet([
                            model.F[i],
                            model.F[i - 1],
                            model.rho[i],
                            model.rho[i - 1],
                            model.T[i],
                            model.T[i - 1],
                        ])) for i in model.streams
                       if i != model.streams.first())
        csr_map.update((model.expansion[i],
                        ComponentSet([
                            model.rho[i],
                            model.rho[i - 1],
                            model.P[i],
                            model.P[i - 1],
                        ])) for i in model.streams
                       if i != model.streams.first())
        csr_map.update((model.ideal_gas[i],
                        ComponentSet([
                            model.P[i],
                            model.rho[i],
                            model.T[i],
                        ])) for i in model.streams)

        # Map constraint and variable indices to the values of the derivatives
        # Note that the derivative values calculated here depend on the model's
        # canonical form.
        deriv_lookup = {}
        m = model  # for convenience
        for s in model.streams:
            # Ideal gas:
            i = con_idx_map[model.ideal_gas[s]]
            j = var_idx_map[model.P[s]]
            deriv_lookup[i, j] = 1.0

            j = var_idx_map[model.rho[s]]
            deriv_lookup[i, j] = -model.R.value * model.T[s].value

            j = var_idx_map[model.T[s]]
            deriv_lookup[i, j] = -model.R.value * model.rho[s].value

            if s != model.streams.first():
                # Expansion:
                i = con_idx_map[model.expansion[s]]
                j = var_idx_map[model.P[s]]
                deriv_lookup[i, j] = 1 / model.P[s - 1].value

                j = var_idx_map[model.P[s - 1]]
                deriv_lookup[i, j] = -model.P[s].value / model.P[s - 1]**2

                j = var_idx_map[model.rho[s]]
                deriv_lookup[i, j] = pyo.value(
                    -m.gamma * (m.rho[s] / m.rho[s - 1])**(m.gamma - 1) /
                    m.rho[s - 1])

                j = var_idx_map[model.rho[s - 1]]
                deriv_lookup[i, j] = pyo.value(
                    -m.gamma * (m.rho[s] / m.rho[s - 1])**(m.gamma - 1) *
                    (-m.rho[s] / m.rho[s - 1]**2))

                # Energy balance:
                i = con_idx_map[m.ebal[s]]
                j = var_idx_map[m.rho[s - 1]]
                deriv_lookup[i, j] = pyo.value(m.F[s - 1] * m.T[s - 1])

                j = var_idx_map[m.F[s - 1]]
                deriv_lookup[i, j] = pyo.value(m.rho[s - 1] * m.T[s - 1])

                j = var_idx_map[m.T[s - 1]]
                deriv_lookup[i, j] = pyo.value(m.F[s - 1] * m.rho[s - 1])

                j = var_idx_map[m.rho[s]]
                deriv_lookup[i, j] = pyo.value(-m.F[s] * m.T[s])

                j = var_idx_map[m.F[s]]
                deriv_lookup[i, j] = pyo.value(-m.rho[s] * m.T[s])

                j = var_idx_map[m.T[s]]
                deriv_lookup[i, j] = pyo.value(-m.F[s] * m.rho[s])

                # Mass balance:
                i = con_idx_map[m.mbal[s]]
                j = var_idx_map[m.rho[s - 1]]
                deriv_lookup[i, j] = pyo.value(m.F[s - 1])

                j = var_idx_map[m.F[s - 1]]
                deriv_lookup[i, j] = pyo.value(m.rho[s - 1])

                j = var_idx_map[m.rho[s]]
                deriv_lookup[i, j] = pyo.value(-m.F[s])

                j = var_idx_map[m.F[s]]
                deriv_lookup[i, j] = pyo.value(-m.rho[s])

        # Want to test that the columns have the rows we expect.
        i = model.streams.first()
        for i, j, e in zip(imat.row, imat.col, imat.data):
            con = all_cons[i]
            var = all_vars[j]
            self.assertIn(var, csr_map[con])
            csr_map[con].remove(var)
            self.assertAlmostEqual(deriv_lookup[i, j], e, 8)
        # And no additional rows
        for con in csr_map:
            self.assertEqual(len(csr_map[con]), 0)