{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE CPP #-}
module Physics.Learn.BlochSphere
( VisObj
, toPos
, ketToPos
, staticBlochSphere
, displayStaticState
, animatedBlochSphere
, simulateBlochSphere
, simulateBlochSphereK
, stateProp
, statePropK
, evolutionBlochSphere
, evolutionBlochSphereK
, hamRabi
)
where
import qualified Physics.Learn.QuantumMat as M
import qualified Physics.Learn.Ket as K
import Physics.Learn.Ket
( Ket
, Operator
, (<>)
, dagger
)
import Numeric.LinearAlgebra
( Vector
, Matrix
, C
, iC
, (!)
, (><)
, scale
, size
)
import Data.Complex
( Complex(..)
, conjugate
, realPart
, imagPart
)
import Physics.Learn
( Position
, v3FromPos
, cart
)
import SpatialMath
( Euler(..)
)
import Vis
( VisObject(..)
, Flavour(..)
, Options(..)
, Camera0(..)
, defaultOpts
, display
, simulate
, blue
, red
)
#if MIN_VERSION_base(4,11,0)
import Prelude hiding ((<>))
#endif
type VisObj = VisObject Double
toPos :: Vector C -> Position
toPos v
= if size v /= 2
then error "toPos only for size 2 vectors"
else let z1 = v ! 0
z2 = v ! 1
in cart (2 * realPart (conjugate z1 * z2))
(2 * imagPart (conjugate z1 * z2))
(realPart (conjugate z1 * z1 - conjugate z2 * z2))
ketToPos :: Ket -> Position
ketToPos psi
= if K.dim psi /= 2
then error "ketToPos only for qubit kets"
else let z1 = dagger K.zp <> psi
z2 = dagger K.zm <> psi
in cart (2 * realPart (conjugate z1 * z2))
(2 * imagPart (conjugate z1 * z2))
(realPart (conjugate z1 * z1 - conjugate z2 * z2))
staticBlochSphere :: Position -> VisObj
staticBlochSphere r
= RotEulerDeg (Euler 270 0 0) $ RotEulerDeg (Euler 0 180 0) $
VisObjects [ Sphere 1 Wireframe blue
, Trans (v3FromPos r) (Sphere 0.05 Solid red)
]
displayStaticBlochSphere :: Position -> IO ()
displayStaticBlochSphere r
= display myOptions (staticBlochSphere r)
displayStaticState :: Vector C -> IO ()
displayStaticState = displayStaticBlochSphere . toPos
animatedBlochSphere :: (Double -> Position) -> (Float -> VisObj)
animatedBlochSphere f
= staticBlochSphere . f . realToFrac
simulateBlochSphere :: Double -> Vector C -> (Float -> (Float,Vector C) -> (Float,Vector C)) -> IO ()
simulateBlochSphere sampleRate initial statePropFunc
= simulate myOptions sampleRate (0,initial) (staticBlochSphere . toPos . snd) statePropFunc
simulateBlochSphereK :: Double -> Ket -> (Float -> (Float,Ket) -> (Float,Ket)) -> IO ()
simulateBlochSphereK sampleRate initial statePropFuncK
= simulate myOptions sampleRate (0,initial) (staticBlochSphere . ketToPos . snd) statePropFuncK
stateProp :: (Double -> Matrix C) -> Float -> (Float,Vector C) -> (Float,Vector C)
stateProp ham tNew (tOld,v)
= (tNew, M.timeEv (realToFrac dt) (ham tMid) v)
where
dt = tNew - tOld
tMid = realToFrac $ (tNew + tOld) / 2
statePropK :: (Double -> Operator) -> Float -> (Float,Ket) -> (Float,Ket)
statePropK ham tNew (tOld,psi)
= (tNew, K.timeEv (realToFrac dt) (ham tMid) psi)
where
dt = tNew - tOld
tMid = realToFrac $ (tNew + tOld) / 2
evolutionBlochSphere :: Vector C -> (Double -> Matrix C) -> IO ()
evolutionBlochSphere psi0 ham
= simulateBlochSphere 0.01 psi0 (stateProp ham)
evolutionBlochSphereK :: Ket -> (Double -> Operator) -> IO ()
evolutionBlochSphereK psi0 ham
= simulateBlochSphereK 0.01 psi0 (statePropK ham)
myOptions :: Options
myOptions = defaultOpts {optWindowName = "Bloch Sphere"
,optInitialCamera = Just (Camera0 75 20 4)}
hamRabi :: Double -> Double -> Double -> Double -> Matrix C
hamRabi omega0 omegaR omega t
= let h11 = omega0 :+ 0
h12 = (omegaR :+ 0) * exp (-iC * ((omega * t) :+ 0))
in scale (1/2) $ (2><2) [h11, h12, (conjugate h12), (-h11)]