{-# 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..])