{- Implementation of the Jacobi iteration XZ, 24/10/91 -} {- Modified to adopt S_array XZ, 19/2/92 -} module Jcb_method ( jcb_method ) where import Defs import S_Array -- not needed w/ proper module handling import Norm -- ditto import Asb_routs import Tol_cal import Ix--1.3 ----------------------------------------------------------- -- Jacobi iteration method: -- -- solves: scalor*MX = B -- -- with iteration counter (r) as -- -- X(r+1) = X(r) + relax*(B/scalor - MX(r))/D -- -- The system matrix M is never really assembled -- ----------------------------------------------------------- jcb_method :: Int -> My_Array Int (Frac_type,((Frac_type,Frac_type,Frac_type), (Frac_type,Frac_type,Frac_type))) -> My_Array Int [(Int,Int)] -> My_Array Int [Int] -> (My_Array Int Bool,(My_Array Int Bool, My_Array Int Bool)) -> (My_Array Int Frac_type, My_Array Int Frac_type) -> Frac_type -> Int -> Frac_type -> Frac_type -> (My_Array Int Frac_type, My_Array Int Frac_type) sparse_elems = \y -> map (\(_,x)->x) (sparse_assocs y) jcb_method f_step el_det_fac asb_table v_steer (all_bry,(x_fixed,y_fixed)) (b1,b2) scalor max_iter m_iter_toler relax = sub_jacobi (init_u,init_u) max_iter where n_bnds = s_bounds asb_table init_u = s_array n_bnds [] -- the recursive function of the Jacobi iteration sub_jacobi old_x n = -- X(r) iteration_counter if -- checking the iteration limit ( n <= 1 ) || -- checking the tolerance ( (n /= max_iter) && ( tol_cal ((s_elems (fst new_x)) ++ (s_elems (snd new_x))) ((sparse_elems (fst diff)) ++ (sparse_elems (snd diff))) True ) < m_iter_toler ) {- ( (sum ( map abs ( s_elems (fst diff) ) )) + (sum ( map abs ( s_elems (snd diff) ) )) ) < m_iter_toler -} then new_x -- X(r+1) else sub_jacobi new_x (n-1) where -- new adaptive x new_x = if ( n == max_iter ) -- first iteration then diff -- otherwise else add_u old_x diff diff = if ( f_step == 1 ) then -- For step 1. Only fixes some boundry nodes. ( find_diff x_fixed (fst old_x) b1, find_diff y_fixed (snd old_x) b2 ) else -- For step 3. Fixes all boundry nodes. ( find_diff all_bry (fst old_x) b1, find_diff all_bry (snd old_x) b2 ) bindTo x k = k x -- old haskell 1.0 "let" -- function which does one adaptation, -- ie, calculates: -- relax*(B - MX(r))/D find_diff fixed x b = -- list_of_unfixed_nodes X(r) B s_def_listArray n_bnds (0::Frac_type) [ if fixed!^i then 0 else ((b!^i) / scalor) `bindTo` ( \ b' -> (( if ( n == max_iter ) then b' else b' - sum [ (list_inner_prod (get_val x (v_steer!^e)) (map (mult (fst (el_det_fac!^e))) (m_mat!^id))) | (e,id)<-asb_table!^i ] ) * relax) / (mat_diag!^i) ) | i <- range n_bnds ] -- row sums of system M mat_diag = s_listArray n_bnds [ sum [ (fst ( el_det_fac!^e)) * (m_r_sum!^id) | (e,id)<-asb_table!^i ] | i <- range n_bnds ] ----------------------------------------------------------- -- row sums of element matrix m_mat -- ----------------------------------------------------------- m_r_sum = s_def_listArray (1,v_nodel) def_v [ def_v,def_v,def_v,v',v',v' ] where def_v = (12 / 180)::Frac_type v' = (68 / 180)::Frac_type ----------------------------------------------------------- -- element matrix -- ----------------------------------------------------------- m_mat = s_listArray (1,v_nodel) (map (map (mult inv_180)) [ [6,(-1),(-1),(-4),0,0], [(-1),6,(-1),0,(-4),0], [(-1),(-1),6,0,0,(-4)], [(-4),0,0,32,16,16], [0,(-4),0,16,32,16], [0,0,(-4),16,16,32] ]) where inv_180 = 1 / 180