\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)) || ((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 -------------------------------------
-----------------------------------------------------------------
|