\section{Input} Represent a sparse matrix where each "element" of the matrix is a dense block Roger L. Wainwright 6-8-90 ================================================================ TEST DATA INPUT FUNCTIONS These functions create test data sets for the linear system solver. ================================================================ Notes: gmat n provides a large sparse matrix for data set n. rhside n provides the b vector for data set n. soln_vect n provides the x vector for data set n. wells n provides the length of wells in (gmat n) split a_easy n provides some "easy" a matrix. a_hard n provides some "hard" a matrix. x1 n provides a vector of all 1's for (a_easy n) AbsDensematrix is imported to keep hbc happy. mkbigvec and mksparse contain some yucky kludges. (r,c,b) = (r-1,c-1,..) to make indices zero origin. \begin{code} module Input (gmat,rhside,soln_vect,wells,split,blm',mkbigvec, mksparse,a_easy,a_hard,x1) where import List (transpose) import Matrix import AbsDensematrix import Utils mkbigvec :: [[Float]] -> Vector mkbigvec v = mkvector (map mkvec v) mksparse :: [[(Int,Int,[[Float]])]] -> Matrix mksparse m = mkmatrix (map (map f) m) where f (r,c,b) = (r-1,c-1,mkblock b) \end{code} ####################################################################### ################ GCOMP DATA INPUT ROUTINES ############################ Note: readmtx, split, splitmtx was written by Dan Vasicek and copied from his directory 6/22/90 with minor modifications. In the code that follows "abc" replaces force(ReadFile x) as a temporary measure(irm) except in myread in which it replaces: f (system ("cat "++fname)) where f (a,b,c) = a \begin{code} directory :: String directory = "./Data/" file1 :: Int -> String file1 n = directory ++ "gcomp.mat" ++ (show n) ++ ".one" file2a :: Int -> String file2a n = directory ++ "gcomp.mat" ++ (show n) ++ ".twoa" file2b :: Int -> String file2b n = directory ++ "gcomp.mat" ++ (show n) ++ ".twob" file2c :: Int -> String file2c n = directory ++ "gcomp.mat" ++ (show n) ++ ".twoc" file3 :: Int -> String file3 n = directory ++ "gcomp.mat" ++ (show n) ++ ".three" file4 :: Int -> String file4 n = directory ++ "gcomp.mat" ++ (show n) ++ ".four" file5 :: Int -> String file5 n = directory ++ "gcomp.mat" ++ (show 2) ++ ".soln" file6 :: Int -> String file6 n = directory ++ "gcomp.mat" ++ (show n) ++ ".well" file :: String file = "gconem.bmtx3" -- original file resn = 11 resm = 21 resnm = resn * resm readmtx rtype x = map (map numval) (map f y) where y = if (rtype == 1) then drop 1 (lines ("abc")) else if (rtype == 2) then init (lines ("abc")) else lines ("abc") f y = [take 15 (drop 1 y ) , take 15 (drop 16 y ) , take 15 (drop 31 y ) , take 15 (drop 46 y ) ] readsoln x = map (map numval) (map f y) where y = lines ("abc") f y = [take 15 (drop 8 y ) , take 15 (drop 24 y ) , take 15 (drop 40 y ) , take 15 (drop 56 y ) ] myreadmtx rtype x = map (map numval) (map f y) where y = if (rtype == 1) then drop 1 (lines (myread x)) else if (rtype == 2) then init (lines (myread x)) else lines (myread x) f y = [take 15 (drop 1 y ) , take 15 (drop 16 y ) , take 15 (drop 31 y ) , take 15 (drop 46 y ) ] myread fname = "abc" readsolnvect x = collect_by4 (concat z) where z = map (map numval) (map f y) y = lines ("abc") f y = [take 21 (drop 11 y )] collect_by4 [] = [] collect_by4 (a:b:c:d:xs) = [a,b,c,d]: (collect_by4 xs) \end{code} ******* TEST VARIOUS OPERATIONS ************************ file1 contains a header line file4 contains an END line input1' looks like: [ [4 values] [4 values] ... [4 values] ] input1 looks like: [blocks] as shown below [ [ [4 values] [4 values] [4values] [4values] ] [ [ ] [ ] [ ] [ ] ] . . . . [ [ ] [ ] [ ] [ ] ] ] \begin{code} split m [] = [] split m xs = (take m xs):(split m (drop m xs)) splitmtx n m xs = split n (split m xs) \end{code} ************************* READ FILES **************************** \begin{code} input1' n = readmtx 1 (file1 n) input1 n = split 4 (input1' n) input2a' n = readmtx 0 (file2a n) input2a n = split 4 (input2a' n) input2b' n = readmtx 0 (file2b n) input2b n = split 4 (input2b' n) input2c' n = readmtx 0 (file2c n) input2c n = split 4 (input2c' n) input3' n = readmtx 0 (file3 n) input3 n = split 4 (input3' n) input4' n = readmtx 2 (file4 n) input5' n = readsolnvect (file5 n) \end{code} ********************** FILE 1 ******************************* \begin{code} lowerband' n = take (resnm-resn) (drop resn (input1 n)) lowerband n = map transpose (lowerband' n) block_lowerband n = convert_lowerband (lowerband' n) \end{code} ********************** FILE 2a ******************************* \begin{code} ldiagband' n = drop 1 (input2a n) ldiagband n = map transpose (ldiagband n) block_ldiagband n = convert_ldiagband (ldiagband' n) \end{code} ********************** FILE 2b ******************************* \begin{code} mdiagband' = input2b mdiagband n = map transpose (mdiagband' n) block_mdiagband n = convert_mdiagband (mdiagband' n) \end{code} ********************** FILE 2c ******************************* \begin{code} udiagband' n = init(input2c n) udiagband n = map transpose (udiagband' n) block_udiagband n = convert_udiagband (udiagband' n) \end{code} ********************** FILE 3 ******************************* \begin{code} upperband' n = take (resnm-resn) (input3 n) upperband n = map transpose (upperband' n) block_upperband n = convert_upperband (upperband' n) \end{code} ********************** FILE 4 ******************************* \begin{code} rhside n = mkbigvec (input4' n) \end{code} ********************** FILE 5 ******************************* \begin{code} soln_vect n = mkbigvec (input5' n) \end{code} ******* END TEST VARIOUS OPERATIONS ********************* \begin{code} convert_lowerband :: [[[Float]]] -> Block_list convert_lowerband b = [(i+resn,i,head (drop(i-1) b) ) | i <-[1..length b]] convert_ldiagband :: [[[Float]]] -> Block_list convert_ldiagband b = [(i+1,i,head (drop(i-1)b)) | i <-[1..length b]] convert_mdiagband :: [[[Float]]] -> Block_list convert_mdiagband b = [(i,i,head (drop(i-1)b)) | i <-[1..length b]] convert_udiagband :: [[[Float]]] -> Block_list convert_udiagband b = [(i,i+1,head (drop(i-1)b))| i <-[1..length b]] convert_upperband :: [[[Float]]] -> Block_list convert_upperband b = [(i,i+resn, head (drop(i-1) b)) | i <-[1..length b]] \end{code} ------------------ more testing ------------------------------------------ Note: In make_lmat(below) that Block_list :: [(Int,Int,[[Float]])] \begin{code} wells :: Int -> Int wells 6 = 1 wells 7 = 3 wells 8 = 7 wells n = 0 gvect :: Vector gvect = mkbigvec (rep resnm [1,1,1,1]) gmat n = make_lmat (block_lowerband n) (block_ldiagband n) (block_mdiagband n) (block_udiagband n) (block_upperband n) gvect0 :: Vector gvect0 = mkbigvec (rep resnm [0,0,0,0]) make_lmat :: Block_list -> Block_list -> Block_list -> Block_list -> Block_list -> Matrix make_lmat lower ldiag mdiag udiag upper = mksparse [row i | i<- [1..resnm]] where row i = combine i lower ldiag mdiag udiag upper combine i low ld md ud up = if (i==1) then (take 1 md) ++ (take 1 ud) ++ (take 1 up) else if (i <=resn) then diag3 ++ upper else if (i >(resnm - resn)) then lower ++ diag3 else if (i == resnm) then [last low] ++ [last ld] ++ [last md] else lower ++ diag3 ++ upper where diag3 = (take 1 (drop (i-2) ld )) ++ (take 1 (drop (i-1) md )) ++ (take 1 (drop (i-1) ud )) upper = take 1(drop(i-1) up) lower = take 1(drop (i-resn-1) low) \end{code} =========================================================== =================== DEBUGGING CONSTANTS =================== =========================================================== \begin{code} x0 size = mkbigvec [ [0,0,0,0] | i<-[1..size*size]] x1 size = mkbigvec [ [1,1,1,1] | i<-[1..size*size]] a_easy size = if (size > 1) then blm size else mksparse [[(1,1,[[11,-1, 0, 0], [-1,11,-1, 0], [ 0,-1,11,-1], [ 0, 0,-1,11]])]] a_hard size = if size > 1 then blm_hard size else error "ummm. system size to small for this model." off_block = [[-1,0,0,0], [0,-1,0,0], [0,0,-1,0], [0,0,0,-1]] d_block = [[11,-1, 0, 0], [-1,11,-1, 0], [ 0,-1,11,-1], [ 0, 0,-1,11]] hard_off_block = (map (map (/90)) [[-1,-2,-3,-4], [-4,-1,-2,-3], [-3,-4,-1,-2], [-2,-3,-4,-1]]) hard_d_block = (map (map (/90)) [[90,-2,-3,-4], [-4,90,-2,-3], [-3,-4,90,-2], [-2,-3,-4,40]]) \end{code} ----------------------------------------------------------- ----------------------------------------------------------- CONSTRUCT A LIST MATRIX for a specific pattern using off_block and d_block for data. Note we assume 4x4 blocks in this pattern. br (build row) will build a block-row blm (build list matrix) will build a list matrix \begin{code} blm :: Int -> Matrix blm n = mksparse (blm' n) blm' :: Int -> [[(Int,Int,[[Float]])]] blm' n = [row i | i<- [1..(n*n)]] where row i = br i n br :: Int -> Int -> [(Int,Int,[[Float]])] br rw n = if ((rw == 1) || (rw == (n*n-n+1))) then [block i| i<- [1,2,n+1,n+2]] else if ((rw == n) || (rw == n*n)) then [block i | i<-[n-1,n,2*n-1,2*n]] else if ((rw `mod` n) == 1) then [block i | i<-[1,2,n+1,n+2,2*n+1,2*n+2]] else if ((rw `mod` n) == 0) then [block i | i<-[n-1,n,2*n-1,2*n,3*n-1,3*n]] else if ((rw >1) && (rw (n*n-n+1)) && (rw < n*n)) then [block i | i<-[m,1+m,2+m,n+m,n+1+m,n+2+m]] else [block i | i<-[m,1+m,2+m,n+m,n+1+m,n+2+m, 2*n+m,2*n+1+m,2*n+2+m]] where block i = if (rw == (i+offset)) then (rw,i+offset,d_block) else (rw,i+offset,off_block) m = (rw `mod` n) -1 offset = if (rw <= n) then 0 else (((rw-1) `div` n) -1) * n blm_hard :: Int -> Matrix blm_hard n = mksparse hard where hard = map (map f) (blm' n) f (r,c,b) = if (r/=c) then (r,c,hard_off_block) else (r,c,hard_d_block) \end{code} ====================================================== Include wells in a given matrix (Copied from Roger Wainwright and modified) ======================================================= Note: include_wells :: matrix -> [[num]] -> [[num]] -> [[num]] -> [[num]] -> matrix include_well :: matrix -> [num]-> [num]-> [num]-> [num] -> matrix include_row_well :: matrix -> [num] -> [num] -> matrix include_col_well :: matrix -> [num] -> [num] -> matrix include_dw :: matrix -> [num] -> matrix append_row :: matrix -> (num, [num]) -> matri In append_row the line: colnum = length m is required to append row wells before col wells. \begin{code} include_wells m (a:as) (b:bs) (c:cs) (d:ds) = if (as == []) then include_well m a b c d else include_wells m' as bs cs ds where m' = include_well m a b c d include_well m well_pos wellg wellh welldw = include_dw m'' welldw where m'' = include_col_well m' well_pos wellg m' = include_row_well m well_pos wellh include_row_well m well_pos wellh = m' where m' = m ++ [new_row] new_row = map2 f well_pos (split 4 wellh) f x y = (row_num, x,[y]) row_num = length m +1 include_col_well m well_pos wellg = foldl append_row m x where x = zip2 well_pos (split 4 wellg) include_dw m welldw = append_row m (length m,welldw) append_row m (rownum, dat) = m' where m' = (take (rownum-1) m) ++ [appendrow] ++ drop rownum m appendrow = row ++ [(rownum,colnum,data')] data' = split 1 dat row = m !! (rownum-1) colnum = length m numval :: String -> Float numval x = (read x)::Float \end{code} ---------------------------------------------------------------- ---------- THAT'S ALL FOLKS ------------------------------------- -----------------------------------------------------------------