342 lines
8.9 KiB
Python
342 lines
8.9 KiB
Python
|
"""Operators and states for 1D cartesian position and momentum.
|
||
|
|
||
|
TODO:
|
||
|
|
||
|
* Add 3D classes to mappings in operatorset.py
|
||
|
|
||
|
"""
|
||
|
|
||
|
from sympy.core.numbers import (I, pi)
|
||
|
from sympy.core.singleton import S
|
||
|
from sympy.functions.elementary.exponential import exp
|
||
|
from sympy.functions.elementary.miscellaneous import sqrt
|
||
|
from sympy.functions.special.delta_functions import DiracDelta
|
||
|
from sympy.sets.sets import Interval
|
||
|
|
||
|
from sympy.physics.quantum.constants import hbar
|
||
|
from sympy.physics.quantum.hilbert import L2
|
||
|
from sympy.physics.quantum.operator import DifferentialOperator, HermitianOperator
|
||
|
from sympy.physics.quantum.state import Ket, Bra, State
|
||
|
|
||
|
__all__ = [
|
||
|
'XOp',
|
||
|
'YOp',
|
||
|
'ZOp',
|
||
|
'PxOp',
|
||
|
'X',
|
||
|
'Y',
|
||
|
'Z',
|
||
|
'Px',
|
||
|
'XKet',
|
||
|
'XBra',
|
||
|
'PxKet',
|
||
|
'PxBra',
|
||
|
'PositionState3D',
|
||
|
'PositionKet3D',
|
||
|
'PositionBra3D'
|
||
|
]
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
# Position operators
|
||
|
#-------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
class XOp(HermitianOperator):
|
||
|
"""1D cartesian position operator."""
|
||
|
|
||
|
@classmethod
|
||
|
def default_args(self):
|
||
|
return ("X",)
|
||
|
|
||
|
@classmethod
|
||
|
def _eval_hilbert_space(self, args):
|
||
|
return L2(Interval(S.NegativeInfinity, S.Infinity))
|
||
|
|
||
|
def _eval_commutator_PxOp(self, other):
|
||
|
return I*hbar
|
||
|
|
||
|
def _apply_operator_XKet(self, ket, **options):
|
||
|
return ket.position*ket
|
||
|
|
||
|
def _apply_operator_PositionKet3D(self, ket, **options):
|
||
|
return ket.position_x*ket
|
||
|
|
||
|
def _represent_PxKet(self, basis, *, index=1, **options):
|
||
|
states = basis._enumerate_state(2, start_index=index)
|
||
|
coord1 = states[0].momentum
|
||
|
coord2 = states[1].momentum
|
||
|
d = DifferentialOperator(coord1)
|
||
|
delta = DiracDelta(coord1 - coord2)
|
||
|
|
||
|
return I*hbar*(d*delta)
|
||
|
|
||
|
|
||
|
class YOp(HermitianOperator):
|
||
|
""" Y cartesian coordinate operator (for 2D or 3D systems) """
|
||
|
|
||
|
@classmethod
|
||
|
def default_args(self):
|
||
|
return ("Y",)
|
||
|
|
||
|
@classmethod
|
||
|
def _eval_hilbert_space(self, args):
|
||
|
return L2(Interval(S.NegativeInfinity, S.Infinity))
|
||
|
|
||
|
def _apply_operator_PositionKet3D(self, ket, **options):
|
||
|
return ket.position_y*ket
|
||
|
|
||
|
|
||
|
class ZOp(HermitianOperator):
|
||
|
""" Z cartesian coordinate operator (for 3D systems) """
|
||
|
|
||
|
@classmethod
|
||
|
def default_args(self):
|
||
|
return ("Z",)
|
||
|
|
||
|
@classmethod
|
||
|
def _eval_hilbert_space(self, args):
|
||
|
return L2(Interval(S.NegativeInfinity, S.Infinity))
|
||
|
|
||
|
def _apply_operator_PositionKet3D(self, ket, **options):
|
||
|
return ket.position_z*ket
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
# Momentum operators
|
||
|
#-------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
class PxOp(HermitianOperator):
|
||
|
"""1D cartesian momentum operator."""
|
||
|
|
||
|
@classmethod
|
||
|
def default_args(self):
|
||
|
return ("Px",)
|
||
|
|
||
|
@classmethod
|
||
|
def _eval_hilbert_space(self, args):
|
||
|
return L2(Interval(S.NegativeInfinity, S.Infinity))
|
||
|
|
||
|
def _apply_operator_PxKet(self, ket, **options):
|
||
|
return ket.momentum*ket
|
||
|
|
||
|
def _represent_XKet(self, basis, *, index=1, **options):
|
||
|
states = basis._enumerate_state(2, start_index=index)
|
||
|
coord1 = states[0].position
|
||
|
coord2 = states[1].position
|
||
|
d = DifferentialOperator(coord1)
|
||
|
delta = DiracDelta(coord1 - coord2)
|
||
|
|
||
|
return -I*hbar*(d*delta)
|
||
|
|
||
|
X = XOp('X')
|
||
|
Y = YOp('Y')
|
||
|
Z = ZOp('Z')
|
||
|
Px = PxOp('Px')
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
# Position eigenstates
|
||
|
#-------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
class XKet(Ket):
|
||
|
"""1D cartesian position eigenket."""
|
||
|
|
||
|
@classmethod
|
||
|
def _operators_to_state(self, op, **options):
|
||
|
return self.__new__(self, *_lowercase_labels(op), **options)
|
||
|
|
||
|
def _state_to_operators(self, op_class, **options):
|
||
|
return op_class.__new__(op_class,
|
||
|
*_uppercase_labels(self), **options)
|
||
|
|
||
|
@classmethod
|
||
|
def default_args(self):
|
||
|
return ("x",)
|
||
|
|
||
|
@classmethod
|
||
|
def dual_class(self):
|
||
|
return XBra
|
||
|
|
||
|
@property
|
||
|
def position(self):
|
||
|
"""The position of the state."""
|
||
|
return self.label[0]
|
||
|
|
||
|
def _enumerate_state(self, num_states, **options):
|
||
|
return _enumerate_continuous_1D(self, num_states, **options)
|
||
|
|
||
|
def _eval_innerproduct_XBra(self, bra, **hints):
|
||
|
return DiracDelta(self.position - bra.position)
|
||
|
|
||
|
def _eval_innerproduct_PxBra(self, bra, **hints):
|
||
|
return exp(-I*self.position*bra.momentum/hbar)/sqrt(2*pi*hbar)
|
||
|
|
||
|
|
||
|
class XBra(Bra):
|
||
|
"""1D cartesian position eigenbra."""
|
||
|
|
||
|
@classmethod
|
||
|
def default_args(self):
|
||
|
return ("x",)
|
||
|
|
||
|
@classmethod
|
||
|
def dual_class(self):
|
||
|
return XKet
|
||
|
|
||
|
@property
|
||
|
def position(self):
|
||
|
"""The position of the state."""
|
||
|
return self.label[0]
|
||
|
|
||
|
|
||
|
class PositionState3D(State):
|
||
|
""" Base class for 3D cartesian position eigenstates """
|
||
|
|
||
|
@classmethod
|
||
|
def _operators_to_state(self, op, **options):
|
||
|
return self.__new__(self, *_lowercase_labels(op), **options)
|
||
|
|
||
|
def _state_to_operators(self, op_class, **options):
|
||
|
return op_class.__new__(op_class,
|
||
|
*_uppercase_labels(self), **options)
|
||
|
|
||
|
@classmethod
|
||
|
def default_args(self):
|
||
|
return ("x", "y", "z")
|
||
|
|
||
|
@property
|
||
|
def position_x(self):
|
||
|
""" The x coordinate of the state """
|
||
|
return self.label[0]
|
||
|
|
||
|
@property
|
||
|
def position_y(self):
|
||
|
""" The y coordinate of the state """
|
||
|
return self.label[1]
|
||
|
|
||
|
@property
|
||
|
def position_z(self):
|
||
|
""" The z coordinate of the state """
|
||
|
return self.label[2]
|
||
|
|
||
|
|
||
|
class PositionKet3D(Ket, PositionState3D):
|
||
|
""" 3D cartesian position eigenket """
|
||
|
|
||
|
def _eval_innerproduct_PositionBra3D(self, bra, **options):
|
||
|
x_diff = self.position_x - bra.position_x
|
||
|
y_diff = self.position_y - bra.position_y
|
||
|
z_diff = self.position_z - bra.position_z
|
||
|
|
||
|
return DiracDelta(x_diff)*DiracDelta(y_diff)*DiracDelta(z_diff)
|
||
|
|
||
|
@classmethod
|
||
|
def dual_class(self):
|
||
|
return PositionBra3D
|
||
|
|
||
|
|
||
|
# XXX: The type:ignore here is because mypy gives Definition of
|
||
|
# "_state_to_operators" in base class "PositionState3D" is incompatible with
|
||
|
# definition in base class "BraBase"
|
||
|
class PositionBra3D(Bra, PositionState3D): # type: ignore
|
||
|
""" 3D cartesian position eigenbra """
|
||
|
|
||
|
@classmethod
|
||
|
def dual_class(self):
|
||
|
return PositionKet3D
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
# Momentum eigenstates
|
||
|
#-------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
class PxKet(Ket):
|
||
|
"""1D cartesian momentum eigenket."""
|
||
|
|
||
|
@classmethod
|
||
|
def _operators_to_state(self, op, **options):
|
||
|
return self.__new__(self, *_lowercase_labels(op), **options)
|
||
|
|
||
|
def _state_to_operators(self, op_class, **options):
|
||
|
return op_class.__new__(op_class,
|
||
|
*_uppercase_labels(self), **options)
|
||
|
|
||
|
@classmethod
|
||
|
def default_args(self):
|
||
|
return ("px",)
|
||
|
|
||
|
@classmethod
|
||
|
def dual_class(self):
|
||
|
return PxBra
|
||
|
|
||
|
@property
|
||
|
def momentum(self):
|
||
|
"""The momentum of the state."""
|
||
|
return self.label[0]
|
||
|
|
||
|
def _enumerate_state(self, *args, **options):
|
||
|
return _enumerate_continuous_1D(self, *args, **options)
|
||
|
|
||
|
def _eval_innerproduct_XBra(self, bra, **hints):
|
||
|
return exp(I*self.momentum*bra.position/hbar)/sqrt(2*pi*hbar)
|
||
|
|
||
|
def _eval_innerproduct_PxBra(self, bra, **hints):
|
||
|
return DiracDelta(self.momentum - bra.momentum)
|
||
|
|
||
|
|
||
|
class PxBra(Bra):
|
||
|
"""1D cartesian momentum eigenbra."""
|
||
|
|
||
|
@classmethod
|
||
|
def default_args(self):
|
||
|
return ("px",)
|
||
|
|
||
|
@classmethod
|
||
|
def dual_class(self):
|
||
|
return PxKet
|
||
|
|
||
|
@property
|
||
|
def momentum(self):
|
||
|
"""The momentum of the state."""
|
||
|
return self.label[0]
|
||
|
|
||
|
#-------------------------------------------------------------------------
|
||
|
# Global helper functions
|
||
|
#-------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
def _enumerate_continuous_1D(*args, **options):
|
||
|
state = args[0]
|
||
|
num_states = args[1]
|
||
|
state_class = state.__class__
|
||
|
index_list = options.pop('index_list', [])
|
||
|
|
||
|
if len(index_list) == 0:
|
||
|
start_index = options.pop('start_index', 1)
|
||
|
index_list = list(range(start_index, start_index + num_states))
|
||
|
|
||
|
enum_states = [0 for i in range(len(index_list))]
|
||
|
|
||
|
for i, ind in enumerate(index_list):
|
||
|
label = state.args[0]
|
||
|
enum_states[i] = state_class(str(label) + "_" + str(ind), **options)
|
||
|
|
||
|
return enum_states
|
||
|
|
||
|
|
||
|
def _lowercase_labels(ops):
|
||
|
if not isinstance(ops, set):
|
||
|
ops = [ops]
|
||
|
|
||
|
return [str(arg.label[0]).lower() for arg in ops]
|
||
|
|
||
|
|
||
|
def _uppercase_labels(ops):
|
||
|
if not isinstance(ops, set):
|
||
|
ops = [ops]
|
||
|
|
||
|
new_args = [str(arg.label[0])[0].upper() +
|
||
|
str(arg.label[0])[1:] for arg in ops]
|
||
|
|
||
|
return new_args
|