Source code for pytdscf.basis.boson

"""
Boson basis module
"""

import numpy as np
from numpy.typing import NDArray


[docs] class Boson: """ Boson basis class Args: nstate (int): number of states """ nstate: int names: list[str] def __init__(self, nstate: int) -> None: self.nstate = nstate
[docs] def get_creation_matrix(self, margin: int = 0) -> NDArray[np.float64]: r""" Returns the creation matrix for the boson basis .. math:: b^\dagger |n> = \sqrt{n+1} |n+1> Example: >>> boson = Boson(3) >>> boson.get_creation_matrix() array([[0., 0., 0.], [1., 0., 0.], [1.41421356, 0., 0.]]) >>> state = np.array([[1.0], [1.0], [0.0]]) >>> np.allclose(boson.get_creation_matrix() @ state, np.array([[0.0], [1.0], [math.sqrt(2)]])) True """ return self.get_annihilation_matrix(margin=margin).T
[docs] def get_annihilation_matrix(self, margin: int = 0) -> NDArray[np.float64]: r""" Returns the annihilation matrix for the boson basis .. math:: b |n> = \sqrt{n} |n-1> Example: >>> exciton = Boson(4) >>> exciton.get_annihilation_matrix() array([[0., 1., 0., 0.], [0., 0., 1.41421356, 0.], [0., 0., 0., 1.73205081], [0., 0., 0., 0.]]) >>> state = np.array([[1.0], [1.0], [1.0], [0.0]]) >>> np.allclose(exciton.get_annihilation_matrix() @ state, np.array([[0.0], [1.0], [math.sqrt(2)], [math.sqrt(3)]])) True """ # mat = np.zeros((self.nstate, self.nstate), dtype=np.float64) # for i in range(self.nstate - 1): # mat[i, i+1] = np.sqrt(i + 1) mat = np.diag(np.sqrt(np.arange(1, self.nstate + margin)), 1) return mat
[docs] def get_number_matrix(self) -> NDArray[np.float64]: r""" Returns the number matrix for the boson basis .. math:: b^\dagger b |n> = n |n> Example: >>> boson = Boson(3) >>> boson.get_number_matrix() array([[0., 0., 0.], [0., 1., 0.], [0., 0., 2.]]) >>> state = np.array([[1.0], [1.0], [0.0]]) >>> np.allclose(boson.get_number_matrix() @ state, np.array([[0.0], [1.0], [0.0]])) True """ mat = np.diag(np.arange(self.nstate)) return mat
[docs] def get_q_matrix(self, margin: int = 0) -> NDArray[np.float64]: r""" Returns the q matrix for the boson basis q = 1/sqrt(2) (b + b^\dagger) """ return ( 1 / np.sqrt(2) * ( self.get_creation_matrix(margin=margin) + self.get_annihilation_matrix(margin=margin) ) )
[docs] def get_p_matrix(self, margin: int = 0) -> NDArray[np.complex128]: r""" Returns the p matrix for the boson basis .. math:: p = 1/\sqrt{2} i (b - b^\dagger) = i/\sqrt{2} (b^\dagger - b) """ return ( 1 / np.sqrt(2) * 1j * ( self.get_creation_matrix(margin=margin) - self.get_annihilation_matrix(margin=margin) ) )
[docs] def get_q2_matrix(self) -> NDArray[np.float64]: r""" Returns the p^2 matrix for the boson basis .. math:: p^2 = 1/2 (b^\dagger b + b b^\dagger + b^\dagger ^2 + b^2) """ b = self.get_annihilation_matrix(margin=1) bd = self.get_creation_matrix(margin=1) bd_b = bd + b return 1 / 2 * (bd_b @ bd_b)[:-1, :-1]
[docs] def get_p2_matrix(self) -> NDArray[np.float64]: r""" Returns the p^2 matrix for the boson basis .. math:: p^2 = -1/2 (b^\dagger b + b b^\dagger - b^\dagger ^2 - b^2) """ b = self.get_annihilation_matrix(margin=1) bd = self.get_creation_matrix(margin=1) bd_b = bd - b return -1 / 2 * (bd_b @ bd_b)[:-1, :-1]
@property def nprim(self) -> int: return self.nstate def __len__(self) -> int: return self.nstate
if __name__ == "__main__": boson = Boson(3) state0 = np.array([[1.0], [1.0], [0.0]]) state1 = np.array([[0.0], [1.0], [np.sqrt(2)]]) state2 = np.array([[1.0], [0.0], [0.0]]) state3 = np.array([[0.0], [0.0], [np.sqrt(2)]]) state4 = np.array([[1.0], [2.0], [0.0]]) cmat = boson.get_creation_matrix() amat = boson.get_annihilation_matrix() nmat = boson.get_number_matrix() np.testing.assert_allclose(cmat @ amat, nmat) for state, mat, ans in zip( [state0, state0, state1, state1], [cmat, amat, cmat, amat], [state1, state2, state3, state4], strict=False, ): np.testing.assert_allclose(mat @ state, ans) boson = Boson(5) cmat = boson.get_creation_matrix() amat = boson.get_annihilation_matrix() nmat = boson.get_number_matrix() pmat = boson.get_p_matrix() qmat = boson.get_q_matrix() np.testing.assert_allclose(1 / np.sqrt(2) * (qmat + 1j * pmat), amat) np.testing.assert_allclose(1 / np.sqrt(2) * (qmat - 1j * pmat), cmat) pmat = boson.get_p_matrix(margin=1) qmat = boson.get_q_matrix(margin=1) # [p,q] = -i np.testing.assert_allclose( (pmat @ qmat)[:-1, :-1] - (qmat @ pmat)[:-1, :-1], -1.0j * np.eye(boson.nstate), ) p2 = boson.get_p2_matrix() q2 = boson.get_q2_matrix() np.testing.assert_allclose(p2, (pmat @ pmat)[:-1, :-1]) np.testing.assert_allclose(q2, (qmat @ qmat)[:-1, :-1]) np.testing.assert_allclose( 1 / 2 * (p2 + q2), nmat + 1 / 2 * np.eye(boson.nstate) )