root/trunk/ProjectFortress/demos/BiCGSTAB.fss

Revision 4130, 11.8 KB (checked in by sukyoungryu, 3 months ago)

[disambiguator] Fixed handling getters and setters in ExprDisambiguator?. Fixed libraries and tests using getters.

Line 
1(*******************************************************************************
2  This program is copyrighted free software by Kento Emoto
3  <emoto[at]ipl.t.u-tokyo.ac.jp> developed under the collaborative
4  research on Fortress Programming Language between Sun Microsystems,
5  Inc. and the University of Tokyo.
6
7  You can redistribute it and/or modify it under the following
8  BSD-style license or the Sun Contributor Agreement that Kento Emoto signed.
9
10
11  Copyright 2009 by Kento Emoto
12  All rights reserved.
13
14  Redistribution and use in source and binary forms, with or without
15  modification, are permitted provided that the following conditions
16  are met:
17
18      * Redistributions of source code must retain the above copyright
19        notice, this list of conditions and the following disclaimer.
20      * Redistributions in binary form must reproduce the above copyright
21        notice, this list of conditions and the following disclaimer
22        in the documentation and/or other materials provided with the
23        distribution.
24      * Neither the name of Kento Emoto nor the names of its
25        contributors may be used to endorse or promote products derived
26        from this software without specific prior written permission.
27
28  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
30  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
32  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
35  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
37  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
38  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
40
41 ******************************************************************************)
42
43(*****************************************************************************
44This program was translated from Fortran program
45cgstab_org_commented.f90, which implements BiCGSTAB method for 7-band
46matrices. The Fortran program is available on the following URL.
47
48  http://www.ipl.t.u-tokyo.ac.jp/~emoto/cgstab_sentinel.f90
49
50Also, a report about the translation is abailable on the follwoing URL.
51
52  http://www.ipl.t.u-tokyo.ac.jp/~emoto/BiCGSTAB-report-eng.pdf
53
54
55The Fortran program was originally provided by Dr. Kajita (Nagoya
56Municipal Industrial Research Institute, Japan), which is available on
57the following blog (Japanese).
58
59  http://atsim.hpc.co.jp/portal/article.php?story=20090325171921177
60
61We started the translation from a little modified version of his program.
62
63This program is a straightforward translation of the Fortran program;
64it uses arrays of one-based indexing.  However, this prohibits us from
65using instances of Vector and algebraic operations on vectors, because
66an array of non-zero-based indexing cannot be a vector in Fortress.
67This point is improved in the next translation BiCGSTAB2.fss .
68*)
69
70component BiCGSTAB
71
72export Executable
73
74
75run(args : String...) : () = do
76  println("BiCGSTAB")
77  testrun[\16,16,16\]();
78  (*testrun[\2,2,2\]();*)
79end
80
81(* Makes sample matrix A and vector b s.t. the answer of A x = b is x = 1 . *)
82initilization[\nat imax, nat jmax, nat kmax\]() =
83do
84  Ap = array3[\RR64, imax, jmax, kmax\]().shift((1,1,1))
85  Ae = array3[\RR64, imax, jmax, kmax\]().shift((1,1,1))
86  Aw = array3[\RR64, imax, jmax, kmax\]().shift((1,1,1))
87  An = array3[\RR64, imax, jmax, kmax\]().shift((1,1,1))
88  As = array3[\RR64, imax, jmax, kmax\]().shift((1,1,1))
89  At = array3[\RR64, imax, jmax, kmax\]().shift((1,1,1))
90  Ab = array3[\RR64, imax, jmax, kmax\]().shift((1,1,1))
91  Ap.fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):RR64 => 2.0)
92  Ae.fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):RR64 => 1.0)
93  Aw.fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):RR64 => 1.0)
94  An.fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):RR64 => 1.0)
95  As.fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):RR64 => 1.0)
96  At.fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):RR64 => 1.0)
97  Ab.fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):RR64 => 1.0)
98
99  for j <- 1:jmax do
100    for k <- 1:kmax do
101      Aw[1,j,k]    := 0.0
102      Ae[imax,j,k] := 0.0
103    end
104  end
105  for i <- 1:imax do
106    for k <- 1:kmax do
107      As[i,1,k]    := 0.0
108      An[i,jmax,k] := 0.0
109    end
110  end
111  for i <- 1:imax do
112    for j <- 1:jmax do
113      Ab[i,j,1]    := 0.0
114      At[i,j,kmax] := 0.0
115    end
116  end
117
118  (*  PrintMatrix[\imax,jmax,kmax\](Ap, Ae, Aw, An, As, At, Ab) *)
119  (*
120  oops! we cant use negative indices! ... nat is only for non-negative...
121  b = array1[\RR64, imax jmax kmax + 2 jmax imax\]().shift(1 - jmax imax)
122  c = array1[\RR64, imax jmax kmax + 2 jmax imax\]().shift(1 - jmax imax)
123
124  i will shift them in the product loop.
125  *)
126
127  b = array1[\RR64, (imax jmax kmax) + (2 jmax imax)\]().shift(1)
128  x = array1[\RR64, (imax jmax kmax) + (2 jmax imax)\]().shift(1)
129
130  x.fill(fn (i:ZZ32):RR64 => 0.0)
131  b.fill(fn (i:ZZ32):RR64 => 0.0)
132
133  for i <- 1:imax do
134    for j <- 1:jmax do
135      for k <- 1:kmax do
136        m = i + imax (j-1) + imax jmax (k-1) + imax jmax
137        b[m] := 2.0
138        if (i>1) AND (i<imax) then
139          b[m] := b[m] + 2.0
140        else
141          b[m] := b[m] + 1.0
142        end
143
144        if (j>1) AND (j<jmax) then
145          b[m] := b[m] + 2.0
146        else
147          b[m] := b[m] + 1.0
148        end
149
150        if (k>1) AND (k<kmax) then
151          b[m] := b[m] + 2.0
152        else
153          b[m] := b[m] + 1.0
154        end
155      end
156    end
157  end
158  (* the answer of Ax=b is x = 1. *)
159  (Ap, Ae, Aw, An, As, At, Ab, b, x)
160end
161
162(* A sample driver for the BiCGSTAB method. *)
163testrun[\nat imax, nat jmax, nat kmax\]() : () =
164do
165  (Ap, Ae, Aw, An, As, At, Ab, b, x) = initilization[\imax, jmax, kmax\]()
166(*
167  PrintVector[\imax, jmax, kmax\](b)
168  PrintMatrixVector[\imax, jmax, kmax\](Ap, Ae, Aw, An, As, At, Ab, b)
169  MatrixVectorProduct[\imax, jmax, kmax\](Ap, Ae, Aw, An, As, At, Ab, b, x)
170  PrintVector[\imax, jmax, kmax\](x)
171  *)
172
173  st = nanoTime()
174  bicg_stab_band[\imax, jmax, kmax\](Ap,Ae,Aw,An,As,At,Ab,x,b)
175  et = nanoTime()
176  t = et - st
177  ss = t / 1000000000.0
178  println("elapsed time " t " ns ( " ss " s)")
179end
180(* Note
181b must be of [1-imax jamx : imax jmax kmax + imax jmax] for simplicity
182oops! we cant use negative indices for arrays!!!!!!
183ok. i will shift the indices by + imax jmax
184
185conditions for sentinels (zero-valued extra computatios on boundaries)
186Aw(1,_,_)    = 0
187Ae(imax,_,_) = 0
188As(_,1,_)    = 0
189An(_,jmax,_) = 0
190Ab(_,_,1)    = 0
191At(_,_,kmax) = 0
192
193*)
194(* BiCGSTAB method for band matrix A and vector b.
195   The matrix A is ristricted to a 7-band matrix here.
196   We could generalize it by letting A be a function from vectors to vectors.
197 *)
198bicg_stab_band[\nat imax, nat jmax, nat kmax\](Ap,Ae,Aw,An,As,At,Ab,x,b) : (ZZ32, RR64) =
199do
200  dot_product(u, v) = SUM [i <- (1 + imax jmax)#(imax jmax kmax)] u[i] v[i]
201
202  r  = b.copy()
203  r' = b.copy()
204  p  = b.copy()
205  y  = b.copy()
206  e  = b.copy()
207  v  = b.copy()
208  c  = b.copy()
209  (* we dont need so many iterations because the matrix is a band matrix. *)
210  itrmax = imax jmax kmax
211  er0 = 1.0 10^(-4)
212
213  MatrixVectorProduct[\imax,jmax,kmax\](Ap,Ae,Aw,An,As,At,Ab,x,c)
214
215(*
216  PrintVector[\imax, jmax, kmax\](x)
217  PrintMatrixVector[\imax, jmax, kmax\](Ap, Ae, Aw, An, As, At, Ab, x)
218  PrintVector[\imax, jmax, kmax\](c)
219  PrintVector[\imax, jmax, kmax\](b)
220  *)
221
222  (* We can use 'r := b - c' if they are vactors (an array staring from 0).
223     However, the index in the original program starts from 1,
224     and I use arrays of one-based indexing in this program
225     respecting the original program.
226     This prohibits us from using algebraic operations for vectors,
227     since an array of one-based index is not a vector in Fortress.
228     Also, point-wise operations lead to inefficiency because of
229     excessive boundary checking.
230     *)
231  r[i] := b[i] - c[i], i <- x.indices
232  c1 : RR64 := dot_product(r, r) (* r DOT r *)
233
234  label MainLoop
235    if (c1 < er0) then exit MainLoop with () end
236    p[i] = r[i], i <- r.indices  (* p = r *)
237    r'[i] = r[i], i <- r.indices (* r' = r *)
238
239(*
240    PrintVector[\imax, jmax, kmax\](p)
241    PrintVector[\imax, jmax, kmax\](r')
242*)
243    it : ZZ32 := 1
244    rr : RR64 := 0
245    while it <= itrmax do
246      MatrixVectorProduct[\imax,jmax,kmax\](Ap,Ae,Aw,An,As,At,Ab,p,y)
247      c2 = dot_product(r', y) (* r' DOT y *)
248      alp = c1 / c2
249      e[i] := r[i] - alp y[i], i <- r.indices (* e = r - alp y *)
250      MatrixVectorProduct[\imax,jmax,kmax\](Ap,Ae,Aw,An,As,At,Ab,e,v)
251      ev = dot_product(e, v) (* e DOT v *)
252      vv = dot_product(v, v) (* v DOT v *)
253      (* We get ev=vv=0 when imax=jmax=kmax=2. Thus, we need to avoid NaN. *)
254      c3 = if (vv=0) AND (ev=0) then 1 else ev / vv end
255      x[i] := x[i] + alp p[i] + c3 e[i], i <- x.indices (* x = x + alp p + c3 e *)
256      r[i] := e[i] - c3 v[i], i <- e.indices (* r = e - c3 v *)
257      rr := dot_product(r, r) (* r DOT r *)
258      println(it " residual = " rr)
259      if (rr < er0) then exit MainLoop with (it,rr) end
260      c1 := dot_product(r', r) (* r' DOT r *)
261
262      bet = c1 / (c2 c3)
263      p[i] := r[i] + bet (p[i] - c3 y[i]), i <- p.indices (* p = r + bet (p - c3 y) *)
264
265      it += 1
266    end
267    (it,rr)
268  end MainLoop
269end
270
271(* A product of a 7-band matrix and a vector. *)
272MatrixVectorProduct[\nat imax, nat jmax, nat kmax\]
273(Ap, Ae, Aw, An, As, At, Ab, b, c) : () =
274do
275  for k <- 1:kmax do
276    for j <- 1:jmax do
277      for i <- 1:imax do
278        m = i + imax (j-1) + imax jmax (k-1) + imax jmax
279        c[m] := Ap[i,j,k] b[m] + Aw[i,j,k] b[m - 1] + Ae[i,j,k] b[m + 1] + As[i,j,k] b[m - imax] + An[i,j,k] b[m + imax] + Ab[i,j,k] b[m - imax jmax] + At[i,j,k] b[m + imax jmax]
280      end
281    end
282  end
283end
284(* A pretty printer for a 7-band matrix.*)
285PrintMatrix[\nat imax, nat jmax, nat kmax\]
286(Ap, Ae, Aw, An, As, At, Ab) : () =
287do
288  for k <- seq(1:kmax) do
289    for j <- seq(1:jmax) do
290      for i <- seq(1:imax) do
291        m = i + (imax (j-1)) + (imax jmax (k-1)) (* mth row *)
292        p : ZZ32 := 1
293        while p <= imax jmax kmax do
294          v = case p of
295                m             => Ap[i,j,k]
296                m - 1         => Aw[i,j,k]
297                m + 1         => Ae[i,j,k]
298                m - imax      => As[i,j,k]
299                m + imax      => An[i,j,k]
300                m - imax jmax => Ab[i,j,k]
301                m + imax jmax => At[i,j,k]
302                else          => 0.0
303              end
304          print(v " ")
305          p += 1
306        end
307        println()
308      end
309    end
310  end
311end
312
313(* A pretty printer for a vector (an array). *)
314PrintVector[\nat imax, nat jmax, nat kmax\]
315(s, b) : () =
316do
317print(s " : ")
318PrintVector[\imax, jmax, kmax\](b)
319end
320
321(* A pretty printer for a vector (an array). *)
322PrintVector[\nat imax, nat jmax, nat kmax\]
323(b) : () =
324do
325  for k <- seq(1:kmax) do
326    for j <- seq(1:jmax) do
327      for i <- seq(1:imax) do
328        m = i + (imax (j-1)) + (imax jmax (k-1)) + imax jmax (* mth row *)
329        print(b[m] " ")
330      end
331    end
332  end
333  println()
334end
335
336(* A pretty printer for the pair of a 7-band matrix and a vector (an array). *)
337PrintMatrixVector[\nat imax, nat jmax, nat kmax\]
338(Ap, Ae, Aw, An, As, At, Ab, b) : () =
339do
340  for k <- seq(1:kmax) do
341    for j <- seq(1:jmax) do
342      for i <- seq(1:imax) do
343        m = i + (imax (j-1)) + (imax jmax (k-1)) (* mth row *)
344        p : ZZ32 := 1
345        while p <= imax jmax kmax do
346          v = case p of
347                m             => Ap[i,j,k]
348                m - 1         => Aw[i,j,k]
349                m + 1         => Ae[i,j,k]
350                m - imax      => As[i,j,k]
351                m + imax      => An[i,j,k]
352                m - imax jmax => Ab[i,j,k]
353                m + imax jmax => At[i,j,k]
354                else          => 0.0
355              end
356          print(v " ")
357          p += 1
358        end
359        println(": " b[m + imax jmax])
360      end
361    end
362  end
363end
364
365
366end
Note: See TracBrowser for help on using the browser.