+
+
+
+big_K_elem :: forall m n l a b.
+ (Arity l, Arity m, Arity n,
+ Algebraic.C a, RealField.C a, ToRational.C a)
+ => PDE a
+ -> Params m n l a
+ -> Int
+ -> Int
+ -> Mat l l a
+ -> b
+ -> Mat l l a
+big_K_elem pde params _ k cur_K _ =
+ ifoldl2 accum cur_K (big_N's_matrix :: Mat m (S n) (a -> a))
+ where
+ accum :: Int -> Int -> Mat l l a -> (a -> a) -> Mat l l a
+ accum i j prev_K these_N's =
+ prev_K + this_K
+ where
+ two = fromInteger 2
+ (x1,x2) = (mesh params) !!! (k,0)
+ q = affine_inv (x1,x2)
+ integrand x = ((big_A pde) (q x)) * (these_N's x)
+ -- The pointer matrix numbers from 1 so subtract one here to
+ -- get the right index.
+ global_row_idx = ((pointer params) !!! (k,i)) - 1
+ global_col_idx = ((pointer params) !!! (k,j)) - 1
+ this_K = construct lambda
+ lambda v w = if v == global_row_idx && w == global_col_idx
+ then (two/(x2 - x1))* (gaussian integrand)
+ else fromInteger 0
+
+
+
+-- | Compute the \"big K\" stiffness matrix. There are three
+-- parameters needed for K, namely i,j,k so a fold over a matrix will
+-- not do. This little gimmick simulates a three-index fold by doing a
+-- two-index fold over a row of the proper dimensions.
+--
+-- Examples:
+--
+-- >>> import Data.Vector.Fixed ( N3, N4 )
+-- >>> import Linear.Matrix ( Col4, frobenius_norm, fromList )
+-- >>> import Naturals ( N7 )
+--
+-- >>> let big_A = const (1::Double)
+-- >>> let c x = sin x
+-- >>> let f x = x*(sin x)
+-- >>> let bdy = Left (Dirichlet (0,1::Double))
+-- >>> let pde = PDE big_A c f bdy
+--
+-- >>> let i1 = (0.0,1/3)
+-- >>> let i2 = (1/3,2/3)
+-- >>> let i3 = (2/3,4/5)
+-- >>> let i4 = (4/5,1.0)
+-- >>> let mesh = fromList [[i1], [i2], [i3], [i4]] :: Col4 (Double,Double)
+-- >>> let pvec = fromList [[2],[3],[2],[1]] :: Col4 Int
+-- >>> let params = Params mesh pvec :: Params N4 N3 N7 Double
+--
+-- >>> let k1 = [6, -3, 0, 0, 0, 0, 0] :: [Double]
+-- >>> let k2 = [-3, 10.5, -7.5, 0, 0, 0, 0] :: [Double]
+-- >>> let k3 = [0, -7.5, 12.5, 0, 0, 0, 0] :: [Double]
+-- >>> let k4 = [0, 0, 0, 6, 0, 0, 0] :: [Double]
+-- >>> let k5 = [0, 0, 0, 0, 6, 0, 0] :: [Double]
+-- >>> let k6 = [0, 0, 0, 0, 0, 6, 0] :: [Double]
+-- >>> let k7 = [0, 0, 0, 0, 0, 0, 15] :: [Double]
+-- >>> let expected = fromList [k1,k2,k3,k4,k5,k6,k7] :: Mat N7 N7 Double
+-- >>> let actual = big_K pde params
+-- >>> frobenius_norm (actual - expected) < 1e-10
+-- True
+--
+big_K :: forall m n l a.
+ (Arity l, Arity m, Arity n,
+ Algebraic.C a, RealField.C a, ToRational.C a)
+ => PDE a
+ -> Params m n l a
+ -> Mat l l a
+big_K pde params =
+ ifoldl2 (big_K_elem pde params) zero col_idxs
+ where
+ col_idxs = fromList [map fromInteger [0..]] :: Row m a
+