Skip to content

Commit e828901

Browse files
authored
Merge pull request #33 from statnett/reintroduce-invalid-value-in-bisect
feat: reintroduce invalid_value in bisect
2 parents 31b9b4a + d983075 commit e828901

File tree

1 file changed

+15
-4
lines changed

1 file changed

+15
-4
lines changed

linerate/solver.py

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from functools import partial
2-
from typing import Callable
2+
from typing import Callable, Optional
33

44
import numpy as np
55

@@ -13,6 +13,7 @@ def bisect(
1313
xmin: FloatOrFloatArray,
1414
xmax: FloatOrFloatArray,
1515
tolerance: float,
16+
invalid_value: Optional[float] = None,
1617
) -> FloatOrFloatArray:
1718
r"""Compute the roots of a function using a vectorized bisection method.
1819
@@ -31,6 +32,9 @@ def bisect(
3132
bounded within an interval of size :math:`\Delta x` or less. The bisection method will
3233
run for :math:`\left\lceil\frac{x_\max - x_\min}{\Delta x}\right\rceil`
3334
iterations.
35+
invalid_value:
36+
If provided, then this value is used whenever
37+
:math:`\text{sign}(f(\mathbf{x}_\min)) = \text{sign}(f(\mathbf{x}_\max))`.
3438
3539
Returns
3640
-------
@@ -47,10 +51,12 @@ def bisect(
4751
f_right = f(xmax)
4852

4953
invalid_mask = np.sign(f_left) == np.sign(f_right)
50-
if np.any(invalid_mask):
54+
if np.any(invalid_mask) and invalid_value is None:
5155
raise ValueError(
5256
"f(xmin) and f(xmax) have the same sign. Consider increasing the search interval."
5357
)
58+
elif isinstance(invalid_mask, bool) and invalid_mask:
59+
return invalid_value # type: ignore
5460

5561
while interval > tolerance:
5662
xmid = 0.5 * (xmax + xmin)
@@ -63,7 +69,7 @@ def bisect(
6369
f_left = np.where(mask, f_mid, f_left)
6470
f_right = np.where(mask, f_right, f_mid)
6571

66-
out = 0.5 * (xmax + xmin)
72+
out = np.where(invalid_mask, invalid_value, 0.5 * (xmax + xmin)) # type: ignore
6773
return out
6874

6975

@@ -112,6 +118,7 @@ def compute_conductor_ampacity(
112118
min_ampacity: Ampere = 0,
113119
max_ampacity: Ampere = 5_000,
114120
tolerance: float = 1, # Ampere
121+
invalid_value=None,
115122
) -> Ampere:
116123
r"""Use the bisection method to compute the steady-state thermal rating (ampacity).
117124
@@ -134,6 +141,10 @@ def compute_conductor_ampacity(
134141
bisection iterations will stop once the numerical ampacity uncertainty is below
135142
:math:`\Delta I`. The bisection method will run for
136143
:math:`\left\lceil\frac{I_\text{max} - I_\text{min}}{\Delta I}\right\rceil` iterations.
144+
invalid_value:
145+
if the optimization problem is invalid, this value is returned instead of an error.
146+
Suggested value: 0 for 0-ampacity when max_conductor_temperature is exceeded for all
147+
ampacities.
137148
138149
Returns
139150
-------
@@ -142,4 +153,4 @@ def compute_conductor_ampacity(
142153
"""
143154
f = partial(heat_balance, max_conductor_temperature)
144155

145-
return bisect(f, min_ampacity, max_ampacity, tolerance)
156+
return bisect(f, min_ampacity, max_ampacity, tolerance, invalid_value=invalid_value)

0 commit comments

Comments
 (0)