Skip to content

Commit

Permalink
Merge pull request #35 from viljarjf/dev
Browse files Browse the repository at this point in the history
0.1.1
  • Loading branch information
viljarjf authored May 23, 2023
2 parents c82d238 + e738d50 commit c4dd608
Show file tree
Hide file tree
Showing 25 changed files with 472 additions and 238 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/build_package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Upload Python Package

on:
release:
types: [published]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Publish package
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
44 changes: 44 additions & 0 deletions .github/workflows/linting.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Lint the sourcecode

on:
pull_request:
branches:
- dev
- main
workflow_dispatch:

permissions:
contents: write

env:
SRC_DIR: src/qm_sim

jobs:
lint:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
- name: setup
run: |
pip install .[linting]
- name: run black
run: |
black "$SRC_DIR" --check
- name: run isort
run: |
isort "$SRC_DIR" -m 3 --trailing-comma -c
- name: run pylint
run: |
pylint "$SRC_DIR" --fail-under=7
# Remove -c and --check if we want to force linting in the future
# - name: Commit changes
# run: |
# git config user.name github-actions
# git config user.email [email protected]
# git add .
# git commit -m "[Auto-generated] Linting"
# git push

21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Python library for simulation of quantum mechanical systems.

To be able to use the [PyTorch](https://pytorch.org/) backend for eigenvalue calculations, run the following command:

`pip install qm-sim .[torch]`
`pip install qm-sim[torch]`

This will install the cpu-version of the package. To run GPU calculations, install the version for your system at the [PyTorch website](https://pytorch.org/get-started/locally/) instead.

Expand All @@ -38,18 +38,31 @@ These are enumerated with increasing level of simulation complexity.

To contribute, please open a pull request to the `dev`-branch on [GitHub](https://www.github.com/viljarjf/QM_sim/pulls).

### Linting

When opening a PR, a linting check is performed.
To ensure your contribution passes the checks, you can run the following

~~~bash
$ pip install .[linting]
$ black src/qm_sim
$ isort src -m 3 --trailing-comma
$ pylint src --fail-under=7
~~~

### Setup

The following is an example of how to set up VS Code for development, adapt to your IDE of choice.

TL;DR:
- `pip install -e .` to install in an editable state
- `pip install .` to (re)compile the C++ (subsequent python file edits will not be recognized before another reinstall)

### Requirements
**Requirements**
- VS Code
- Python extension
- Python 3.10 or above

### Setup
**Steps**
1. Clone the repo recursively and open the repo in VS Code. If not cloned recursively, initialize the submodules with `git submodule update --init`
2. Press f1, and run `Python: Create Environment`. Select `.venv`
3. Open a new terminal, which should automatically use the virtual environment. If not, run `.venv\Scripts\activate` on Windows, or `source .venv/bin/activate` on Unix
Expand Down
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
project = 'QM sim'
copyright = '2023, Viljar Femoen'
author = 'Viljar Femoen'
release = '0.0.3'
release = '0.1.1'

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand Down
4 changes: 2 additions & 2 deletions examples/01_zero_potential.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from qm_sim.hamiltonian import Hamiltonian
from qm_sim.nature_constants import m_e

N = (100,) # Discretisation point count
L = (1e-9,) # System size in meters
N = 100 # Discretisation point count
L = 1e-9 # System size in meters
m = m_e # Mass of the particle, here chosen as electron mass
n = 4 # The amount of eigenstates to find

Expand Down
6 changes: 3 additions & 3 deletions examples/02_quadratic_potential.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@

import numpy as np

N = (1000,) # Discretisation point count
L = (1e-9,) # System size in meters
N = 1000 # Discretisation point count
L = 1e-9 # System size in meters
m = m_e # Mass of the particle, here chosen as electron mass
n = 4 # The amount of eigenstates to find

# Set hamiltonian
H = Hamiltonian(N, L, m)

# Set potential
x = np.linspace(-L[0]/2, L[0]/2, N[0])
x = np.linspace(-L/2, L/2, N)

def V(t):
k = 200
Expand Down
9 changes: 4 additions & 5 deletions examples/05_temporal_evolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from qm_sim.nature_constants import e_0, m_e


N = (200,) # Discretisation point count
L = (2e-9,) # System size in meters
N = 200 # Discretisation point count
L = 2e-9 # System size in meters
m = m_e # Mass of the particle, here chosen as electron mass
t_end = 10e-15 # Simulation time
dt = 1e-17 # Simulation data storage stepsize
Expand All @@ -14,9 +14,8 @@
H = Hamiltonian(N, L, m, temporal_scheme="leapfrog")

# Set the potential to a quadratic potential oscilating from side to side
z = np.linspace(-L[0]/2, L[0]/2, N[0])
Vt = lambda t: 6*z**2 + 3*z*np.abs(z)*np.sin(4e15*t)
H.V = Vt
z = np.linspace(-L/2, L/2, N)
H.V = lambda t: 6*z**2 + 3*z*np.abs(z)*np.sin(4e15*t)

# Plot
H.plot_temporal(t_end, dt)
25 changes: 21 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "qm_sim"
version = "0.1.0"
version = "0.1.1"
authors = [
{ name="Viljar Femoen", email="[email protected]" },
]
Expand Down Expand Up @@ -28,9 +28,10 @@ dependencies = [
"Source" = "https://github.com/viljarjf/QM_sim"

[project.optional-dependencies]
test = ["pytest", "matplotlib"]
torch = ["torch"]
docs = ["sphinx", "sphinx-rtd-theme", "sphinx-mdinclude"]
test = ["pytest", "matplotlib",]
torch = ["torch",]
docs = ["sphinx", "sphinx-rtd-theme", "sphinx-mdinclude",]
linting = ["black", "isort", "pylint",]

[build-system]
requires = [
Expand All @@ -46,3 +47,19 @@ wheel.expand-macos-universal-tags = true
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-raP"

[tool.black]
# this is a regex, not a list
exclude = "nature_constants.py"

[tool.pylint.'Basic']
good-names = [
"N", "L", "m", "x", "y", "z", "i", "j", "t", "t0",
"tn", "dt", "H", "h", "l", "n", "v", "w", "psi", "E",
"V",
]

[tool.pylint.'Main']
ignore = [
"nature_constants.py",
]
2 changes: 1 addition & 1 deletion src/qm_sim/cpp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
C++ code for faster eigenproblem solution.
Currently unused, as the performance was just the same at best
"""
"""
2 changes: 1 addition & 1 deletion src/qm_sim/cpp/eigen/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
try:
from .eigen_wrapper import *
except ImportError:
print("Warning: eigen_wrapper C++ module not found")
print("Warning: eigen_wrapper C++ module not found")
12 changes: 9 additions & 3 deletions src/qm_sim/cpp/eigen/scripts/generate_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@
"""

import sys, pathlib
import pathlib
import sys


def main(module_name: str):
path = pathlib.Path(__file__).parent.parent
with open(path / "__init__.py", "w") as file:
file.write(f"""try:
file.write(
f"""try:
from .{module_name} import *
except ImportError:
print("Warning: {module_name} C++ module not found")""")
print("Warning: {module_name} C++ module not found")
"""
)


if __name__ == "__main__":
if len(sys.argv) < 2:
Expand Down
4 changes: 4 additions & 0 deletions src/qm_sim/eigensolvers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,21 @@
"""

from typing import Callable

import numpy as np
from scipy import sparse as sp

# Dict to lookup the solvers
__SOLVERS = {}

from .scipy_eigen import scipy_get_eigen

__SOLVERS["scipy"] = scipy_get_eigen

# Import guard the pytorch backend since it is optional
try:
from .pytorch_eigen import torch_get_eigen

__SOLVERS["pytorch"] = torch_get_eigen
__SOLVERS["torch"] = torch_get_eigen
except (ImportError, RuntimeError):
Expand All @@ -30,5 +33,6 @@
# Function signature of the solver
Eigensolver = Callable[[sp.spmatrix, int, tuple[int]], tuple[np.ndarray, np.ndarray]]


def get_eigensolver(solver: str) -> Eigensolver | None:
return __SOLVERS.get(solver)
3 changes: 2 additions & 1 deletion src/qm_sim/eigensolvers/pytorch_eigen.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import torch
from scipy import sparse as sp

PYTORCH_DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
PYTORCH_DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")


def torch_get_eigen(mat: sp.dia_matrix, n: int, shape: tuple[int], **kwargs):
"""Calculate :code:`n` eigenvalues of :code:`mat`. Reshape output to :code:`shape`
Expand Down
55 changes: 40 additions & 15 deletions src/qm_sim/eigensolvers/scipy_eigen.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
Use the scipy backend eigen solver to skip some overhead
"""
from scipy._lib._threadsafety import ReentrancyLock
from scipy.sparse.linalg._eigen.arpack.arpack import _SymmetricArpackParams
import numpy as np
from scipy import sparse as sp
from scipy._lib._threadsafety import ReentrancyLock
from scipy.sparse.linalg import eigsh
import numpy as np
from scipy.sparse.linalg._eigen.arpack.arpack import _SymmetricArpackParams


def scipy_get_eigen(mat: sp.dia_matrix, n: int, shape: tuple[int], **kwargs) -> tuple[np.ndarray, np.ndarray]:
def scipy_get_eigen(
mat: sp.dia_matrix, n: int, shape: tuple[int], **kwargs
) -> tuple[np.ndarray, np.ndarray]:
"""Calculate :code:`n` eigenvalues of :code:`mat`. Reshape output to :code:`shape`
:param mat: Matrix to calculate eigenvectors and -values for
Expand All @@ -22,8 +25,7 @@ def scipy_get_eigen(mat: sp.dia_matrix, n: int, shape: tuple[int], **kwargs) ->
:rtype: tuple[np.ndarray(shape = (:code:`n`)), np.ndarray(shape = (:code:`n`, :code:`shape`)]
"""
if kwargs.get("sigma") is None:
v, w = _eigsh(mat._mul_vector, mat.shape[0],
mat.dtype, k=n, **kwargs)
v, w = _eigsh(mat._mul_vector, mat.shape[0], mat.dtype, k=n, **kwargs)
else:
# Fallback to default solver
v, w = eigsh(mat, k=n, which="SA", **kwargs)
Expand All @@ -34,22 +36,45 @@ def scipy_get_eigen(mat: sp.dia_matrix, n: int, shape: tuple[int], **kwargs) ->
return v, w


def _eigsh(A_OP, n, dtype, k=6, sigma=None, which='SA', v0=None,
ncv=None, maxiter=None, tol=0, return_eigenvectors=True,
):
def _eigsh(
A_OP,
n,
dtype,
k=6,
sigma=None,
which="SA",
v0=None,
ncv=None,
maxiter=None,
tol=0,
return_eigenvectors=True,
):
"""Copied from the scipy sourcecode, removing some overhead.
See https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.linalg.eigsh.html
"""
mode = 1
M_matvec = None
Minv_matvec = None
params = _SymmetricArpackParams(n, k, dtype.char, A_OP, mode,
M_matvec, Minv_matvec, sigma,
ncv, v0, maxiter, which, tol)
params = _SymmetricArpackParams(
n,
k,
dtype.char,
A_OP,
mode,
M_matvec,
Minv_matvec,
sigma,
ncv,
v0,
maxiter,
which,
tol,
)

with ReentrancyLock("Nested calls to eigs/eighs not allowed: "
"ARPACK is not re-entrant"):
with ReentrancyLock(
"Nested calls to eigs/eighs not allowed: ARPACK is not re-entrant"
):
while not params.converged:
params.iterate()

return params.extract(return_eigenvectors)
return params.extract(return_eigenvectors)
2 changes: 1 addition & 1 deletion src/qm_sim/hamiltonian/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
"""

# The spatial Hamiltonian is the default
from .spatial_hamiltonian import SpatialHamiltonian as Hamiltonian
from .spatial_hamiltonian import SpatialHamiltonian
from .spatial_hamiltonian import SpatialHamiltonian as Hamiltonian
Loading

0 comments on commit c4dd608

Please sign in to comment.