# Copyright 2014 M. A. Zentile, J. Keaveney, L. Weller, D. Whiting, # C. S. Adams and I. G. Hughes. # Updated 2017 JK # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Calculates the atomic Hamiltonian for a given Isotope and magnetic field Modules called: FundamentalConstants -- fundamental physical constants from CODATA AtomConstants -- All isotope and D-line specific constants sz_lsi -- Last updated 2018-07-04 MAZ """ # py 2.7 compatibility from __future__ import (division, print_function, absolute_import) # Calulates the ground state manifold and the excited state manifold. # Is called by spectra.py from scipy.linalg import eig, eigh from numpy import pi, append, transpose, identity from AtomConstants import * from FundamentalConstants import * from sz_lsi import sz, lz, Iz from fs_hfs import Hfs,Hhfs,Bbhfs class Hamiltonian(object): """Functions to create the atomic hamiltonian.""" def __init__(self, Isotope, Trans, gL, Bfield): """Ground and excited state Hamiltonian for an isotope""" if Isotope=='Rb87': atom = Rb87 elif Isotope=='Rb85': atom = Rb85 elif Isotope=='Cs': atom = Cs elif Isotope=='K39': atom = K39 elif Isotope=='K40': atom = K40 elif Isotope=='K41': atom = K41 elif Isotope=='Na': atom = Na elif Isotope=='IdealAtom': atom = IdealAtom transition = IdealD1Transition atom_transition = Ideal_D1 self.atom = atom if (Trans=='D1') and (Isotope=='Rb85'): transition = RbD1Transition atom_transition = Rb85_D1 elif (Trans=='D2') and (Isotope=='Rb85'): transition = RbD2Transition atom_transition = Rb85_D2 elif (Trans=='D1') and (Isotope=='Rb87'): transition = RbD1Transition atom_transition = Rb87_D1 elif (Trans=='D2') and (Isotope=='Rb87'): transition = RbD2Transition atom_transition = Rb87_D2 elif (Trans=='D1') and (Isotope=='Cs'): transition = CsD1Transition atom_transition = Cs_D1 elif (Trans=='D2') and (Isotope=='Cs'): transition = CsD2Transition atom_transition = Cs_D2 elif (Trans=='D1') and (Isotope=='Na'): transition = NaD1Transition atom_transition = Na_D1 elif (Trans=='D2') and (Isotope=='Na'): transition = NaD2Transition atom_transition = Na_D2 elif (Trans=='D1') and (Isotope=='K39'): transition = KD1Transition atom_transition = K39_D1 elif (Trans=='D2') and (Isotope=='K39'): transition = KD2Transition atom_transition = K39_D2 elif (Trans=='D1') and (Isotope=='K40'): transition = KD1Transition atom_transition = K40_D1 elif (Trans=='D2') and (Isotope=='K40'): transition = KD2Transition atom_transition = K40_D2 elif (Trans=='D1') and (Isotope=='K41'): transition = KD1Transition atom_transition = K41_D1 elif (Trans=='D2') and (Isotope=='K41'): transition = KD2Transition atom_transition = K41_D2 if Bfield == 0.0: Bfield += 1e-5 # avoid degeneracy problem..? #Useful quantities to return self.ds=int((2*S+1)*(2*atom.I+1)) #Dimension of S-term matrix self.dp=int(3*(2*S+1)*(2*atom.I+1)) #Dimension of P-term matrix self.groundManifold, self.groundEnergies = self.groundStateManifold(atom.gI,atom.I,atom.As, atom_transition.IsotopeShift,Bfield) self.excitedManifold, self.excitedEnergies = self.excitedStateManifold(gL,atom.gI,atom.I, atom_transition.Ap,atom_transition.Bp,Bfield) def groundStateManifold(self,gI,I,A_hyp_coeff,IsotopeShift,Bfield): """Function to produce the ground state manifold""" ds = int((2*S+1)*(2*I+1)) # total dimension of matrix #print 'Matrix dim:', ds As = A_hyp_coeff # Add the S-term hyperfine interaction S_StateHamiltonian = As*Hhfs(0.0,S,I)+IsotopeShift*identity(ds) Ez = muB*Bfield*1.e-4/(hbar*2.0*pi*1.0e6) S_StateHamiltonian += Ez*(gs*sz(0.0,S,I)+gI*Iz(0.0,S,I)) # Add Zeeman EigenSystem = eigh(S_StateHamiltonian) EigenValues = EigenSystem[0].real EigenVectors = EigenSystem[1] stateManifold = append([EigenValues],EigenVectors,axis=0) sortedManifold = sorted(transpose(stateManifold),key=(lambda i:i[0])) return sortedManifold, EigenValues def excitedStateManifold(self,gL,gI,I,A_hyp_coeff,B_hyp_coeff,Bfield): """Function to produce the excited state manifold""" dp = int(3*(2*S+1)*(2*I+1)) # total dimension of matrix # The actual value of FS is unimportant. FS = self.atom.FS # Fine structure splitting Ap = A_hyp_coeff Bp = B_hyp_coeff # Add P-term fine and hyperfine interactions if Bp==0.0: P_StateHamiltonian=FS*Hfs(1.0,S,I)+FS*identity(dp)+Ap*Hhfs(1.0,S,I) if Bp!=0.0: P_StateHamiltonian=FS*Hfs(1.0,S,I)-(FS/2.0)*identity(dp)+Ap*Hhfs(1.0,S,I) P_StateHamiltonian+=Bp*Bbhfs(1.0,S,I) # add p state quadrupole E=muB*(Bfield*1.0e-4)/(hbar*2.0*pi*1.0e6) # Add magnetic interaction P_StateHamiltonian+=E*(gL*lz(1.0,S,I)+gs*sz(1.0,S,I)+gI*Iz(1.0,S,I)) ep=eigh(P_StateHamiltonian) EigenValues=ep[0].real EigenVectors=ep[1] stateManifold=append([EigenValues],EigenVectors,axis=0) sortedManifold=sorted(transpose(stateManifold),key=(lambda i:i[0])) return sortedManifold, EigenValues