Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/remove kwant dev dependency #72

Merged
merged 19 commits into from
Dec 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,6 @@ jobs:
pipx install --pip-args=--constraint=.github/workflows/constraints.txt poetry
poetry --version

- name: Install System Dependencies (Ubuntu)
if: startsWith(matrix.os, 'ubuntu') && (matrix.session == 'no')
run: |
sudo apt-get update
sudo apt-get install -y python3-dev python3-setuptools python3-scipy python3-matplotlib python3-pytest python3-sympy g++ build-essential gfortran libopenblas-dev liblapack-dev libmumps-scotch-dev

- name: Install Python dependencies (Ubuntu)
if: startsWith(matrix.os, 'ubuntu') && (matrix.session == 'no')
run: |
python -m pip install cython tinyarray

- name: Clone and Install kwant (Ubuntu)
if: startsWith(matrix.os, 'ubuntu') && (matrix.session == 'no')
run: |
git clone https://github.com/kwant-project/kwant.git
cd kwant
git checkout master

- name: Install Nox
run: |
pipx install --pip-args=--constraint=.github/workflows/constraints.txt nox
Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,44 @@ KPM Tools is an open-source Python package that extends the Kernel Polynomial Me
## Requirements

- Python >=3.9
- Kwant >= 1.4.4

## Installation

### Installing KPM Tools

You can install _KPM Tools_ via [pip] from [PyPI]:

```console
$ pip install kpm-tools
```

### Important Note on Kwant Dependency

While _KPM Tools_ requires Kwant to function, direct installation of Kwant via pip can sometimes be problematic due to its specific build requirements. To ensure a smooth setup, we recommend the following installation approach:

1. **Try installing with pip (optional):**

You can attempt to install Kwant along with KPM Tools via pip:

```console
$ pip install kpm-tools[kwant]
```

If this installation fails, proceed to the next step.

2. **Install Kwant using Conda or follow Kwant's installation guide:**

We recommend using Conda to install Kwant, which typically handles its build requirements more reliably:

```console
$ conda install -c conda-forge kwant
```

Alternatively, refer to the [Kwant installation page](https://kwant-project.org/install) for detailed instructions on installing Kwant in different environments.

After installing Kwant, you can then install KPM Tools using pip as shown above.

## Python API

Please see the [python api reference] for details.
Expand Down
70 changes: 31 additions & 39 deletions docs/tutorials/tutorial_bloch.ipynb

Large diffs are not rendered by default.

635 changes: 541 additions & 94 deletions docs/tutorials/tutorial_tiles.ipynb

Large diffs are not rendered by default.

79 changes: 17 additions & 62 deletions docs/tutorials/tutorial_time_evolution.ipynb

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ def activate_virtualenv_in_precommit_hooks(session: Session) -> None:

@nox.session(python=python_versions)
def install_kwant(session: Session):
"""Install kwant from source."""
session.install("cython", "numpy", "scipy", "sympy", "tinyarray", "kwant")
"""Install kwant from PyPi."""
session.install("kwant")


@nox.session(python=python_versions)
Expand Down Expand Up @@ -146,8 +146,8 @@ def build_kwant(session: Session):
# Navigate to the cloned directory
session.cd(str(kwant_dir))

# Checkout the master branch
session.run("git", "checkout", "master", external=True)
# Checkout the stable branch
session.run("git", "checkout", "stable", external=True)

# Install kwant from source
if need_to_build:
Expand Down
941 changes: 470 additions & 471 deletions poetry.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ sphinx-click = ">=3.0.2"
typeguard = ">=2.13.3"
xdoctest = {extras = ["colors"], version = ">=0.15.10"}
myst-parser = {version = ">=0.16.1"}
kwant = { version = "^1.4.4", optional = true }

[tool.poetry.extras]
kwant = ["kwant"]

[tool.poetry.scripts]
kpm-tools = "kpm_tools.__main__:main"
Expand Down
2 changes: 0 additions & 2 deletions pytest.ini

This file was deleted.

7 changes: 7 additions & 0 deletions src/kpm_tools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
"""KPM Tools."""
# flake8: noqa
try:
import kwant
except ImportError:
raise ImportError(
"Missing dependency 'kwant'. Please install it manually. "
"Visit https://kwant-project.org/ for installation instructions."
)
from .bloch import _hopping_distance
from .bloch import separate_bloch_components
from .bloch import wrap_distance
Expand Down
71 changes: 51 additions & 20 deletions src/kpm_tools/bloch.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,24 @@
import collections
import inspect
import warnings
from functools import cache

import kwant.system
import numpy as np
import tinyarray as ta
from kwant._common import get_parameters
from kwant._common import memoize
from kwant.builder import Builder
from kwant.builder import HermConjOfFunc
from kwant.builder import herm_conj
from kwant.lattice import TranslationalSymmetry
from kwant.system import SiteArray
from kwant.wraparound import WrappedBuilder
from kwant.wraparound import _callable_herm_conj
from kwant.wraparound import _set_signature
from kwant.wraparound import wraparound

from .utils import get_parameters


support_site_array = hasattr(kwant.system, "SiteArray")


def wraparound_by_parts(
builder, keep=None, *, coordinate_names="xyz", separate_sites=False
Expand Down Expand Up @@ -55,7 +59,12 @@ def wraparound_by_parts(

"""

@memoize
@cache
def _callable_herm_conj(val):
"""Keep the same id for every 'val'."""
return HermConjOfFunc(val)

@cache
def bind_site(val):
def f(*args):
a, *args = args
Expand All @@ -66,7 +75,7 @@ def f(*args):
_set_signature(f, get_parameters(val) + momenta)
return f

@memoize
@cache
def bind_hopping_as_site(elem, val):
def f(*args):
a, *args = args
Expand All @@ -81,7 +90,7 @@ def f(*args):
_set_signature(f, params + momenta)
return f

@memoize
@cache
def bind_hopping(elem, val):
def f(*args):
a, b, *args = args
Expand All @@ -95,7 +104,7 @@ def f(*args):
_set_signature(f, params + momenta)
return f

@memoize
@cache
def bind_sum(num_sites, *vals):
"""Construct joint signature for all 'vals'."""

Expand Down Expand Up @@ -203,7 +212,8 @@ def f(*in_args):
ret.particle_hole = None
ret.time_reversal = None

ret.vectorize = builder.vectorize
if hasattr(builder, "vectorize"):
ret.vectorize = builder.vectorize

sites = {}
hops = collections.defaultdict(list)
Expand Down Expand Up @@ -340,21 +350,36 @@ def separate_bloch_components(builder):
return fsyst_bloch_superonsite, fsyst_bloch_superhopping


def _get_positions(site):
"""Extract positions from a site. Handles both Site and SiteArray.

Args:
- site (Any): A Site or SiteArray object.

Returns:
- np.ndarray: Position array.
"""
if hasattr(site, "positions"): # Handle SiteArray
return site.positions().transpose()
if hasattr(site, "pos"): # Handle Site
return site.pos
else:
raise TypeError("The site object does not have a valid position attribute.")


def _hopping_distance(site1, site2, direction):
norbs = site1.family.norbs
if norbs != site2.family.norbs:
raise NotImplementedError(
"Only hopppings between sites of equal number of orbitals is implemented."
)

if isinstance(site1, SiteArray):
pos1 = site1.positions().transpose()
pos2 = site2.positions().transpose()
d = np.dot(direction, (pos1 - pos2))[:, np.newaxis, np.newaxis]
else:
pos1 = site1.pos
pos2 = site2.pos
d = np.dot(direction, (pos1 - pos2))
pos1 = _get_positions(site1)
pos2 = _get_positions(site2)
d = np.dot(direction, (pos1 - pos2))

if support_site_array and hasattr(site1, "positions"):
d = d[:, np.newaxis, np.newaxis]

# return an imaginary number so that the matrix is antisymmetric
# but hermitian
Expand All @@ -376,7 +401,7 @@ def wrap_velocity(builder):
direction = ("direction",)
dnp = -len(direction)

@memoize
@cache
def bind_velocity_hopping(val):
def f(*args):
a, b, *args = args # first two args are sites
Expand All @@ -392,7 +417,10 @@ def f(*args):
_set_signature(f, params + direction)
return f

velocity_builder = Builder(builder.symmetry, vectorize=builder.vectorize)
if hasattr(builder, "vectorize"):
velocity_builder = Builder(builder.symmetry, vectorize=builder.vectorize)
else:
velocity_builder = Builder(builder.symmetry)

for s in builder.sites():
norbs = s.family.norbs
Expand All @@ -419,7 +447,10 @@ def wrap_distance(builder):
Hamiltonian of the original system, and does not depends on the
paramters of the original system, the 'builder'.
"""
distance_builder = Builder(builder.symmetry, vectorize=builder.vectorize)
if hasattr(builder, "vectorize"):
distance_builder = Builder(builder.symmetry, vectorize=builder.vectorize)
else:
distance_builder = Builder(builder.symmetry)

for s in builder.sites():
norbs = s.family.norbs
Expand Down
2 changes: 1 addition & 1 deletion src/kpm_tools/hamiltonians.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import kwant
import numpy as np
from kwant import HoppingKind
from kwant.builder import HoppingKind


# neighbors for honeycomb lattice
Expand Down
3 changes: 2 additions & 1 deletion src/kpm_tools/kpm_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from scipy.sparse.linalg import eigsh

from .common import identity_operator
from .utils import ensure_rng


DEFAULT_MOMENTS = 100
Expand Down Expand Up @@ -245,7 +246,7 @@ def __init__(
self.operator = _normalize_operator(operator, params)

self.mean = mean
rng0 = kwant._common.ensure_rng(rng)
rng0 = ensure_rng(rng)

_v0 = None
if bounds is None:
Expand Down
3 changes: 2 additions & 1 deletion src/kpm_tools/tiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

import kwant
import numpy as np
from kwant._common import ensure_rng

from .utils import ensure_rng


def momentum_to_ts(k, ts):
Expand Down
Loading
Loading