{-# LANGUAGE NoImplicitPrelude #-} module TBit.Plots (bzPlot, paramPlot, bandPlot) where import TBit.Types import TBit.Framework import TBit.Parameterization import TBit.Hamiltonian.Eigenstates (eigenenergies) import Prelude.Listless import Data.List -- .Stream import Data.Map (adjust, elems) import Control.Monad.State import Control.Parallel.Strategies import Numeric.LinearAlgebra.HMatrix import qualified Data.Traversable as T {-| Given a hamiltonian and a set of parameters, plot a real-valued function over the Brillouin zone. For a Berry curvature plot, /e.g./, > bzPlot (kagomeAF, defaultParams) (bandCurvature 0) The output string is suitable for gnuplot, unless that string is reporting an error from the calculation. -} bzPlot :: (Parameterized Hamiltonian, Parameters) -> (Hamiltonian -> Wavevector -> Parameterized Double) -> String bzPlot (h, ps) f = case crunch (h >>= computeBZPlot f) ps of Left err -> show err Right dat -> unlines . map (\(k, d) -> (unwords . map show . toList $ k) ++ " " ++ show d) $ dat computeBZPlot :: (Hamiltonian -> Wavevector -> Parameterized Double) -> Hamiltonian -> Parameterized [(Wavevector, Double)] computeBZPlot f h = meshBZ >>= T.mapM (\k -> T.sequence (k, f h k)) >>= (return . elems) {-| Given a hamiltonian and a set of parameters, plot a real-valued function over some range of a parameter. For a Chern number plot over the hopping parameter, /e.g./, > paramPlot (kagomeAF, defaultParams) (chern 1) ("t", [1.0, 1.1 .. 5.0]) The output string is suitable for gnuplot, unless that string is reporting an error from the calculation. -} paramPlot :: (Parameterized Hamiltonian, Parameters) -> (Hamiltonian -> Parameterized Double) -> (String, [Double]) -> String paramPlot (h, ps) f (s, ss) = case crunch (computePMPlot f s ss h) ps of Left err -> show err Right dat -> unlines . map (\(p, d) -> show p ++ " " ++ show d) $ dat computePMPlot :: (Hamiltonian -> Parameterized Double) -> String -> [Double] -> Parameterized Hamiltonian -> Parameterized [(Double, Double)] computePMPlot f s ss h = liftM (zip ss) $ mapM (\v -> modify (setScalar s v) >> (h >>= f)) $ ss where setScalar str val ps = ps { scalarParams = adjust (\_ -> val :+ 0.0) str $ scalarParams ps } multiPlot :: (Parameterized Hamiltonian, Parameters) -> [(Hamiltonian -> Parameterized Double)] -> (String, [Double]) -> String multiPlot sys fs params = unlines $ map (\f -> paramPlot sys f params) fs {-| Given a hamiltonian and a set of parameters, plot the bands over a path anchored by the provided wavevectors. For instance, > gamma = vector [0.0 , 0.0] > point1 = vector [0.5 , 1.0] > point2 = vector [0.5 , -1.0] > bandPlot (kagomeAF, defaultParams) [gamma, point1, point2, gamma] The output string is suitable for gnuplot, unless that string is reporting an error from the calculation. -} bandPlot :: (Parameterized Hamiltonian, Parameters) -> [Wavevector] -> String bandPlot (h,ps) ks = either show id $ crunch (bandData h ks) ps bandData :: Parameterized Hamiltonian -> [Wavevector] -> Parameterized String bandData h ks = do mtx <- h kPath ks >>= mapM (eigenenergies mtx) >>= (return . unlines . map (\(x, e) -> show x ++ " " ++ show e) . concatMap T.sequence . zip [0..])