Esempio n. 1
0
    def test_diagonal_blocks_with_cached_maps(self):
        N = 5
        model = make_gas_expansion_model(N)
        igraph = IncidenceGraphInterface()

        # 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))

        igraph.block_triangularize(variables, constraints)
        var_blocks, con_blocks = igraph.get_diagonal_blocks(
            variables, constraints)
        self.assertIsNot(igraph.row_block_map, None)
        self.assertIsNot(igraph.col_block_map, None)
        self.assertEqual(len(var_blocks), N + 1)
        self.assertEqual(len(con_blocks), N + 1)

        for i, (vars, cons) in enumerate(zip(var_blocks, con_blocks)):
            var_set = ComponentSet(vars)
            con_set = ComponentSet(cons)

            if i == 0:
                pred_var_set = ComponentSet([model.P[0]])
                self.assertEqual(pred_var_set, var_set)
                pred_con_set = ComponentSet([model.ideal_gas[0]])
                self.assertEqual(pred_con_set, con_set)

            else:
                pred_var_set = ComponentSet(
                    [model.rho[i], model.T[i], model.P[i], model.F[i]])
                pred_con_set = ComponentSet([
                    model.ideal_gas[i],
                    model.expansion[i],
                    model.mbal[i],
                    model.ebal[i],
                ])
                self.assertEqual(pred_var_set, var_set)
                self.assertEqual(pred_con_set, con_set)
Esempio n. 2
0
def main():
    horizon = 600.0
    ntfe = 40
    #horizon = 30.0
    #ntfe = 2
    t1 = 0.0
    ch4_cuid = "fs.MB.gas_inlet.mole_frac_comp[*,CH4]"
    co2_cuid = "fs.MB.gas_inlet.mole_frac_comp[*,CO2]"
    h2o_cuid = "fs.MB.gas_inlet.mole_frac_comp[*,H2O]"
    input_dict = {
        ch4_cuid: {
            (t1, horizon): 0.5
        },
        co2_cuid: {
            (t1, horizon): 0.5
        },
        h2o_cuid: {
            (t1, horizon): 0.0
        },
    }

    m, var_cat, con_cat = get_model_for_simulation(horizon, ntfe)
    time = m.fs.time
    load_inputs_into_model(m, time, input_dict)

    solver = pyo.SolverFactory("ipopt")
    solve_kwds = {"tee": True}
    res_list = initialize_by_time_element(m,
                                          time,
                                          solver=solver,
                                          solve_kwds=solve_kwds)
    res = solver.solve(m, **solve_kwds)
    msg = res if type(res) is str else res.solver.termination_condition
    print(horizon, ntfe, msg)

    m._obj = pyo.Objective(expr=0.0)
    nlp = PyomoNLP(m)
    igraph = IncidenceGraphInterface()

    # TODO: I should be able to do categorization in the pre-time-discretized
    # model. This is somewhat nicer as the time points are all independent
    # in that case.
    solid_enth_conds = []
    gas_enth_conds = []
    solid_dens_conds = []
    gas_dens_conds = []
    for t in time:
        var_set = ComponentSet(var[t] for var in var_cat[VC.ALGEBRAIC])
        constraints = [con[t] for con in con_cat[CC.ALGEBRAIC] if t in con]
        variables = [
            var for var in _generate_variables_in_constraints(constraints)
            if var in var_set
        ]

        assert len(variables) == len(constraints)

        alg_jac = nlp.extract_submatrix_jacobian(variables, constraints)
        N, M = alg_jac.shape
        assert N == M
        matching = igraph.maximum_matching(variables, constraints)
        assert len(matching) == N
        try_factorization(alg_jac)

        # Condition number of the entire algebraic Jacobian seems
        # inconsistent, so I don't calculate it.
        #cond = np.linalg.cond(alg_jac.toarray())
        #cond = get_condition_number(alg_jac)

        var_blocks, con_blocks = igraph.get_diagonal_blocks(
            variables, constraints)
        block_matrices = [
            nlp.extract_submatrix_jacobian(vars, cons)
            for vars, cons in zip(var_blocks, con_blocks)
        ]
        gas_enth_blocks = [
            i for i, (vars, cons) in enumerate(zip(var_blocks, con_blocks))
            if any("gas_phase" in var.name and "temperature" in var.name
                   for var in vars)
        ]
        solid_enth_blocks = [
            i for i, (vars, cons) in enumerate(zip(var_blocks, con_blocks))
            if any("solid_phase" in var.name and "temperature" in var.name
                   for var in vars)
        ]
        gas_dens_blocks = [
            i for i, (vars, cons) in enumerate(zip(var_blocks, con_blocks))
            if any("gas_phase" in con.name and "sum_component_eqn" in con.name
                   for con in cons)
        ]
        solid_dens_blocks = [
            i for i, (vars, cons) in enumerate(zip(var_blocks, con_blocks))
            if any(
                "solid_phase" in con.name and "sum_component_eqn" in con.name
                for con in cons)
        ]
        gas_enth_cond = [
            np.linalg.cond(block_matrices[i].toarray())
            for i in gas_enth_blocks
        ]
        solid_enth_cond = [
            np.linalg.cond(block_matrices[i].toarray())
            for i in solid_enth_blocks
        ]
        gas_dens_cond = [
            np.linalg.cond(block_matrices[i].toarray())
            for i in gas_dens_blocks
        ]
        solid_dens_cond = [
            np.linalg.cond(block_matrices[i].toarray())
            for i in solid_dens_blocks
        ]
        max_gas_enth_cond = max(gas_enth_cond)
        max_solid_enth_cond = max(solid_enth_cond)
        max_gas_dens_cond = max(gas_dens_cond)
        max_solid_dens_cond = max(solid_dens_cond)
        gas_enth_conds.append(max_gas_enth_cond)
        solid_enth_conds.append(max_solid_enth_cond)
        gas_dens_conds.append(max_gas_dens_cond)
        solid_dens_conds.append(max_solid_dens_cond)

    # Plot condition numbers over time
    plt.rcParams.update({"font.size": 16})
    fig = plt.figure()
    ax = fig.add_subplot()
    t_list = list(time)
    ax.plot(t_list,
            gas_enth_conds,
            label="Gas enth.",
            linewidth=3,
            linestyle="solid")
    ax.plot(t_list,
            solid_enth_conds,
            label="Solid enth.",
            linewidth=3,
            linestyle="dotted")
    ax.plot(t_list,
            gas_dens_conds,
            label="Gas dens.",
            linewidth=3,
            linestyle="dashed")
    ax.plot(t_list,
            solid_dens_conds,
            label="Solid dens.",
            linewidth=3,
            linestyle="dashdot")
    ax.set_yscale("log")
    ax.set_ylim(bottom=1.0, top=1e7)
    ax.set_xlabel("Time (s)")
    ax.set_ylabel("Condition number")
    fig.legend(loc="center right", bbox_to_anchor=(1.0, 0.65))
    fig.tight_layout()
    fig.show()
    fig.savefig("condition_over_time.png", transparent=True)

    # Generate some structural results with the incidence matrix at a single
    # point in time.
    t = time.at(2)
    var_set = ComponentSet(var[t] for var in var_cat[VC.ALGEBRAIC])
    constraints = [con[t] for con in con_cat[CC.ALGEBRAIC] if t in con]
    variables = [
        var for var in _generate_variables_in_constraints(constraints)
        if var in var_set
    ]
    alg_jac = nlp.extract_submatrix_jacobian(variables, constraints)

    var_blocks, con_blocks = igraph.get_diagonal_blocks(variables, constraints)
    dim = len(constraints)
    n_blocks = len(var_blocks)
    print("Number of variables/constraints: %s" % dim)
    print("Number of diagonal blocks: %s" % n_blocks)
    block_polynomial_degrees = [
        get_polynomial_degree_wrt(cons, vars)
        for cons, vars in zip(con_blocks, var_blocks)
    ]
    nonlinear_blocks = [
        i for i, d in enumerate(block_polynomial_degrees) if d is None or d > 1
    ]
    print("Number of nonlinear blocks: %s" % len(nonlinear_blocks))

    print("\nNonlinear blocks:")
    for i in nonlinear_blocks:
        vars = var_blocks[i]
        cons = con_blocks[i]
        dim = len(vars)
        print("  Block %s, dim = %s" % (i, dim))
        print("    Variables:")
        for var in vars:
            print("      %s" % var.name)
        print("    Constraints:")
        for con in cons:
            print("      %s" % con.name)

    ordered_variables = [var for vars in var_blocks for var in vars]
    ordered_constraints = [con for cons in con_blocks for con in cons]
    ordered_jacobian = nlp.extract_submatrix_jacobian(ordered_variables,
                                                      ordered_constraints)
    plt.rcParams.update({"font.size": 18})
    fig, ax = plot_spy(
        ordered_jacobian,
        markersize=3,
    )
    ax.xaxis.set_tick_params(bottom=False)
    ax.xaxis.set_label_position("top")
    ax.set_xticks([0, 200, 400, 600])
    ax.set_yticks([0, 200, 400, 600])
    ax.set_xlabel("Column (variable) coordinates")
    ax.set_ylabel("Row (equation) coordinates")
    fig.tight_layout()
    fig.savefig("block_triangular_alg_jac.png", transparent=True)
    fig.show()