gloss-examples-1.7.3.1: raster/Fluid/Stage/Linear.hs
{-# LANGUAGE FlexibleContexts, BangPatterns #-}
module Stage.Linear
(linearSolver)
where
import Model
import FieldElt as E
import Data.Array.Repa as R
import Data.Array.Repa.Stencil as R
import Data.Array.Repa.Stencil.Dim2 as R
import Data.Array.Repa.Eval as R
import Data.Vector.Unboxed
import Debug.Trace
linearSolver
:: (FieldElt a, Repr U a, Unbox a, Elt a, Num a)
=> Field a -- ^ Original field.
-> Field a -- ^ Current field.
-> Float
-> Float
-> Int -- ^ Number of iterations to apply.
-> IO (Field a)
linearSolver origField curField !a !c !i
-- If nothing would change by running the solver, then skip it.
| 0 <- a = return origField
-- The solver has finished its loop
| 0 <- i = return curField
-- Do one iteration
| otherwise
= origField `deepSeqArray` curField `deepSeqArray`
do let !c' = 1/c
let {-# INLINE zipFunc #-}
zipFunc !orig !new
= new ~+~ (orig ~*~ c')
traceEventIO "Fluid: linear solver mapStencil"
newField <- {-# SCC "linearSolver.mapStencil" #-}
computeUnboxedP
$ R.czipWith zipFunc origField
$ mapStencil2 (BoundConst E.zero) (linearSolverStencil a c) curField
linearSolver origField newField a c (i - 1)
{-# SPECIALIZE linearSolver
:: Field Float
-> Field Float
-> Float -> Float -> Int
-> IO (Field Float) #-}
{-# SPECIALIZE linearSolver
:: Field (Float, Float)
-> Field (Float, Float)
-> Float -> Float -> Int
-> IO (Field (Float, Float)) #-}
-- | Stencil function for the linear solver.
linearSolverStencil
:: FieldElt a
=> Float -> Float -> Stencil DIM2 a
linearSolverStencil a c
= StencilStatic (Z:.3:.3) E.zero
(\ix val acc ->
case linearSolverCoeffs a c ix of
Nothing -> acc
Just coeff -> acc ~+~ (val ~*~ coeff))
{-# INLINE linearSolverStencil #-}
-- | Linear solver stencil kernel.
linearSolverCoeffs
:: Float -> Float -> DIM2 -> Maybe Float
linearSolverCoeffs a c (Z:.j:.i)
| i == 1, j == 0 = Just (a/c)
| i == -1, j == 0 = Just (a/c)
| i == 0, j == 1 = Just (a/c)
| i == 0, j == -1 = Just (a/c)
| otherwise = Nothing
{-# INLINE linearSolverCoeffs #-}