Skip to content

Commit

Permalink
Merge branch 'main' into chore-remove-unused-dependency-pillow
Browse files Browse the repository at this point in the history
  • Loading branch information
amundfr authored Apr 5, 2024
2 parents 380a0f0 + 617db5c commit 224a171
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 40 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ jobs:
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: 3.8
- name: install poetry
Expand Down Expand Up @@ -59,9 +59,9 @@ jobs:
if: github.repository_owner == 'statnett'
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: 3.8
- name: install poetry
Expand All @@ -77,9 +77,9 @@ jobs:
poetry run make html
- name: Setup Pages
id: pages
uses: actions/configure-pages@v3
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
uses: actions/upload-pages-artifact@v3
with:
path: docs/_build/html

Expand All @@ -93,4 +93,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
uses: actions/deploy-pages@v4
6 changes: 3 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
python: ['3.8', '3.9', '3.10']
python: ['3.9', '3.10', '3.11']
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: install poetry
Expand Down
18 changes: 6 additions & 12 deletions linerate/solver.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from functools import partial
from typing import Callable, Optional
from typing import Callable

import numpy as np

Expand All @@ -13,7 +13,6 @@ def bisect(
xmin: FloatOrFloatArray,
xmax: FloatOrFloatArray,
tolerance: float,
invalid_value: Optional[float] = None,
) -> FloatOrFloatArray:
r"""Compute the roots of a function using a vectorized bisection method.
Expand All @@ -32,9 +31,6 @@ def bisect(
bounded within an interval of size :math:`\Delta x` or less. The bisection method will
run for :math:`\left\lceil\frac{x_\max - x_\min}{\Delta x}\right\rceil`
iterations.
invalid_value:
If provided, then the this value is used whenever
:math:`\text{sign}(f(\mathbf{x}_\min)) = \text{sign}(f(\mathbf{x}_\max))`.
Returns
-------
Expand All @@ -43,20 +39,18 @@ def bisect(
there is a root :math:`x_i \in [\tilde{x}_i - 0.5 \Delta x, \tilde{x}_i + 0.5 \Delta x]`
so :math:`f_i(x_i) = 0`.
"""
if not np.isfinite(xmin) or not np.isfinite(xmax):
if not np.all(np.isfinite(xmin)) or not np.all(np.isfinite(xmax)):
raise ValueError("xmin and xmax must be finite.")
interval = np.max(np.abs(xmax - xmin))

f_left = f(xmin)
f_right = f(xmax)

invalid_mask = np.sign(f_left) == np.sign(f_right)
if np.any(invalid_mask) and invalid_value is None:
if np.any(invalid_mask):
raise ValueError(
"f(xmin) and f(xmax) have the same sign. Consider increasing the search interval."
)
elif isinstance(invalid_mask, bool) and invalid_mask:
return invalid_value # type: ignore

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

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


Expand Down Expand Up @@ -139,7 +133,7 @@ def compute_conductor_ampacity(
:math:`\Delta I~\left[\text{A}\right]`. The numerical accuracy of the ampacity. The
bisection iterations will stop once the numerical ampacity uncertainty is below
:math:`\Delta I`. The bisection method will run for
:math:`\left\lceil\frac{I_\text{min} - I_\text{min}}{\Delta I}\right\rceil` iterations.
:math:`\left\lceil\frac{I_\text{max} - I_\text{min}}{\Delta I}\right\rceil` iterations.
Returns
-------
Expand All @@ -148,4 +142,4 @@ def compute_conductor_ampacity(
"""
f = partial(heat_balance, max_conductor_temperature)

return bisect(f, min_ampacity, max_ampacity, tolerance, invalid_value=0)
return bisect(f, min_ampacity, max_ampacity, tolerance)
17 changes: 8 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
[tool.poetry]
name = "linerate"
version = "0.0.7-post.3+62231f4"
version = "1.0.0"
description = "Library for computing line ampacity ratings for overhead lines"
authors = ["Statnett Datascience <[email protected]>", "Yngve Mardal Moe <[email protected]>"]
repository = "https://github.com/statnett/linerate.git"
readme = "README.md"

[tool.poetry.dependencies]
python = ">=3.8.1,<4.0"
python = ">=3.9,<4.0"
numpy = "*"
scipy = "*"
numba = ">=0.56.4"
pygeodesy = "*"
typing-extensions = { version = ">=4.0.0", python = "<3.9" }

[tool.poetry.dev-dependencies]
black = "24.3.0"
Expand All @@ -22,18 +21,18 @@ flake8-bugbear = "24.2.6"
hypothesis = ">= 6.56.2"
isort = "5.13.2"
pre-commit = "*"
pytest = "7.4.4"
pytest-cov = "4.0.0"
pytest-randomly = "3.12.0"
pytest = "8.1.1"
pytest-cov = "5.0.0"
pytest-randomly = "3.15.0"

[tool.poetry.group.docs]
optional = true

[tool.poetry.group.docs.dependencies]
sphinx = "^5.2.3"
sphinx = "^7.0.0"
sphinxcontrib-bibtex = "^2.5.0"
sphinx-gallery = "^0.11.1"
pydata-sphinx-theme = "^0.11.0"
sphinx-gallery = "^0.15.0"
pydata-sphinx-theme = "^0.15.0"
matplotlib = "^3.6.0"

[tool.poetry-dynamic-versioning]
Expand Down
60 changes: 51 additions & 9 deletions tests/test_solver.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import numpy as np
import pytest

import linerate.solver as solver
Expand Down Expand Up @@ -31,17 +32,58 @@ def heat_balance(conductor_temperature, current):
assert conductor_temperature == pytest.approx(9000, rel=1e-7)


def test_compute_conductor_temperature_caps_ampacity_at_zero():
def heat_balance(conductor_temperature, current):
def test_bisect_raises_value_error():
def heat_balance(current):
A = current
T = conductor_temperature
return (A + 100 * T) * (current + 200 * T)
T = 90
return (A + 100 * T) * (A + 100 * T)

conductor_temperature = solver.compute_conductor_ampacity(
with pytest.raises(ValueError):
solver.bisect(
heat_balance,
xmin=0,
xmax=10_000,
tolerance=1e-8,
)


def test_bisect_handles_function_returning_array_happy_path():
def heat_balance(currents: np.array):
A = currents
T = 90
res = (A - 100 * T) * (currents + 100 * T)
return res

solution = solver.bisect(
heat_balance,
max_conductor_temperature=90,
min_ampacity=0,
max_ampacity=10_000,
xmin=np.array([0, 0]),
xmax=np.array([10_000, 10_000]),
tolerance=1e-8,
)
assert conductor_temperature == pytest.approx(0, rel=1e-7)
np.testing.assert_array_almost_equal(solution, [9_000, 9_000], decimal=8)


def test_bisect_raises_valueerror_when_same_sign_for_array_input():
def heat_balance(currents: np.array):
A = currents
T = 90
res = (A - 100 * T) * (currents + 100 * T)
return res

with pytest.raises(ValueError):
solver.bisect(
heat_balance,
xmin=np.array([0, 0]),
xmax=np.array([10_000, 8_000]),
tolerance=1e-8,
)


def test_bisect_raises_valueerror_when_infinite_in_array_input():
with pytest.raises(ValueError):
solver.bisect(
lambda x: x,
xmin=np.array([-np.inf, 0]),
xmax=np.array([10_000, 10_000]),
tolerance=1e-8,
)

0 comments on commit 224a171

Please sign in to comment.