| 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 | (***************************************************************************** |
|---|
| 44 | This program was translated from Fortran program |
|---|
| 45 | cgstab_org_commented.f90, which implements BiCGSTAB method for 7-band |
|---|
| 46 | matrices. The Fortran program is available on the following URL. |
|---|
| 47 | |
|---|
| 48 | http://www.ipl.t.u-tokyo.ac.jp/~emoto/cgstab_sentinel.f90 |
|---|
| 49 | |
|---|
| 50 | Also, 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 | |
|---|
| 55 | The Fortran program was originally provided by Dr. Kajita (Nagoya |
|---|
| 56 | Municipal Industrial Research Institute, Japan), which is available on |
|---|
| 57 | the following blog (Japanese). |
|---|
| 58 | |
|---|
| 59 | http://atsim.hpc.co.jp/portal/article.php?story=20090325171921177 |
|---|
| 60 | |
|---|
| 61 | We started the translation from a little modified version of his program. |
|---|
| 62 | |
|---|
| 63 | This program is a straightforward translation of the Fortran program; |
|---|
| 64 | it uses arrays of one-based indexing. However, this prohibits us from |
|---|
| 65 | using instances of Vector and algebraic operations on vectors, because |
|---|
| 66 | an array of non-zero-based indexing cannot be a vector in Fortress. |
|---|
| 67 | This point is improved in the next translation BiCGSTAB2.fss . |
|---|
| 68 | *) |
|---|
| 69 | |
|---|
| 70 | component BiCGSTAB |
|---|
| 71 | |
|---|
| 72 | export Executable |
|---|
| 73 | |
|---|
| 74 | |
|---|
| 75 | run(args : String...) : () = do |
|---|
| 76 | println("BiCGSTAB") |
|---|
| 77 | testrun[\16,16,16\](); |
|---|
| 78 | (*testrun[\2,2,2\]();*) |
|---|
| 79 | end |
|---|
| 80 | |
|---|
| 81 | (* Makes sample matrix A and vector b s.t. the answer of A x = b is x = 1 . *) |
|---|
| 82 | initilization[\nat imax, nat jmax, nat kmax\]() = |
|---|
| 83 | do |
|---|
| 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) |
|---|
| 160 | end |
|---|
| 161 | |
|---|
| 162 | (* A sample driver for the BiCGSTAB method. *) |
|---|
| 163 | testrun[\nat imax, nat jmax, nat kmax\]() : () = |
|---|
| 164 | do |
|---|
| 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)") |
|---|
| 179 | end |
|---|
| 180 | (* Note |
|---|
| 181 | b must be of [1-imax jamx : imax jmax kmax + imax jmax] for simplicity |
|---|
| 182 | oops! we cant use negative indices for arrays!!!!!! |
|---|
| 183 | ok. i will shift the indices by + imax jmax |
|---|
| 184 | |
|---|
| 185 | conditions for sentinels (zero-valued extra computatios on boundaries) |
|---|
| 186 | Aw(1,_,_) = 0 |
|---|
| 187 | Ae(imax,_,_) = 0 |
|---|
| 188 | As(_,1,_) = 0 |
|---|
| 189 | An(_,jmax,_) = 0 |
|---|
| 190 | Ab(_,_,1) = 0 |
|---|
| 191 | At(_,_,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 | *) |
|---|
| 198 | bicg_stab_band[\nat imax, nat jmax, nat kmax\](Ap,Ae,Aw,An,As,At,Ab,x,b) : (ZZ32, RR64) = |
|---|
| 199 | do |
|---|
| 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 |
|---|
| 269 | end |
|---|
| 270 | |
|---|
| 271 | (* A product of a 7-band matrix and a vector. *) |
|---|
| 272 | MatrixVectorProduct[\nat imax, nat jmax, nat kmax\] |
|---|
| 273 | (Ap, Ae, Aw, An, As, At, Ab, b, c) : () = |
|---|
| 274 | do |
|---|
| 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 |
|---|
| 283 | end |
|---|
| 284 | (* A pretty printer for a 7-band matrix.*) |
|---|
| 285 | PrintMatrix[\nat imax, nat jmax, nat kmax\] |
|---|
| 286 | (Ap, Ae, Aw, An, As, At, Ab) : () = |
|---|
| 287 | do |
|---|
| 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 |
|---|
| 311 | end |
|---|
| 312 | |
|---|
| 313 | (* A pretty printer for a vector (an array). *) |
|---|
| 314 | PrintVector[\nat imax, nat jmax, nat kmax\] |
|---|
| 315 | (s, b) : () = |
|---|
| 316 | do |
|---|
| 317 | print(s " : ") |
|---|
| 318 | PrintVector[\imax, jmax, kmax\](b) |
|---|
| 319 | end |
|---|
| 320 | |
|---|
| 321 | (* A pretty printer for a vector (an array). *) |
|---|
| 322 | PrintVector[\nat imax, nat jmax, nat kmax\] |
|---|
| 323 | (b) : () = |
|---|
| 324 | do |
|---|
| 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() |
|---|
| 334 | end |
|---|
| 335 | |
|---|
| 336 | (* A pretty printer for the pair of a 7-band matrix and a vector (an array). *) |
|---|
| 337 | PrintMatrixVector[\nat imax, nat jmax, nat kmax\] |
|---|
| 338 | (Ap, Ae, Aw, An, As, At, Ab, b) : () = |
|---|
| 339 | do |
|---|
| 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 |
|---|
| 363 | end |
|---|
| 364 | |
|---|
| 365 | |
|---|
| 366 | end |
|---|