Skip to content

solve_strongly_connected_components should take scaling into account #3785

@dallan-keylogic

Description

@dallan-keylogic

Summary

The function solve_strongly_connected_components should behave like other Pyomo solvers and have an option to take variable and constraint scaling factors into account when solving a block. To do this, calculate_variable_from_constraint should have an option to use the scaled constraint residual when checking the termination condition. Additionally, the temporary blocks generated to solve subsystems with multiple variables and constraints should have the scaling factors for those variables and constraints copied over.

Rationale

In IDAES, we now have the writer configuration setting scale_model=True as a default option. As a result, I've been going through and updating various parts of the model_statistics and model_diagnostics functions to use the scaled model---the scaled model is what the solver sees, so the scaled model should be used for troubleshooting. That means using scaled values of variables for detecting variables "near bounds", scaled values of constraints when detecting constraints "with large residuals", and the scaled Jacobian matrix for diagnostics that utilize it.

As a part of this process, I updated the large_residuals_set function to use scaled values of constraint residuals. However, in addition to being used in model diagnostics, that function is also used as part of the postchecks for the initialization API. If we solve a block with IPOPT or another external solver, the constraints are guaranteed to be satisfied only to within the scaled tolerance, so using scaled values when checking for large residuals is necessary. However, if we initialize the block using the BlockTriangularizationInitializer, constraints are not satisfied to within the scaled tolerance.

Description

For 1x1 blocks, solve_strongly_connected_components uses calculate_variable_from_constraint, which does not take scaling into account. Because calculate_variable_from_constraint uses Newton's method, scaling does not affect the steps taken in the solution process. However, scaling should be taken into account when checking whether the constraint residual is small enough to stop iterating. Accordingly, an option should be added to use the scaled residual in checking the termination condition.

For the n x n blocks, solve_strongly_connected_components creates a temporary block to solve each strongly connected subsystem. However, the .nl writer does use variable or constraint scaling factors when passing the system to the solver. If I use the suffix finder on the elements of these temporary blocks, it can still find the scaling factors on the original model, but apparently the .nl writer doesn't bother searching for scaling factors if the block being solved doesn't have the scaling_factor suffix on it. One way or another, there should be an option to allow variable and constraint scaling to be used on these temporary blocks. Either solve_strongly_connected_components can add the scaling factors into a suffix on the temporary block manually or either the temporary block interface or .nl writer needs to be updated.

As a short-term solution, we can have the BlockTriangularizationInitializer do a solve of the entire block after calling solve_strongly_connected_components. It isn't ideal because it slows down the initialization process, but it will work until solve_strongly_connected_components or the functions it uses can be updated.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions