-- | Stable fluid flow-solver. -- Based on "Real-time Fluid Dynamics for Games", Jos Stam, Game developer conference, 2003. -- Implementation by Ben Lambert-Smith. -- Converted to Repa 3 by Ben Lippmeier. -- {-# LANGUAGE ScopedTypeVariables #-} module Main (main) where import Solve.Density import Solve.Velocity import Model import UserEvent import Args import Config import Graphics.Gloss import Graphics.Gloss.Interface.IO.Game import System.Mem import System.Environment (getArgs) import Data.Array.Repa.IO.Timing as R import Prelude as P main :: IO () main = do -- Parse the command-line arguments. args <- getArgs config <- parseArgs args configDefault -- Setup the initial fluid model. let model = initModel (configInitialDensity config) (configInitialVelocity config) performGC case configBatchMode config of False -> runInteractive config model True -> do (_, elapsed) <- time $ do result <- runBatchMode config model result `seq` return () putStrLn $ show $ wallTime milliseconds elapsed -- | Run the simulation interactively. runInteractive :: Config -> Model -> IO () runInteractive config model0 = let (scaleX, scaleY) = configScale config in playIO (InWindow "Stam's stable fluid. Use left-click right-drag to add density / velocity." (configWindowSize config) (20, 20)) black (configRate config) model0 (pictureOfModel (fromIntegral scaleX, fromIntegral scaleY)) (\event model -> return $ userEvent config event model) (\_ -> stepFluid config) -- | Run in batch mode and dump a .bmp of the final state. runBatchMode :: Config -> Model -> IO () runBatchMode config model | stepsPassed model >= configMaxSteps config = return () | otherwise = do model' <- stepFluid config model case configFramesMode config of Nothing -> return () Just path -> do putStrLn $ "frame " ++ show (stepsPassed model) outputBMP path (stepsPassed model) (densityField model) runBatchMode config model' -- Function to step simulator one step forward in time stepFluid :: Config -> Model -> IO Model stepFluid config m@(Model df ds vf vs cl step dv cb) | step >= configMaxSteps config , configMaxSteps config > 0 = return m | otherwise = do performGC vf' <- velocitySteps config step vf vs df' <- densitySteps config step df ds vf' return $ Model df' Nothing vf' Nothing cl (step + 1) dv cb