learn-physics 0.6.2 → 0.6.3
raw patch · 11 files changed
+1044/−83 lines, 11 filesdep +not-glossdep +spatial-mathdep ~basenew-component:exe:learn-physics-BCircularLoopnew-component:exe:learn-physics-LorentzForceSimulationnew-component:exe:learn-physics-NMRnew-component:exe:learn-physics-PlaneWavenew-component:exe:learn-physics-eFieldLine3D
Dependencies added: not-gloss, spatial-math
Dependency ranges changed: base
Files
- examples/src/BCircularLoop.hs +30/−0
- examples/src/LorentzForceSimulation.hs +64/−0
- examples/src/NMR.hs +16/−0
- examples/src/PlaneWave.hs +48/−0
- examples/src/eFieldLine3D.hs +48/−0
- learn-physics.cabal +48/−47
- src/Physics/Learn.hs +14/−14
- src/Physics/Learn/BlochSphere.hs +226/−0
- src/Physics/Learn/Schrodinger1D.hs +415/−0
- src/Physics/Learn/SimpleVec.hs +9/−22
- src/Physics/Learn/Visual/VisTools.hs +126/−0
+ examples/src/BCircularLoop.hs view
@@ -0,0 +1,30 @@+{-# OPTIONS_GHC -Wall #-}++module Main where++import Physics.Learn+import Vis++loopCurve :: Curve+loopCurve = Curve (\phi -> cyl 1 phi 0) 0 (2*pi)++loop :: CurrentDistribution+loop = LineCurrent 20 loopCurve++samplePoints :: [Position]+samplePoints = [cyl s phi z |+ s <- [0.25,0.75..1.75]+ , phi <- [pi/6,pi/2..2*pi]+ , z <- [-1.5,-1..1.5]]++arrows :: VisObject Double+arrows = displayVectorField blue 5e-5 samplePoints (bField loop)++drawFun :: VisObject Double+drawFun = VisObjects [curveObject red loopCurve, arrows]++myOptions :: Options+myOptions = defaultOpts {optWindowName = "Magnetic Field from a Current Loop"}++main :: IO ()+main = display myOptions drawFun
+ examples/src/LorentzForceSimulation.hs view
@@ -0,0 +1,64 @@+module Main where++import Physics.Learn+import Vis+import SpatialMath+ ( Euler(..)+ )++drawFunction :: SimpleState -> VisObject Double+drawFunction (_t,r,_v)+ = RotEulerDeg (Euler 270 0 0) $ RotEulerDeg (Euler 0 180 0) $+ VisObjects [ Axes (0.5, 15)+ , Trans (v3FromPos r) (Sphere 0.1 Solid red)+ ]++statePropagationFunction :: Float -> SimpleState -> SimpleState+statePropagationFunction t' (t,r,v) = rungeKutta4 newton2 (realToFrac t' - t) (t,r,v)++-- Newton's Second Law+newton2 :: SimpleState -> Diff SimpleState+newton2 (t,r,v) = (1,v,force (t,r,v) ^/ m)++-- Lorentz Force Law+force :: SimpleState -> Vec+force (_t,r,v) = q *^ (electricField r ^+^ v >< magneticField r)++myOptions :: Options+myOptions = defaultOpts {optWindowName = "Particle Experiencing Electromagnetic Force"}++main :: IO ()+main = simulate+ myOptions+ 0.01+ (0,initialPosition,initialVelocity)+ drawFunction+ statePropagationFunction++-- particle mass+m :: Double+m = 1++-- particle charge+q :: Double+q = 1++-- Electric Field+electricField :: VectorField+electricField r = vec 0 2 0+ where+ (x,y,z) = cartesianCoordinates r++-- Magnetic Field+magneticField :: VectorField+magneticField r = vec 0 0 4+ where+ (x,y,z) = cartesianCoordinates r++-- Initial displacement+initialPosition :: Position+initialPosition = cart 0 0 0++-- Initial velocity+initialVelocity :: Vec+initialVelocity = vec 0 0 0
+ examples/src/NMR.hs view
@@ -0,0 +1,16 @@+{-# OPTIONS_GHC -Wall #-}++-- ^ Nuclear Magnetic Resonance on the Bloch Sphere++module Main where++import Physics.Learn.QuantumMat+ ( zm+ )+import Physics.Learn.BlochSphere+ ( hamRabi+ , evolutionBlochSphere+ )++main :: IO ()+main = evolutionBlochSphere zm (hamRabi 10 1 10)
+ examples/src/PlaneWave.hs view
@@ -0,0 +1,48 @@+{-# OPTIONS_GHC -Wall #-}++module Main where++import Vis+ ( animate+ , VisObject(..)+ , red+ , blue+ , Options(..)+ , defaultOpts+ )+import Physics.Learn.CarrotVec+ ( vec+ )+import Physics.Learn+ ( Position+ , VectorField+ , displayVectorField+ , cart+ , cartesianCoordinates+ )++samplePoints :: [Position]+samplePoints = [cart x y z | x <- [-2,0,2], y <- [-2,0,2], z <- [-4,-3.6..4]]++drawFun :: Float -> VisObject Double+drawFun time = VisObjects [displayVectorField blue 1 samplePoints (eField t)+ ,displayVectorField red 1 samplePoints (bField t)+ ]+ where+ t = realToFrac time++eField :: Double -> VectorField+eField t r = vec (cos (z - t)) 0 0+ where+ (_,_,z) = cartesianCoordinates r++bField :: Double -> VectorField+bField t r = vec 0 (cos (z - t)) 0+ where+ (_,_,z) = cartesianCoordinates r++myOptions :: Options+myOptions = defaultOpts {optWindowName = "Plane Wave"}++main :: IO ()+main = animate myOptions drawFun
+ examples/src/eFieldLine3D.hs view
@@ -0,0 +1,48 @@+{-# OPTIONS_GHC -Wall #-}++module Main where++import Vis+ ( display+ , VisObject(..)+ , red+ , blue+ , Options(..)+ , defaultOpts+ )+import Physics.Learn.Visual.VisTools+ ( curveObject+ , displayVectorField+ )+import Physics.Learn.Position+ ( Position+ , cart+ )+import Physics.Learn.Curve+ ( Curve(..)+ )+import Physics.Learn.Charge+ ( ChargeDistribution(..)+ , eField+ )++curve1 :: Curve+curve1 = Curve (\t -> cart t 0 0) (-4) 4++lineCharge :: ChargeDistribution+lineCharge = LineCharge (const 1e-9) curve1++samplePoints :: [Position]+samplePoints = [cart x y z | x <- [-8,-6..8], y <- [-4,-2..4], z <- [-4,-2..4], abs y + abs z > 0.5 || abs x > 4.5]++arrows :: VisObject Double+arrows = displayVectorField blue 10 samplePoints (eField lineCharge)++drawFun :: VisObject Double+drawFun = VisObjects [curveObject red curve1, arrows]++myOptions :: Options+myOptions = defaultOpts {optWindowName = "Electric Field from a Line Charge"}++main :: IO ()+main = display myOptions drawFun
learn-physics.cabal view
@@ -1,5 +1,5 @@ Name: learn-physics-Version: 0.6.2+Version: 0.6.3 Synopsis: Haskell code for learning physics Description: A library of functions for vector calculus, calculation of electric field, electric flux,@@ -13,67 +13,68 @@ Build-type: Simple Cabal-version: >=1.8 Library- Exposed-modules: Physics.Learn.Charge- Physics.Learn.Current- Physics.Learn.Position- Physics.Learn.Curve- Physics.Learn.Surface- Physics.Learn.Volume+ Exposed-modules: Physics.Learn+ Physics.Learn.BeamStack+ Physics.Learn.BlochSphere Physics.Learn.CarrotVec- Physics.Learn.SimpleVec+ Physics.Learn.Charge Physics.Learn.CommonVec+ Physics.Learn.CompositeQuadrature Physics.Learn.CoordinateFields Physics.Learn.CoordinateSystem- Physics.Learn.StateSpace- Physics.Learn.RungeKutta- Physics.Learn.CompositeQuadrature- Physics.Learn.RootFinding+ Physics.Learn.Current+ Physics.Learn.Curve+ Physics.Learn.Ket Physics.Learn.Mechanics- Physics.Learn.Visual.PlotTools- Physics.Learn.Visual.GlossTools- Physics.Learn+ Physics.Learn.Position Physics.Learn.QuantumMat- Physics.Learn.Ket- Physics.Learn.BeamStack--- Physics.Learn.BlochSphere--- Physics.Learn.Visual.VisTools+ Physics.Learn.RootFinding+ Physics.Learn.RungeKutta+ Physics.Learn.Schrodinger1D+ Physics.Learn.SimpleVec+ Physics.Learn.StateSpace+ Physics.Learn.Surface+ Physics.Learn.Visual.GlossTools+ Physics.Learn.Visual.PlotTools+ Physics.Learn.Visual.VisTools+ Physics.Learn.Volume Build-depends: base >= 4.7 && < 4.12, vector-space >= 0.8.4, hmatrix >= 0.17, gloss >= 1.8,- gnuplot >= 0.5 && < 0.6--- not-gloss >= 0.5.0.4,--- spatial-math >= 0.2,+ gnuplot >= 0.5 && < 0.6,+ not-gloss >= 0.5.0.4,+ spatial-math >= 0.2 Hs-source-dirs: src Source-repository head type: git location: https://github.com/walck/learn-physics --- Executable learn-physics-PlaneWave--- Main-is: examples/src/PlaneWave.hs--- Build-depends: not-gloss >= 0.7.4,--- base >= 4.5 && < 4.12,--- learn-physics+Executable learn-physics-PlaneWave+ Main-is: examples/src/PlaneWave.hs+ Build-depends: not-gloss >= 0.7.4,+ base >= 4.5 && < 4.12,+ learn-physics --- Executable learn-physics-eFieldLine3D--- Main-is: examples/src/eFieldLine3D.hs--- Build-depends: not-gloss >= 0.7.4,--- base >= 4.5 && < 4.12,--- learn-physics+Executable learn-physics-eFieldLine3D+ Main-is: examples/src/eFieldLine3D.hs+ Build-depends: not-gloss >= 0.7.4,+ base >= 4.5 && < 4.12,+ learn-physics --- Executable learn-physics-LorentzForceSimulation--- Main-is: examples/src/LorentzForceSimulation.hs--- Build-depends: not-gloss >= 0.7.4,--- spatial-math >= 0.2,--- base >= 4.5 && < 4.12,--- learn-physics+Executable learn-physics-LorentzForceSimulation+ Main-is: examples/src/LorentzForceSimulation.hs+ Build-depends: not-gloss >= 0.7.4,+ spatial-math >= 0.2,+ base >= 4.5 && < 4.12,+ learn-physics --- Executable learn-physics-BCircularLoop--- Main-is: examples/src/BCircularLoop.hs--- Build-depends: not-gloss >= 0.7.4,--- base >= 4.5 && < 4.12,--- learn-physics+Executable learn-physics-BCircularLoop+ Main-is: examples/src/BCircularLoop.hs+ Build-depends: not-gloss >= 0.7.4,+ base >= 4.5 && < 4.12,+ learn-physics Executable learn-physics-sunEarth Main-is: examples/src/sunEarthRK4.hs@@ -93,7 +94,7 @@ base >= 4.5 && < 4.12, learn-physics --- Executable learn-physics-NMR--- Main-is: examples/src/NMR.hs--- Build-depends: base >= 4.5,--- learn-physics+Executable learn-physics-NMR+ Main-is: examples/src/NMR.hs+ Build-depends: base >= 4.5,+ learn-physics
src/Physics/Learn.hs view
@@ -166,12 +166,12 @@ , arrow , thickArrow -- ** Vis library- -- , v3FromVec- -- , v3FromPos- -- , visVec- -- , oneVector- -- , displayVectorField- -- , curveObject+ , v3FromVec+ , v3FromPos+ , visVec+ , oneVector+ , displayVectorField+ , curveObject ) where @@ -275,14 +275,14 @@ , shiftVolume , volumeIntegral )--- import Physics.Learn.Visual.VisTools--- ( v3FromVec--- , v3FromPos--- , visVec--- , oneVector--- , displayVectorField--- , curveObject--- )+import Physics.Learn.Visual.VisTools+ ( v3FromVec+ , v3FromPos+ , visVec+ , oneVector+ , displayVectorField+ , curveObject+ ) import Physics.Learn.StateSpace ( StateSpace(..) , (.-^)
+ src/Physics/Learn/BlochSphere.hs view
@@ -0,0 +1,226 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE CPP #-}++{- |+Module : Physics.Learn.BlochSphere+Copyright : (c) Scott N. Walck 2016+License : BSD3 (see LICENSE)+Maintainer : Scott N. Walck <walck@lvc.edu>+Stability : experimental++This module contains functions for displaying the+state of a spin-1/2 particle or other quantum two-level+system as a point on the Bloch Sphere.+-}++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+-- , (<>) -- matrix multiplication+-- , (|>) -- vector definition+ , (!) -- vector element access+ , (><) -- matrix definition+ , 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++{-+3 ways to specify the state of a spin-1/2 particle:+Vector C+Ket+Position (Bloch vector)++2 ways to specify a Hamiltonian:+Matrix C+Operator++3 choices for Vis' world:+(Float, Vector C)+(Float, Ket)+(Float, Position)+-}++-- | A Vis object.+type VisObj = VisObject Double++-- | Convert a 2x1 complex state vector for a qubit+-- into Bloch (x,y,z) coordinates.+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))++-- | Convert a qubit ket+-- into Bloch (x,y,z) coordinates.+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))++-- | A static 'VisObj' for the state of a qubit.+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)++-- | Display a qubit state vector as a point on the Bloch Sphere.+displayStaticState :: Vector C -> IO ()+displayStaticState = displayStaticBlochSphere . toPos++-- | Given a Bloch vector as a function of time,+-- return a 'VisObj' as a function of time.+animatedBlochSphere :: (Double -> Position) -> (Float -> VisObj)+animatedBlochSphere f+ = staticBlochSphere . f . realToFrac++-- | Given a sample rate, initial qubit state vector, and+-- state propagation function, produce a simulation.+-- The 'Float' in the state propagation function is the time+-- since the beginning of the simulation.+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++-- | Given a sample rate, initial qubit state ket, and+-- state propagation function, produce a simulation.+-- The 'Float' in the state propagation function is the time+-- since the beginning of the simulation.+simulateBlochSphereK :: Double -> Ket -> (Float -> (Float,Ket) -> (Float,Ket)) -> IO ()+simulateBlochSphereK sampleRate initial statePropFuncK+ = simulate myOptions sampleRate (0,initial) (staticBlochSphere . ketToPos . snd) statePropFuncK++{-+-- | Given a sample rate, initial qubit state vector, and+-- state propagation function, produce a simulation.+-- The 'Float' in the state propagation function is the time+-- since the beginning of the simulation.+playBlochSphere :: Double -> Vector C -> (Float -> (Float,Vector C) -> (Float,Vector C)) -> IO ()+playBlochSphere sampleRate initial statePropFunc+ = play myOptions sampleRate (0,initial) (staticBlochSphere . toPos . snd) statePropFunc+-}++-- | Produce a state propagation function from a time-dependent Hamiltonian.+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++-- | Produce a state propagation function from a time-dependent Hamiltonian.+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++-- | Given an initial qubit state and a time-dependent Hamiltonian,+-- produce a visualization.+evolutionBlochSphere :: Vector C -> (Double -> Matrix C) -> IO ()+evolutionBlochSphere psi0 ham+ = simulateBlochSphere 0.01 psi0 (stateProp ham)++-- | Given an initial qubit ket and a time-dependent Hamiltonian,+-- produce a visualization.+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)}++{-+staticBz1 :: IO ()+staticBz1 = evolutionBlochSphere M.xp (const (scale 0.9 M.sz))++staticBz2 :: IO ()+staticBz2 = evolutionBlochSphere ((2|>) [(cos (pi / 8)), (sin (pi / 8))]) (const M.sz)++staticBy1 :: IO ()+staticBy1 = evolutionBlochSphere M.xp (const M.sy)+-}++-- | Hamiltonian for nuclear magnetic resonance.+-- Explain omega0, omegaR, omega.+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)]++-- need to scale time++-- a pi pulse
+ src/Physics/Learn/Schrodinger1D.hs view
@@ -0,0 +1,415 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE Trustworthy #-}++{- | +Module : Physics.Learn.Schrodinger1D+Copyright : (c) Scott N. Walck 2015-2018+License : BSD3 (see LICENSE)+Maintainer : Scott N. Walck <walck@lvc.edu>+Stability : experimental++This module contains functions to+solve the (time dependent) Schrodinger equation+in one spatial dimension for a given potential function.+-}++module Physics.Learn.Schrodinger1D+ (+ -- * Potentials+ freeV+ , harmonicV+ , squareWell+ , doubleWell+ , stepV+ , wall+ -- * Initial wavefunctions+ -- , harm+ , coherent+ , gaussian+ , movingGaussian+ -- * Utilities+ , stateVectorFromWavefunction+ , hamiltonianMatrix+ , expectX+ , picture+ , xRange+ , listForm+ )+ where++import Data.Complex+ ( Complex(..)+ , magnitude+ )+import Graphics.Gloss+ ( Picture(..)+ , yellow+ , black+ , Display(..)+ , display+ )+-- import Math.Polynomial.Hermite+-- ( evalPhysHermite+-- )+import Numeric.LinearAlgebra+ ( R+ , C+ , Vector+ , Matrix+ , (|>)+ , (<.>)+ , fromLists+ , toList+ , size+ )+import Physics.Learn.QuantumMat+ ( probVector+ , timeEv+ )++--i :: Complex Double+--i = 0 :+ 1++----------------+-- Potentials --+----------------++-- | Free potential.+-- The potential energy is zero everywhere.+freeV+ :: Double -- ^ position+ -> Double -- ^ potential energy+freeV _x = 0++-- | Harmonic potential.+-- This is the potential energy of a linear spring.+harmonicV+ :: Double -- ^ spring constant+ -> Double -- ^ position+ -> Double -- ^ potential energy+harmonicV k x = k * x**2 / 2++-- | A double well potential.+-- Potential energy is a quartic function of position+-- that gives two wells, each approximately harmonic+-- at the bottom of the well.+doubleWell+ :: Double -- ^ width (for both wells and well separation)+ -> Double -- ^ energy height of barrier between wells+ -> Double -- ^ position+ -> Double -- ^ potential energy+doubleWell a v0 x = v0 * ((x**2 - a**2)/a**2)**2++-- | Finite square well potential.+-- Potential is zero inside the well,+-- and constant outside the well.+-- Well is centered at the origin.+squareWell+ :: Double -- ^ well width+ -> Double -- ^ energy height of well+ -> Double -- ^ position+ -> Double -- ^ potential energy+squareWell l v0 x+ | abs x < l/2 = 0+ | otherwise = v0++-- | A step barrier potential.+-- Potential is zero to left of origin.+stepV+ :: Double -- ^ energy height of barrier (to the right of origin)+ -> Double -- ^ position+ -> Double -- ^ potential energy+stepV v0 x+ | x < 0 = 0+ | otherwise = v0++-- | A potential barrier with thickness and height.+wall+ :: Double -- ^ thickness of wall+ -> Double -- ^ energy height of barrier+ -> Double -- ^ position of center of barrier+ -> Double -- ^ position+ -> Double -- ^ potential energy+wall w v0 x0 x+ | abs (x-x0) < w/2 = v0+ | otherwise = 0++---------------------------+-- Initial wavefunctions --+---------------------------++-- -- | Harmonic oscillator stationary state+-- harm :: Int -- ^ nonnegative integer n identifying stationary state+-- -> Double -- ^ x / sqrt(hbar/(m * omega)), i.e. position+-- -- in units of sqrt(hbar/(m * omega))+-- -> C -- ^ complex amplitude+-- harm n u+-- = exp (-u**2/2) * evalPhysHermite n u / sqrt (2^n * fact n * sqrt pi) :+ 0++coherent+ :: R -- ^ length scale = sqrt(hbar / m omega)+ -> C -- ^ parameter z+ -> R -> C -- ^ wavefunction+coherent l z x+ = ((1/(pi*l**2))**0.25 * exp(-x**2/(2*l**2)) :+ 0)+ * exp(-z**2/2 + (sqrt(2/l**2) * x :+ 0) * z)++gaussian+ :: R -- ^ width parameter+ -> R -- ^ center of wave packet+ -> R -> C -- ^ wavefunction+gaussian a x0 x = exp(-(x-x0)**2/(2*a**2)) / sqrt(a * sqrt pi) :+ 0++movingGaussian+ :: R -- ^ width parameter+ -> R -- ^ center of wave packet+ -> R -- ^ l0 = hbar / p0+ -> R -> C -- ^ wavefunction+movingGaussian a x0 l0 x = exp((0 :+ x/l0) - ((x-x0)**2/(2*a**2) :+ 0)) / (sqrt(a * sqrt pi) :+ 0)++---------------+-- Utilities --+---------------++fact :: Int -> Double+fact 0 = 1+fact n = fromIntegral n * fact (n-1)++linspace :: Double -> Double -> Int -> [Double]+linspace left right num+ = let dx = (right - left) / fromIntegral (num - 1)+ in [ left + dx * fromIntegral n | n <- [0..num-1]]++-- | Transform a wavefunction into a state vector.+stateVectorFromWavefunction :: R -- ^ lowest x+ -> R -- ^ highest x+ -> Int -- ^ dimension of state vector+ -> (R -> C) -- ^ wavefunction+ -> Vector C -- ^ state vector+stateVectorFromWavefunction left right num psi+ = (num |>) [psi x | x <- linspace left right num]++hamiltonianMatrix :: R -- ^ lowest x+ -> R -- ^ highest x+ -> Int -- ^ dimension of state vector+ -> R -- ^ hbar+ -> R -- ^ mass+ -> (R -> R) -- ^ potential energy function+ -> Matrix C -- ^ Hamiltonian Matrix+hamiltonianMatrix xmin xmax num hbar m pe+ = let coeff = -hbar**2/(2*m)+ dx = (xmax - xmin) / fromIntegral (num - 1)+ diagKEterm = -2 * coeff / dx**2+ offdiagKEterm = coeff / dx**2+ xs = linspace xmin xmax num+ in fromLists [[case abs(i-j) of+ 0 -> (diagKEterm + pe x) :+ 0+ 1 -> offdiagKEterm :+ 0+ _ -> 0+ | j <- [1..num] ] | (i,x) <- zip [1..num] xs]++expectX :: Vector C -- ^ state vector+ -> Vector R -- ^ vector of x values+ -> R -- ^ <X>, expectation value of X+expectX psi xs = probVector psi <.> xs+++glossScaleX :: Int -> (Double,Double) -> Double -> Float+glossScaleX screenWidth (xmin,xmax) x+ = let w = fromIntegral screenWidth :: Double+ in realToFrac $ (x - xmin) / (xmax - xmin) * w - w / 2++glossScaleY :: Int -> (Double,Double) -> Double -> Float+glossScaleY screenHeight (ymin,ymax) y+ = let h = fromIntegral screenHeight :: Double+ in realToFrac $ (y - ymin) / (ymax - ymin) * h - h / 2++glossScalePoint :: (Int,Int) -- ^ (screenWidth,screenHeight)+ -> (Double,Double) -- ^ (xmin,xmax)+ -> (Double,Double) -- ^ (ymin,ymax)+ -> (Double,Double) -- ^ (x,y)+ -> (Float,Float)+glossScalePoint (screenWidth,screenHeight) xMinMax yMinMax (x,y)+ = (glossScaleX screenWidth xMinMax x+ ,glossScaleY screenHeight yMinMax y)+++-- | Produce a gloss 'Picture' of state vector+-- for 1D wavefunction.+picture :: (Double, Double) -- ^ y range+ -> [Double] -- ^ xs+ -> Vector C -- ^ state vector+ -> Picture+picture (ymin,ymax) xs psi+ = Color+ yellow+ (Line+ [glossScalePoint+ (screenWidth,screenHeight)+ (head xs, last xs)+ (ymin,ymax)+ p | p <- zip xs (map magSq $ toList psi)])+ where+ magSq = \z -> magnitude z ** 2+ screenWidth = 1000+ screenHeight = 750++-- options for representing wave functions+-- 1. A function R -> C+-- 2. ([R],Vector C), where lengths match+-- 3. [(R,C)]+-- 4. (R,R,Vector C) -- xmin, xmax, state vector (assumes even spacing)++-- 2,4 are best for evolution++listForm :: (R,R,Vector C) -> ([R],Vector C)+listForm (xmin,xmax,v)+ = let dt = (xmax - xmin) / fromIntegral (size v - 1)+ in ([xmin, xmin + dt .. xmax],v)+++{-+-- | Given an initial state vector and+-- state propagation function, produce a simulation.+-- The 'Float' in the state propagation function is the time+-- interval for one timestep.+simulate1D :: [Double] -> Vector C -> (Float -> (Float,[Double],Vector C) -> (Float,[Double],Vector C)) -> IO ()+simulate1D xs initial statePropFunc+ = simulate display black 10 (0,initial) displayFunc (const statePropFunc)+ where+ display = InWindow "Animation" (screenWidth,screenHeight) (10,10)+ displayFunc (_t,v) = Color yellow (Line [(+ + white (\tFloat -> Pictures [Color blue (Line (points (realToFrac tFloat)))+ ,axes (screenWidth,screenHeight) (xmin,xmax) (ymin,ymax)])++-- | Produce a state propagation function from a time-dependent Hamiltonian.+-- The float is dt.+statePropGloss :: (Double -> Matrix C) -> Float -> (Float,Vector C) -> (Float,Vector C)+statePropGloss ham dt (tOld,v)+ = (tNew, timeEv (realToFrac dt) (ham tMid) v)+ where+ tNew = tOld + dt+ tMid = realToFrac $ (tNew + tOld) / 2++-- | Given an initial state vector and a time-dependent Hamiltonian,+-- produce a visualization of a 1D wavefunction.+evolutionBlochSphere :: Vector C -> (Double -> Matrix C) -> IO ()+evolutionBlochSphere psi0 ham+ = simulateBlochSphere 0.01 psi0 (stateProp ham)++-}+++{-+def triDiagMatrixMult(square_arr,arr):+ num = len(arr)+ result = array([0 for n in range(num)],dtype=complex128)+ result[0] = square_arr[0][0] * arr[0] + square_arr[0][1] * arr[1]+ for n in range(1,num-1):+ result[n] = square_arr[n][n-1] * arr[n-1] + square_arr[n][n] * arr[n] \+ + square_arr[n][n+1] * arr[n+1]+ result[num-1] = square_arr[num-1][num-2] * arr[num-2] \+ + square_arr[num-1][num-1] * arr[num-1]+ return result+-}++------------------+-- Main program --+------------------++-- n is number of points+-- n-1 is number of intervals+xRange :: R -> R -> Int -> [R]+xRange xmin xmax n+ = let dt = (xmax - xmin) / fromIntegral (n - 1)+ in [xmin, xmin + dt .. xmax]+++{-+if __name__ == '__main__':+ m = 1+ omega = 10+ xmin = -2.0+ xmax = 2.0+ num = 256+ num = 128+ dt = 0.0002+ dt = 0.01+ xs = linspace(xmin,xmax,num)+ dx = xs[1] - xs[0]++ super = lambda x: (harm0(m,omega)(x) + harm1(m,omega)(x))/sqrt(2)+ shiftedHarm = lambda x: harm0(m,omega)(x-1)+ coh = coherent(m,omega,1)++ print sum(conj(psi)*psi)*dx++ harmV = harmonicV(m * omega**2)++ V = doubleWell(1,0.1*hbar*omega)+ V = squareWell(1.0,hbar*omega)+ V = harmonicV(m*omega**2)+ V = stepV(10*hbar*omega)+ V = wall(0.1,14.0*hbar*omega,0)+ V = freeV++ H = matrixH(m,xmin,xmax,num,V)+ I = matrixI(num)++ (vals,vecs) = eigh(H)++ E0 = vals[0]+ E1 = vals[1]+ psi0 = normalize(transpose(vecs)[0],dx)+ psi1 = normalize(transpose(vecs)[1],dx)++ psi = func2psi(gaussian(0.3,1),xmin,xmax,num)+ psi = func2psi(coh,xmin,xmax,num)+ psi = func2psi(movingGaussian(0.3,10,-1),xmin,xmax,num)++ psi = psi0+ psi = psi1+ psi = (psi0 + psi1)/sqrt(2)++ E = sum(conj(psi)*triDiagMatrixMult(H,psi)).real*dx++ Escale = hbar*omega++ print E+ print Escale++ leftM = I + 0.5 * i * H / hbar * dt+ rightM = I - 0.5 * i * H / hbar * dt++ box = display(title='Schrodinger Equation',width=1000,height=1000)++ c = curve(pos = psi2rho(psi,xs))+ c.color = color.blue+ c.radius = 0.02++ ball = sphere(radius=0.05,color=color.red,pos=(expectX(psi,xs),0,0))++ pot_curve = [(x,V(x)/Escale,0) for x in xs if V(x)/Escale < xmax]+ pot = curve(color=color.green,pos=pot_curve,radius=0.01)++ Eline = curve(color=(1,1,0),pos=[(x,E/Escale) for x in xs])+ axis = curve(color=color.white,pos=[(x,0) for x in xs])++ while 1:+ psi = solve(leftM,triDiagMatrixMult(rightM,psi))+ c.pos = psi2rho(psi,xs)+ ball.x = expectX(psi,xs)++To Do:+add combinators for potentials+to shift horizontally and vertically,+and to add potentials++-}++-- Are we committed to SI units for hbar? No.+-- harmonic oscillator functions depend only on sqrt(hbar/m omega)+-- which is a length parameter+-- for moving gaussian, could give hbar/p0 instead of p0+-- (is that debrogie wavelength? I think it's h/p0)
src/Physics/Learn/SimpleVec.hs view
@@ -3,7 +3,7 @@ {- | Module : Physics.Learn.SimpleVec-Copyright : (c) Scott N. Walck 2012-2014+Copyright : (c) Scott N. Walck 2012-2018 License : BSD3 (see LICENSE) Maintainer : Scott N. Walck <walck@lvc.edu> Stability : experimental@@ -17,24 +17,9 @@ easier for a person just learning Haskell. -} --- 2011 Apr 10--- Placed the code common to SimpleVec and CarrotVec in CommonVec---- 2011 Mar 19--- Add support for sumV, so that the interface matches CarrotVec.hs---- This uses the same internal data representation as SimpleVector,--- but uses an interface to match Conal Elliott's operators for--- vectors. (A similar interface to CarrotVector and SimpleCarrotVector.)--- The notation--- zeroV, negateV, (^+^), (^-^)--- is borrowed from Data.AdditiveGroup, and--- (*^), (^*), (^/), (<.>), magnitude--- is borrowed from Data.VectorSpace.--- Cross product operator is my own.- module Physics.Learn.SimpleVec ( Vec+ , R , xComp , yComp , zComp@@ -72,6 +57,8 @@ infixl 7 ^/ infixl 7 <.> +type R = Double+ -- | The zero vector. zeroV :: Vec zeroV = vec 0 0 0@@ -95,23 +82,23 @@ -- | Scalar multiplication, where the scalar is on the left -- and the vector is on the right.-(*^) :: Double -> Vec -> Vec+(*^) :: R -> Vec -> Vec c *^ Vec ax ay az = Vec (c*ax) (c*ay) (c*az) -- | Scalar multiplication, where the scalar is on the right -- and the vector is on the left.-(^*) :: Vec -> Double -> Vec+(^*) :: Vec -> R -> Vec Vec ax ay az ^* c = Vec (c*ax) (c*ay) (c*az) -- | Division of a vector by a scalar.-(^/) :: Vec -> Double -> Vec+(^/) :: Vec -> R -> Vec Vec ax ay az ^/ c = Vec (ax/c) (ay/c) (az/c) -- | Dot product of two vectors.-(<.>) :: Vec -> Vec -> Double+(<.>) :: Vec -> Vec -> R Vec ax ay az <.> Vec bx by bz = ax*bx + ay*by + az*bz -- | Magnitude of a vector.-magnitude :: Vec -> Double+magnitude :: Vec -> R magnitude v = sqrt(v <.> v)
+ src/Physics/Learn/Visual/VisTools.hs view
@@ -0,0 +1,126 @@+{-# OPTIONS_GHC -Wall #-}++-- | Some tools related to the not-gloss 3D graphics and animation library.++module Physics.Learn.Visual.VisTools+ ( v3FromVec+ , v3FromPos+ , visVec+ , oneVector+ , displayVectorField+ , curveObject+ )+ where++import SpatialMath+ ( V3(..)+ , Euler(..)+ )+import Vis+ ( VisObject(..)+ , Color+ )+import Physics.Learn.CarrotVec+ ( Vec+ , xComp+ , yComp+ , zComp+-- , magnitude+ , (^/)+ )+import Physics.Learn.Position+ ( Position+ , cartesianCoordinates+ , VectorField+ )+import Physics.Learn.Curve+ ( Curve(..)+ )++-- | Make a 'V3' object from a 'Vec'.+v3FromVec :: Vec -> V3 Double+v3FromVec v = V3 x y z+ where+ x = xComp v+ y = yComp v+ z = zComp v++-- | Make a 'V3' object from a 'Position'.+v3FromPos :: Position -> V3 Double+v3FromPos r = V3 x y z+ where+ (x,y,z) = cartesianCoordinates r++-- | Display a vector field.+displayVectorField :: Color -- ^ color for the vector field+ -> Double -- ^ scale factor+ -> [Position] -- ^ list of positions to show the field+ -> VectorField -- ^ vector field to display+ -> VisObject Double -- ^ the displayable object+displayVectorField col unitsPerMeter samplePts field+ = VisObjects [Trans (v3FromPos r) $ visVec col (e ^/ unitsPerMeter) | r <- samplePts, let e = field r]++-- | A displayable VisObject for a curve.+curveObject :: Color -> Curve -> VisObject Double+curveObject color (Curve f a b)+ = Line' Nothing [(v3FromPos (f t), color) | t <- [a,a+(b-a)/1000..b]]++-- | Place a vector at a particular position.+oneVector :: Color -> Position -> Vec -> VisObject Double+oneVector c r v = Trans (v3FromPos r) $ visVec c v++data Cart = Cart Double Double Double+ deriving (Show)++data Sph = Sph Double Double Double+ deriving (Show)++sphericalCoords :: Cart -> Sph+sphericalCoords (Cart x y z) = Sph r theta phi+ where+ r = sqrt (x*x + y*y + z*z)+ s = sqrt (x*x + y*y)+ theta = atan2 s z+ phi = atan2 y x++-- | A VisObject arrow from a vector+visVec :: Color -> Vec -> VisObject Double+visVec c v = rotZ phi $ rotY theta $ Arrow (r,20*r) (V3 0 0 1) c+ where+ x = xComp v+ y = yComp v+ z = zComp v+ Sph r theta phi = sphericalCoords (Cart x y z)++{-+rotX :: Double -- ^ in radians+ -> VisObject Double+ -> VisObject Double+rotX alpha = RotEulerRad (Euler 0 0 alpha)+-}++rotY :: Double -- ^ in radians+ -> VisObject Double+ -> VisObject Double+rotY alpha = RotEulerRad (Euler 0 alpha 0)++rotZ :: Double -- ^ in radians+ -> VisObject Double+ -> VisObject Double+rotZ alpha = RotEulerRad (Euler alpha 0 0)+++{-+adjacentDistance :: [Position] -> Double+adjacentDistance [] = 0+adjacentDistance rs'@(_:rs) = minimum (map magnitude $ zipWith displacement rs' rs)++visVectorField :: Color -> [Position] -> VectorField -> VisObject Double+visVectorField c rs vf = let prs = [(r,vf r) | r <- rs]+ bigV = maximum [magnitude (snd pr) | pr <- prs]+ disp = adjacentDistance rs+ scaleFactor = disp / bigV+ newPrs = [(r, scaleFactor *^ v) | (r,v) <- prs]+ vecs = [oneVector c r v' | (r,v') <- newPrs]+ in VisObjects vecs+-}