GithubHelp home page GithubHelp logo

dylanljones / lattpy Goto Github PK

View Code? Open in Web Editor NEW
39.0 1.0 11.0 1.48 MB

Simple and efficient Python package for modeling d-dimensional Bravais lattices in solid state physics.

Home Page: https://lattpy.readthedocs.io/en/stable/

License: MIT License

Python 100.00%
physics crystal lattice bravais bravais-lattice python high-dimensional neighbors solid-state-physics computational-physics

lattpy's Introduction

LattPy - Simple Lattice Modeling in Python

Python Version Version Status Downloads MIT License Code style: black LGTM Grade

โš ๏ธ WARNING: This project is still in development and might change significantly in the future!

LattPy is a simple and efficient Python package for modeling Bravais lattices and constructing (finite) lattice structures in any dimension. It provides an easy interface for constructing lattice structures by simplifying the configuration of the unit cell and the neighbor connections - making it possible to construct complex models in just a few lines of code and without the headache of adding neighbor connections manually. You will save time and mental energy for more important matters.

Master Test Codecov Read the Docs
Dev Test Codecov Read the Docs

๐Ÿ”ง Installation

LattPy is available on PyPI:

pip install lattpy

Alternatively, it can be installed via GitHub

pip install git+https://github.com/dylanljones/lattpy.git@VERSION

where VERSION is a release or tag. The project can also be cloned/forked and installed via

python setup.py install

๐Ÿ“– Documentation

Read the documentation on ReadTheDocs!

๐Ÿš€ Quick-Start

See the tutorial for more information and examples.

Features:

  • Basis transformations
  • Configurable unit cell
  • Easy neighbor configuration
  • General lattice structures
  • Finite lattice models in world or lattice coordinates
  • Periodic boundary conditions along any axis

Configuration

A new instance of a lattice model is initialized using the unit-vectors of the Bravais lattice. After the initialization the atoms of the unit-cell need to be added. To finish the configuration the connections between the atoms in the lattice have to be set. This can either be done for each atom-pair individually by calling add_connection or for all possible pairs at once by callling add_connections. The argument is the number of unique distances of neighbors. Setting a value of 1 will compute only the nearest neighbors of the atom.

import numpy as np
from lattpy import Lattice

latt = Lattice(np.eye(2))                 # Construct a Bravais lattice with square unit-vectors
latt.add_atom(pos=[0.0, 0.0])             # Add an Atom to the unit cell of the lattice
latt.add_connections(1)                   # Set the maximum number of distances between all atoms

latt = Lattice(np.eye(2))                 # Construct a Bravais lattice with square unit-vectors
latt.add_atom(pos=[0.0, 0.0], atom="A")   # Add an Atom to the unit cell of the lattice
latt.add_atom(pos=[0.5, 0.5], atom="B")   # Add an Atom to the unit cell of the lattice
latt.add_connection("A", "A", 1)          # Set the max number of distances between A and A
latt.add_connection("A", "B", 1)          # Set the max number of distances between A and B
latt.add_connection("B", "B", 1)          # Set the max number of distances between B and B
latt.analyze()

Configuring all connections using the add_connections-method will call the analyze-method directly. Otherwise this has to be called at the end of the lattice setup or by using analyze=True in the last call of add_connection. This will compute the number of neighbors, their distances and their positions for each atom in the unitcell.

To speed up the configuration prefabs of common lattices are included. The previous lattice can also be created with

from lattpy import simple_square

latt = simple_square(a=1.0, neighbors=1)  # Initializes a square lattice with one atom in the unit-cell

So far only the lattice structure has been configured. To actually construct a (finite) model of the lattice the model has to be built:

latt.build(shape=(5, 3))

This will compute the indices and neighbors of all sites in the given shape and store the data.

After building the lattice periodic boundary conditions can be set along one or multiple axes:

latt.set_periodic(axis=0)

To view the built lattice the plot-method can be used:

import matplotlib.pyplot as plt

latt.plot()
plt.show()

General lattice attributes

After configuring the lattice the attributes are available. Even without building a (finite) lattice structure all attributes can be computed on the fly for a given lattice vector, consisting of the translation vector n and the atom index alpha. For computing the (translated) atom positions the get_position method is used. Also, the neighbors and the vectors to these neighbors can be calculated. The dist_idx-parameter specifies the distance of the neighbors (0 for nearest neighbors, 1 for next nearest neighbors, ...):

from lattpy import simple_square

latt = simple_square()

# Get position of atom alpha=0 in the translated unit-cell
positions = latt.get_position(n=[0, 0], alpha=0)

# Get lattice-indices of the nearest neighbors of atom alpha=0 in the translated unit-cell
neighbor_indices = latt.get_neighbors(n=[0, 0], alpha=0, distidx=0)

# Get vectors to the nearest neighbors of atom alpha=0 in the translated unit-cell
neighbor_vectors = latt.get_neighbor_vectors(alpha=0, distidx=0)

Also, the reciprocal lattice vectors can be computed

rvecs = latt.reciprocal_vectors()

or used to construct the reciprocal lattice:

rlatt = latt.reciprocal_lattice()

The 1. Brillouin zone is the Wigner-Seitz cell of the reciprocal lattice:

bz = rlatt.wigner_seitz_cell()

The 1.BZ can also be obtained by calling the explicit method of the direct lattice:

bz = latt.brillouin_zone()

Finite lattice data

If the lattice has been built the needed data is cached. The lattice sites of the structure then can be accessed by a simple index i. The syntax is the same as before, just without the get_ prefix:

latt.build((5, 2))
i = 2

# Get position of the atom with index i=2
positions = latt.position(i)

# Get the atom indices of the nearest neighbors of the atom with index i=2
neighbor_indices = latt.neighbors(i, distidx=0)

# the nearest neighbors can also be found by calling (equivalent to dist_idx=0)
neighbor_indices = latt.nearest_neighbors(i)

Data map

The lattice model makes it is easy to construct the (tight-binding) Hamiltonian of a non-interacting model:

import numpy as np
from lattpy import simple_chain

# Initializes a 1D lattice chain with a length of 5 atoms.
latt = simple_chain(a=1.0)
latt.build(shape=4)
n = latt.num_sites

# Construct the non-interacting (kinetic) Hamiltonian-matrix
eps, t = 0., 1.
ham = np.zeros((n, n))
for i in range(n):
    ham[i, i] = eps
    for j in latt.nearest_neighbors(i):
        ham[i, j] = t

Since we loop over all sites of the lattice the construction of the hamiltonian is slow. An alternative way of mapping the lattice data to the hamiltonian is using the DataMap object returned by the map() method of the lattice data. This stores the atom-types, neighbor-pairs and corresponding distances of the lattice sites. Using the built-in masks the construction of the hamiltonian-data can be vectorized:

from scipy import sparse

# Vectorized construction of the hamiltonian
eps, t = 0., 1.
dmap = latt.data.map()               # Build datamap
values = np.zeros(dmap.size)         # Initialize array for data of H
values[dmap.onsite(alpha=0)] = eps   # Map onsite-energies to array
values[dmap.hopping(distidx=0)] = t  # Map hopping-energies to array

# The indices and data array can be used to construct a sparse matrix
ham_s = sparse.csr_matrix((values, dmap.indices))
ham = ham_s.toarray()

Both construction methods will create the following Hamiltonian-matrix:

[[0. 1. 0. 0. 0.]
 [1. 0. 1. 0. 0.]
 [0. 1. 0. 1. 0.]
 [0. 0. 1. 0. 1.]
 [0. 0. 0. 1. 0.]]

๐Ÿ”ฅ Performance

Even though lattpy is written in pure python, it achieves high performance and a low memory footprint by making heavy use of numpy's vectorized operations and scipy's cKDTree. As an example the build times and memory usage in the build process for different lattices are shown in the following plots:

Build time Build memory

Note that the overhead of the multi-thread neighbor search results in a slight increase of the build time for small systems. By using num_jobs=1 in the build-method this overhead can be eliminated for small systems. By passing num_jobs=-1 all cores of the system are used.

๐Ÿ’ป Development

See the CHANGELOG for the recent changes of the project.

If you encounter an issue or want to contribute to pyrekordbox, please feel free to get in touch, create an issue or open a pull request! A guide for contributing to lattpy and the commit-message style can be found in CONTRIBUTING

lattpy's People

Contributors

dylanljones avatar lgtm-migrator avatar pre-commit-ci[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

lattpy's Issues

Wrong neighbors if we set 2nd connections

Describe the bug
See below, site 5 is found for site 3 as nearest neighbor, but site 3 is not found for site 5 as nearest neighbor,

To Reproduce
Steps to reproduce the behavior:

import lattpy as lp
import matplotlib.pyplot as plt

latt = lp.Lattice.hexagonal()
latt.add_atom()
latt.add_connections(2)

latt.build((3-0.1, 3-0.1, ), primitive=True)
latt.set_periodic([1, ], primitive=True)

latt.plot(show_indices=True)
plt.show()
print(latt.neighbors(3,distidx=0))
print(latt.neighbors(5,distidx=0))

The resulting error is:

[1 0 4 6 5 8]
[7 4 2 8 0]

Expected behavior
[1 0 4 6 5 8]
[7 4 2 8 0 3]

Environment

  • lattpy version: 0.7.7
  • OS and Python version: MacOs, python3.8

Additional context
Add any other context about the problem here.

Periodic boundary conditions misses some neighbors for non-square lattices

Describe the bug
Setting periodic boundary conditions misses neighbors for some lattices.

To Reproduce
See, for example, the hexagonal lattice

import lattpy as lp
import matplotlib.pyplot as plt

latt = lp.Lattice.hexagonal()
latt.add_atom()
latt.add_connections()

latt.build((3, 3, ), primitive=True)
latt.set_periodic([0, ], primitive=True)

latt.plot()
plt.show()

The top (12) and bottom (3) sites are each missing one neighbor (site 1 and 14, respectively)

Figure_1

Environment

  • lattpy version: 0.7.4
  • OS and Python version: All

Periodic boundary conditions fails for small models with d>1

Describe the bug
Setting periodic boundary conditions for small lattices in higher dimensions fails due a broadcasting error and raises a ValueError.

To Reproduce
Steps to reproduce the behavior:

import lattpy as lp

latt = lp.finite_hypercubic((2, 2), periodic=True)

The resulting error is:

Traceback (most recent call last):
File "D:\Dropbox\Dev\Physics\lattpy\issue.py", line 16, in <module>
  main()
File "D:\Dropbox\Dev\Physics\lattpy\issue.py", line 12, in main
  latt = lp.finite_hypercubic((2, 2), periodic=True)
File "D:\Dropbox\Dev\Physics\lattpy\lattpy\__init__.py", line 451, in finite_hypercubic
  latt.build(s, primitive=primitive, periodic=periodic)
File "D:\Dropbox\Dev\Physics\lattpy\lattpy\lattice.py", line 431, in build
  self.set_periodic(periodic, primitive)
File "D:\Dropbox\Dev\Physics\lattpy\lattpy\lattice.py", line 620, in set_periodic
  self.data.set_periodic(pidx, pdists, pnvecs, paxs)
File "D:\Dropbox\Dev\Physics\lattpy\lattpy\data.py", line 467, in set_periodic
  self.neighbors[i, i0:i1] = pidx
ValueError: could not broadcast input array from shape (2,) into shape (1,)

Expected behavior
Set periodic boundary conditions if possible. In the example above this is not necessary since the sites are already neighbors.

Environment

  • lattpy version: 0.7.4
  • OS and Python version: All

Suggestions for contribution

I just discovered this package and used it to generate some graphics for my masters thesis (graphene, but with the basis rotated in comparison to the predefined one to be in line with my definition) . It absolutely saved me a lot of work doing things myself, but I struggled a bit with the documentation, so I would like to contribute to that a bit.

I can imagine adding the following:

  • My code as an example somewhere, to illustrate how to create lattice and BZ graphics
  • API Documentation where its missing
  • Typehints

Also, I couldn't really figure out how to use the things provided in lattpy.disptools, so I did plotting of bands myself. If you have any hints, I can also add that to the documentation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.