Debugging the solution process¶
The debugging tutorial covers specification errors on a small model. This tutorial goes one step further: it walks through the solution process of a larger model and shows how to use the solver’s inspection tools when the solve fails.
how the problem reduction, the block decomposition and the starting values of a successful solve can be inspected,
how structural over- and underdetermination is reported and what a structurally singular but count-balanced problem looks like,
how the specifications shape the block decomposition,
how to run the solution process in stages with :code:
presolveand :code:solve_continueandhow to pause the solver at a failed block, inspect the failure and decide whether the starting values or the specification are the problem.
Background information on all steps of the solution process is available in the solver section. The outputs shown here are based on the following version of tespy:
from tespy import __version__
__version__
"0.11.0 - Rankine's Renaissance"
The example model¶
The model is an Organic Rankine Cycle with an internal recuperator, an air cooled condenser and a geothermal heat source, the same plant as in the workflow integration section.
Flowsheet of the recuperated ORC system¶
Flowsheet of the recuperated ORC system¶
The working fluid is isopentane. The evaporation level is fixed through saturated turbine inlet at 150 °C, the condensation level through the air temperatures and the pinch specifications of the condenser.
Note
Since the following sections modify the model repeatedly, the setup lives in a function returning a freshly parametrized network.
from tespy.components import (
CycleCloser, Generator, Motor, MovingBoundaryHeatExchanger,
PowerBus, PowerSink, Pump, Sink, Source, Turbine,
)
from tespy.connections import Connection, PowerConnection
from tespy.networks import Network
def build_orc():
nw = Network(iterinfo=False)
nw.units.set_defaults(
temperature="degC", pressure="bar", pressure_difference="bar",
power="kW", heat="kW"
)
turbine = Turbine("turbine")
recuperator = MovingBoundaryHeatExchanger("recuperator")
condenser = MovingBoundaryHeatExchanger("condenser")
pump = Pump("pump")
preheater = MovingBoundaryHeatExchanger("preheater")
evaporator = MovingBoundaryHeatExchanger("evaporator")
cc = CycleCloser("cc")
heat_source = Source("heat source")
heat_outflow = Sink("heat outflow")
air_source = Source("air source")
air_sink = Sink("air sink")
a1 = Connection(heat_source, "out1", evaporator, "in1", label="a1")
a2 = Connection(evaporator, "out1", preheater, "in1", label="a2")
a3 = Connection(preheater, "out1", heat_outflow, "in1", label="a3")
b1 = Connection(cc, "out1", turbine, "in1", label="b1")
b2 = Connection(turbine, "out1", recuperator, "in1", label="b2")
b3 = Connection(recuperator, "out1", condenser, "in1", label="b3")
b4 = Connection(condenser, "out1", pump, "in1", label="b4")
b5 = Connection(pump, "out1", recuperator, "in2", label="b5")
b6 = Connection(recuperator, "out2", preheater, "in2", label="b6")
b7 = Connection(preheater, "out2", evaporator, "in2", label="b7")
b8 = Connection(evaporator, "out2", cc, "in1", label="b8")
c1 = Connection(air_source, "out1", condenser, "in2", label="c1")
c2 = Connection(condenser, "out2", air_sink, "in1", label="c2")
nw.add_conns(a1, a2, a3, b1, b2, b3, b4, b5, b6, b7, b8, c1, c2)
generator = Generator("generator")
motor = Motor("motor")
power_bus = PowerBus("bus", num_in=1, num_out=2)
grid = PowerSink("grid")
e1 = PowerConnection(turbine, "power", generator, "power_in", label="e1")
e2 = PowerConnection(generator, "power_out", power_bus, "power_in1", label="e2")
e3 = PowerConnection(power_bus, "power_out1", motor, "power_in", label="e3")
e4 = PowerConnection(motor, "power_out", pump, "power", label="e4")
e5 = PowerConnection(power_bus, "power_out2", grid, "power", label="e5")
nw.add_conns(e1, e2, e3, e4, e5)
generator.set_attr(eta=0.98)
motor.set_attr(eta=0.98)
a1.set_attr(fluid={"air": 1}, T=200, p=1, m=10)
b1.set_attr(fluid={"Isopentane": 1}, x=1, T=150)
b3.set_attr(td_dew=10)
b4.set_attr(td_bubble=5)
b7.set_attr(td_bubble=5)
c1.set_attr(fluid={"air": 1}, T=10, p=1)
c2.set_attr(T=20)
recuperator.set_attr(dp1=0, dp2=0)
condenser.set_attr(dp1=0, dp2=0)
preheater.set_attr(dp1=0, dp2=0)
evaporator.set_attr(dp1=0, dp2=0)
turbine.set_attr(eta_s=0.8)
pump.set_attr(eta_s=0.7)
condenser.set_attr(td_pinch=5)
evaporator.set_attr(td_pinch=10)
return nw
The model is well specified and solves without any issues:
nw = build_orc()
nw.solve("design")
nw.assert_convergence()
print(f"net power: {nw.get_conn('e5').E.val:.1f} kW")
net power: 178.8 kW
Inspecting a successful solve¶
Before breaking the model, we look at what the solver does with it when
everything works. All inspection methods are available after
presolve(), which prepares and
presolves the problem but stops before solving.
The original problem holds 57 variables. mass flow, pressure and enthalpy
per :code:Connection and an energy flow per :code:PowerConnection. The
reduction merges linearly coupled variables (e.g. all mass flows of the
cycle, the pressures connected through the :code:dp specifications) and
presolves everything the specifications determine directly. 13 variables
remain:
nw = build_orc()
nw.presolve("design")
nw.print_variables()
Variables after presolving (13 total):
# Property Represents
--- ---------- --------------------------------------------------------------
0 h b6 (h)
1 h a2 (h)
2 h a3 (h)
3 h b2 (h)
4 h b3 (h)
5 E e5 (E)
6 h b4 (h)
7 h b5 (h)
8 m b3 (m), b4 (m), b2 (m), b1 (m), b5 (m), b6 (m), b7 (m), b8 (m)
9 m c1 (m), c2 (m)
10 p b3 (p), b4 (p), b2 (p)
11 E e1 (E), e2 (E)
12 E e3 (E), e4 (E)
Each remaining variable has a short label (e.g. :code:h4) and lists the
original variables it represents. The same reduction applies to the equations.
:code:
nw.print_equations(),:code:
nw.print_presolved_variables()and:code:
nw.print_presolved_equations()show the tables.
Next, the solver analyses which equation determines which variable and in what order the equations can be processed, see the decomposition section for how this works:
nw.print_blocks()
Block lower triangular decomposition (11 blocks):
# Kind Needs Equations Variables
--- ------ ---------- ------------------------------------------- -----------
0 square condenser.td_pinch, b3.td_dew, b4.td_bubble h4, h6, p10
1 scalar evaporator.td_pinch h1
2 scalar 0 pump.eta_s h7
3 scalar 0 turbine.eta_s h3
4 scalar 1 evaporator.energy_balance_constraints m8
5 scalar 0, 4 condenser.energy_balance_constraints m9
6 scalar 0, 2, 4 pump.energy_connector_balance E12
7 scalar 0, 2, 3, 4 recuperator.energy_balance_constraints h0
8 scalar 3, 4 turbine.energy_connector_balance E11
9 scalar 6, 8 bus.energy_balance_constraint E5
10 scalar 1, 4, 7 preheater.energy_balance_constraints h2
The decomposition allows to analyze the problem on the mathematical level. You
will find that only the three equations fix the condensation state, i.e. the
condenser pinch together with the two saturation offsets. Everything else
follows sequentially: The isentropic efficiencies determine the machine outlet
enthalpies, the energy balances determine the mass flows and the power
connector balances determine the energy flows. The :code:Needs column lists
which blocks must be solved before solving a block.
The block lower triangular structure can also be displayed as an incidence
matrix, with :code:X marking the entries of an equation within its own
block and :code:x marking dependencies on variables of preceding blocks:
nw.print_incidence_matrix(block_order=True)
Incidence matrix:
Block h4 h6 p10 h1 h7 h3 m8 m9 E12 h0 E11 E5 h2
------- -------------------------------------- ---- ---- ----- ---- ---- ---- ---- ---- ----- ---- ----- ---- ----
0 condenser.td_pinch X X X - - - - - - - - - -
b3.td_dew X - X - - - - - - - - - -
b4.td_bubble - X X - - - - - - - - - -
1 evaporator.td_pinch - - - X - - - - - - - - -
2 pump.eta_s - x x - X - - - - - - - -
3 turbine.eta_s - - x - - X - - - - - - -
4 evaporator.energy_balance_constraints - - - x - - X - - - - - -
5 condenser.energy_balance_constraints x x - - - - x X - - - - -
6 pump.energy_connector_balance - x - - x - x - X - - - -
7 recuperator.energy_balance_constraints x - - - x x x - - X - - -
8 turbine.energy_connector_balance - - - - - x x - - - X - -
9 bus.energy_balance_constraint - - - - - - - - x - x X -
10 preheater.energy_balance_constraints - - - x - - x - - x - - X
The starting values generated for the remaining variables are inspected
with :code:print_variable_values. All values are SI values:
nw.print_variable_values()
Current variable values (13 total):
# Property Represents SI value
--- ---------- ------------ ------------
0 h b6 (h) 2.527262e+05
1 h a2 (h) 5.909122e+05
2 h a3 (h) 5.863523e+05
3 h b2 (h) 4.496956e+05
4 h b3 (h) 4.629675e+05
5 E e5 (E) 2.313834e+04
6 h b4 (h) 1.822059e+05
7 h b5 (h) 1.962334e+05
8 m b3 (m) 5.139894e-01
8 m b4 (m) 5.139894e-01
8 m b2 (m) 5.139894e-01
8 m b1 (m) 5.139894e-01
8 m b5 (m) 5.139894e-01
8 m b6 (m) 5.139894e-01
8 m b7 (m) 5.139894e-01
8 m b8 (m) 5.139894e-01
9 m c1 (m) 1.067294e+01
9 m c2 (m) 1.067294e+01
10 p b3 (p) 7.880278e+05
10 p b4 (p) 7.880278e+05
10 p b2 (p) 7.880278e+05
11 E e1 (E) 2.914222e+04
11 E e2 (E) 2.855937e+04
12 E e3 (E) 5.421034e+03
12 E e4 (E) 5.312613e+03
solve_continue runs the solution process on the prepared problem
and finishes the calculation:
nw.solve_continue()
print(nw.status)
0
Structural errors¶
The determination check compares the number of unknowns with the number of equations. With the maximum matching of the decomposition the solver additionally locates the part of the problem in which a defect sits. Specifying the evaporator heat transfer on top of the well determined model will show what equations overdetermine which variable(s).
nw = build_orc()
nw.get_comp("evaporator").set_attr(Q=-1e6)
nw.solve("design")
You have provided too many parameters: 13 required, 14 supplied. Aborting calculation!
The original problem holds 57 variables and 52 equations. Presolving consumed 38 equations and reduced the problem to 13 variables and 14 equations.
Structural analysis - the problem contains an over-determined part (2 equations competing for 1 variable).
Inspect the problem with
- nw.print_structural_analysis() for the over- or under-determined part of the model,
- nw.print_variables() and nw.print_equations() for the variables and equations that are present,
- nw.print_equations_with_dependents() for the variables each equation depends on,
- nw.print_incidence_matrix() for a compact overview.
---------------------------------------------------------------------------
TESPyNetworkError Traceback (most recent call last)
Cell In[9], line 3
1 nw = build_orc()
2 nw.get_comp("evaporator").set_attr(Q=-1e6)
----> 3 nw.solve("design")
File ~/checkouts/readthedocs.org/user_builds/tespy/envs/main/lib/python3.14/site-packages/tespy/networks/network.py:2470, in Network.solve(self, mode, init_path, design_path, max_iter, min_iter, init_only, init_previous, use_cuda, print_results, robust_relax, skip_postprocess, oscillation_damping, block_solve, pause_on_block_failure)
2374 def solve(self, mode, init_path=None, design_path=None,
2375 max_iter=50, min_iter=2, init_only=False, init_previous=True,
2376 use_cuda=False, print_results=True, robust_relax=False, skip_postprocess=False,
2377 oscillation_damping=False, block_solve=True,
2378 pause_on_block_failure=False):
2379 r"""
2380 Solve the network.
2381
(...) 2468 documentation at tespy.readthedocs.io in the section "TESPy modules".
2469 """
-> 2470 self.presolve(
2471 mode, init_path=init_path, design_path=design_path,
2472 init_previous=init_previous, check=not init_only
2473 )
2475 if init_only:
2476 return
File ~/checkouts/readthedocs.org/user_builds/tespy/envs/main/lib/python3.14/site-packages/tespy/networks/network.py:2570, in Network.presolve(self, mode, init_path, design_path, init_previous, check)
2567 return
2569 try:
-> 2570 self._problem.check_determination()
2571 except hlp.TESPyNetworkError:
2572 self.status = self._problem.status
File ~/checkouts/readthedocs.org/user_builds/tespy/envs/main/lib/python3.14/site-packages/tespy/solver/problem.py:1199, in Problem.check_determination(self)
1197 logger.error(msg)
1198 self.status = 12
-> 1199 raise hlp.TESPyNetworkError(msg)
1200 elif n < self.variable_counter:
1201 msg = (
1202 f"You have not provided enough parameters: {self.variable_counter} "
1203 f"required, {n} supplied. Aborting calculation!{_reduction}"
1204 f"{self._structural_summary()}{_hint}"
1205 )
TESPyNetworkError: You have provided too many parameters: 13 required, 14 supplied. Aborting calculation!
The original problem holds 57 variables and 52 equations. Presolving consumed 38 equations and reduced the problem to 13 variables and 14 equations.
Structural analysis - the problem contains an over-determined part (2 equations competing for 1 variable).
Inspect the problem with
- nw.print_structural_analysis() for the over- or under-determined part of the model,
- nw.print_variables() and nw.print_equations() for the variables and equations that are present,
- nw.print_equations_with_dependents() for the variables each equation depends on,
- nw.print_incidence_matrix() for a compact overview.
The structural analysis remains available after the error is raised and you can print the affected equations and variables:
nw.print_structural_analysis()
Over-determined part - the following equations compete for the involved variables:
Equations: evaporator.Q, evaporator.td_pinch
Involved variables: h1
The evaporator heat transfer and its pinch specification both determine the
enthalpy at the evaporator air outlet (:code:h1).
Similarly, if we remove a specification from a fresh network instance, we produce an under-determined part:
nw = build_orc()
nw.get_conn("c2").set_attr(T=None)
nw.solve("design")
You have not provided enough parameters: 14 required, 13 supplied. Aborting calculation!
The original problem holds 57 variables and 50 equations. Presolving consumed 37 equations and reduced the problem to 14 variables and 13 equations.
Structural analysis - the problem contains an under-determined part (12 variables constrained by 11 equations).
Inspect the problem with
- nw.print_structural_analysis() for the over- or under-determined part of the model,
- nw.print_variables() and nw.print_equations() for the variables and equations that are present,
- nw.print_equations_with_dependents() for the variables each equation depends on,
- nw.print_incidence_matrix() for a compact overview.
---------------------------------------------------------------------------
TESPyNetworkError Traceback (most recent call last)
Cell In[11], line 3
1 nw = build_orc()
2 nw.get_conn("c2").set_attr(T=None)
----> 3 nw.solve("design")
File ~/checkouts/readthedocs.org/user_builds/tespy/envs/main/lib/python3.14/site-packages/tespy/networks/network.py:2470, in Network.solve(self, mode, init_path, design_path, max_iter, min_iter, init_only, init_previous, use_cuda, print_results, robust_relax, skip_postprocess, oscillation_damping, block_solve, pause_on_block_failure)
2374 def solve(self, mode, init_path=None, design_path=None,
2375 max_iter=50, min_iter=2, init_only=False, init_previous=True,
2376 use_cuda=False, print_results=True, robust_relax=False, skip_postprocess=False,
2377 oscillation_damping=False, block_solve=True,
2378 pause_on_block_failure=False):
2379 r"""
2380 Solve the network.
2381
(...) 2468 documentation at tespy.readthedocs.io in the section "TESPy modules".
2469 """
-> 2470 self.presolve(
2471 mode, init_path=init_path, design_path=design_path,
2472 init_previous=init_previous, check=not init_only
2473 )
2475 if init_only:
2476 return
File ~/checkouts/readthedocs.org/user_builds/tespy/envs/main/lib/python3.14/site-packages/tespy/networks/network.py:2570, in Network.presolve(self, mode, init_path, design_path, init_previous, check)
2567 return
2569 try:
-> 2570 self._problem.check_determination()
2571 except hlp.TESPyNetworkError:
2572 self.status = self._problem.status
File ~/checkouts/readthedocs.org/user_builds/tespy/envs/main/lib/python3.14/site-packages/tespy/solver/problem.py:1208, in Problem.check_determination(self)
1206 logger.error(msg)
1207 self.status = 11
-> 1208 raise hlp.TESPyNetworkError(msg)
TESPyNetworkError: You have not provided enough parameters: 14 required, 13 supplied. Aborting calculation!
The original problem holds 57 variables and 50 equations. Presolving consumed 37 equations and reduced the problem to 14 variables and 13 equations.
Structural analysis - the problem contains an under-determined part (12 variables constrained by 11 equations).
Inspect the problem with
- nw.print_structural_analysis() for the over- or under-determined part of the model,
- nw.print_variables() and nw.print_equations() for the variables and equations that are present,
- nw.print_equations_with_dependents() for the variables each equation depends on,
- nw.print_incidence_matrix() for a compact overview.
nw.print_structural_analysis()
Under-determined part - the following variables cannot be determined by the involved equations:
Variables: h0, h2, h3, h4, h5, E6, h7, h8, m10, p11, E12, E13
Involved equations: bus.energy_balance_constraint, condenser.energy_balance_constraints, condenser.td_pinch, preheater.energy_balance_constraints, pump.energy_connector_balance, pump.eta_s, recuperator.energy_balance_constraints, turbine.energy_connector_balance, turbine.eta_s, b3.td_dew, b4.td_bubble
The list is longer here because the missing equation propagates through multiple parts. without the air outlet temperature the condenser energy balance cannot determine the air mass flow, without the air mass flow the condensation level is open, and so on.
A more subtle case is a count-balanced but structurally singular problem. If we remove the air outlet temperature and specify the evaporator heat transfer, we will see 14 equations for 14 variables. However, now the evaporator side is over-determined and the condenser side is under-determined at the same time. Block-wise solving is impossible in this case and the solver reports the structural analysis and exits with status 3.
nw = build_orc()
nw.get_conn("c2").set_attr(T=None)
nw.get_comp("evaporator").set_attr(Q=-1e6)
nw.solve("design")
print(nw.status)
The problem is structurally singular, block-wise solving is not possible.
Structural analysis - the problem contains an under-determined part (12 variables constrained by 11 equations) and an over-determined part (2 equations competing for 1 variable).
Use nw.print_structural_analysis() for the affected equations and variables. If the structural defect stems from an incomplete dependency declaration of a custom equation, the simultaneous solution can still be attempted with nw.solve(mode, block_solve=False).
3
Both defective parts are visible at once here:
nw.print_structural_analysis()
Under-determined part - the following variables cannot be determined by the involved equations:
Variables: h0, h2, h3, h4, h5, E6, h7, h8, m10, p11, E12, E13
Involved equations: bus.energy_balance_constraint, condenser.energy_balance_constraints, condenser.td_pinch, preheater.energy_balance_constraints, pump.energy_connector_balance, pump.eta_s, recuperator.energy_balance_constraints, turbine.energy_connector_balance, turbine.eta_s, b3.td_dew, b4.td_bubble
Over-determined part - the following equations compete for the involved variables:
Equations: evaporator.Q, evaporator.td_pinch
Involved variables: h1
Tip
The message also points to :code:block_solve=False to attempt the
simultaneous solution anyway, for the case that the structural defect stems
from an incomplete dependency declaration of a custom component rather than
from the specifications.
The structural analysis works on the incidence only (which equation depends on which variable). A linear dependency can also arise from the values even when the structure is sound, e.g. redundant specifications connected through nonlinear relations or starting values on a saturation plateau. The solver then reports status 3 and the singularity diagnosis names the suspect equations in the log, see the debugging section.
Specifications and decomposition¶
Changing a specification changes the block structure. In the base model the mass flow of the heat source is given and every block is determined in sequence. If we instead prescribe the net power of the plant, the mass flows can only be determined together with the energy flows through the bus balance:
nw = build_orc()
nw.get_conn("a1").set_attr(m=None)
nw.get_conn("e5").set_attr(E=180)
nw.presolve("design")
nw.print_blocks()
Block lower triangular decomposition (9 blocks):
# Kind Needs Equations Variables
--- ------ ---------- ---------------------------------------------------------------------------------------------- ------------
0 square condenser.td_pinch, b3.td_dew, b4.td_bubble h4, h5, p9
1 scalar evaporator.td_pinch h1
2 scalar 0 pump.eta_s h6
3 scalar 0 turbine.eta_s h3
4 square 0, 2, 3 bus.energy_balance_constraint, pump.energy_connector_balance, turbine.energy_connector_balance m7, E11, E12
5 scalar 0, 4 condenser.energy_balance_constraints m8
6 scalar 1, 4 evaporator.energy_balance_constraints m10
7 scalar 0, 2, 3, 4 recuperator.energy_balance_constraints h0
8 scalar 1, 4, 6, 7 preheater.energy_balance_constraints h2
Block 4 now couples the cycle mass flow with the turbine and pump energy flows. The bus balance connects generator output and motor input, which are tied to the same mass flow through the connector balances. The larger the blocks of your model the harder will debugging be. However, especially in offdesign simulations tightly coupled problems that cannot easily be reduced to multiple subproblems are expected.
Staged solving¶
solve first executes presolve and subsequently solve_continue. You can
pause the model execution between the two stages and inspect the problem, the
variables and their values and even modify the initial guesses yourself (values
are SI values). On this model the generated starting values are good enough
that staging is not needed, therefore the cell only intends to show how the
mechanism works.
nw = build_orc()
nw.presolve("design")
nw.set_variable_value("b4", "p", 1.2e5)
nw.solve_continue()
print(nw.status)
0
Pausing and inspecting a failed block¶
This section will show how you can set starting values selectively for a failing block. To construct the example, we first run the simulation with a tiny pinch point value for the condenser, retrieve the resulting UA and impose it to a freshly constructed model. Then we see that the new solve will fail with a non-convergence warning.
nw = build_orc()
nw.get_comp("condenser").set_attr(td_pinch=0.001)
nw.solve("design")
nw.assert_convergence()
UA_value = nw.get_comp("condenser").UA.val
nw.results["Connection"].loc[["c1", "b3", "b4"], ["m", "p", "h"]]
| m | p | h | |
|---|---|---|---|
| c1 | 78.007190 | 1.000000 | 409348.270900 |
| b3 | 2.078356 | 0.754191 | 347636.458784 |
| b4 | 2.078356 | 0.754191 | -29939.266111 |
nw = build_orc()
nw.get_comp("condenser").set_attr(td_pinch=None, UA=UA_value)
nw.solve("design", pause_on_block_failure=True)
nw.status
Block 2 did not converge, pausing the solution process.
Cause: no acceptance within the iteration budget of 50 iterations, the last scaled residual is 3.78e+01
Inspect the failed block with
- Network.print_blocks() for the block decomposition with the equations, variables and solve status of every block,
- Network.print_variable_values(block=2) for the variables of the block and their current values,
- Network.print_block_jacobian(block=2) for the jacobian and residual as evaluated in the failing iteration,
- Network.print_block_states(block=2) for the states of the involved connections at the current values, with at='failure' as evaluated in the failing iteration.
Modify variable values with Network.set_variable_value and retry with Network.solve_continue(). Passing pause_on_block_failure=False there continues with the standard escalation stages instead in case the block fails again.
20
We can inspect the fluid state at failure, the variables relevant to the block are marked with a star.
nw.print_block_states(block=2, at="failure")
States of the connections of block 2 at the state of failure (*: variable of the block):
Connection m p h T phase
------------ -------------- -------------- -------------- ------- -------
b3 2.078356e+00 3.374839e+06 * 1.389740e+06 * 719.797 g
c1 1.043058e+01 * 1.000000e+05 4.093483e+05 283.15 g
b4 2.078356e+00 3.374839e+06 * 1.389740e+06 * 719.797 g
c2 1.043058e+01 * 1.000000e+05 4.194081e+05 293.15 g
b2 2.078356e+00 3.374839e+06 * 4.496956e+05 456.445 l
And we can inspect the same before starting the block solve. Simultaneously, we can also inspect the variables directly when starting the block solve.
nw.print_block_states(block=2)
nw.print_variable_values(block=2)
States of the connections of block 2 at the current variable values (*: variable of the block):
Connection m p h T phase
------------ -------------- -------------- -------------- ------ -------
b3 2.078356e+00 7.880278e+05 * 4.847008e+05 * 387.25 g
c1 1.507707e+03 * 1.000000e+05 4.093483e+05 283.15 g
b4 2.078356e+00 7.880278e+05 * 1.784017e+05 * 372.25 l
c2 1.507707e+03 * 1.000000e+05 4.194081e+05 293.15 g
b2 2.078356e+00 7.880278e+05 * 4.496956e+05 377.25 tp
Current variable values of block 2 (4 total):
# Property Represents SI value
--- ---------- ------------ ------------
4 h b3 (h) 4.847008e+05
6 h b4 (h) 1.784017e+05
9 m c1 (m) 1.507707e+03
9 m c2 (m) 1.507707e+03
10 p b3 (p) 7.880278e+05
10 p b4 (p) 7.880278e+05
10 p b2 (p) 7.880278e+05
We can transfer the variable values from the tiny pinch solution and continue
solving. In this case we apply osciallation_damping to help the convergence,
since a tiny change in any of the variables will trigger a sign change in the
UA residual.
nw.set_variable_value("b3", "h", 347635)
nw.set_variable_value("c1", "m", 78)
nw.set_variable_value("b4", "h", -29941)
nw.set_variable_value("b3", "p", 754.166)
nw.solve_continue()
nw.status
0
In case you want to continue solving without pausing on a failure, you can run
nw.solve_continue(pause_on_block_failure=False).