156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org/**
256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * Copyright 2012 the V8 project authors. All rights reserved.
356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * Copyright 2009 Oliver Hunt <http://nerget.com>
456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org *
556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * Permission is hereby granted, free of charge, to any person
656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * obtaining a copy of this software and associated documentation
756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * files (the "Software"), to deal in the Software without
856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * restriction, including without limitation the rights to use,
956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * copy, modify, merge, publish, distribute, sublicense, and/or sell
1056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * copies of the Software, and to permit persons to whom the
1156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * Software is furnished to do so, subject to the following
1256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * conditions:
1356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org *
1456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * The above copyright notice and this permission notice shall be
1556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * included in all copies or substantial portions of the Software.
1656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org *
1756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
2156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org * OTHER DEALINGS IN THE SOFTWARE.
2556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org */
2656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
2756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgvar NavierStokes = new BenchmarkSuite('NavierStokes', 1484000,
2856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                                      [new Benchmark('NavierStokes',
2956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                                                     runNavierStokes,
3056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                                                     setupNavierStokes,
3156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                                                     tearDownNavierStokes)]);
3256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
3356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgvar solver = null;
3456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
3556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgfunction runNavierStokes()
3656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org{
3756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    solver.update();
3856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org}
3956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
4056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgfunction setupNavierStokes()
4156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org{
4256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    solver = new FluidField(null);
4356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    solver.setResolution(128, 128);
4456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    solver.setIterations(20);
4556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    solver.setDisplayFunction(function(){});
4656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    solver.setUICallback(prepareFrame);
4756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    solver.reset();
4856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org}
4956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
5056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgfunction tearDownNavierStokes()
5156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org{
5256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    solver = null;
5356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org}
5456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
5556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgfunction addPoints(field) {
5656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var n = 64;
5756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    for (var i = 1; i <= n; i++) {
5856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        field.setVelocity(i, i, n, n);
5956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        field.setDensity(i, i, 5);
6056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        field.setVelocity(i, n - i, -n, -n);
6156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        field.setDensity(i, n - i, 20);
6256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        field.setVelocity(128 - i, n + i, -n, -n);
6356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        field.setDensity(128 - i, n + i, 30);
6456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
6556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org}
6656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
6756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgvar framesTillAddingPoints = 0;
6856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgvar framesBetweenAddingPoints = 5;
6956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
7056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgfunction prepareFrame(field)
7156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org{
7256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    if (framesTillAddingPoints == 0) {
7356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        addPoints(field);
7456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        framesTillAddingPoints = framesBetweenAddingPoints;
7556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        framesBetweenAddingPoints++;
7656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    } else {
7756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        framesTillAddingPoints--;
7856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
7956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org}
8056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
8156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org// Code from Oliver Hunt (http://nerget.com/fluidSim/pressure.js) starts here.
8256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgfunction FluidField(canvas) {
8356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function addFields(x, s, dt)
8456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
8556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        for (var i=0; i<size ; i++ ) x[i] += dt*s[i];
8656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
8756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
8856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function set_bnd(b, x)
8956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
9056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        if (b===1) {
9156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var i = 1; i <= width; i++) {
9256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                x[i] =  x[i + rowSize];
9356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                x[i + (height+1) *rowSize] = x[i + height * rowSize];
9456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
9556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
9656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var j = 1; i <= height; i++) {
9756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                x[j * rowSize] = -x[1 + j * rowSize];
9856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                x[(width + 1) + j * rowSize] = -x[width + j * rowSize];
9956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
10056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        } else if (b === 2) {
10156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var i = 1; i <= width; i++) {
10256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                x[i] = -x[i + rowSize];
10356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                x[i + (height + 1) * rowSize] = -x[i + height * rowSize];
10456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
10556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
10656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var j = 1; j <= height; j++) {
10756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                x[j * rowSize] =  x[1 + j * rowSize];
10856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                x[(width + 1) + j * rowSize] =  x[width + j * rowSize];
10956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
11056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        } else {
11156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var i = 1; i <= width; i++) {
11256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                x[i] =  x[i + rowSize];
11356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                x[i + (height + 1) * rowSize] = x[i + height * rowSize];
11456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
11556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
11656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var j = 1; j <= height; j++) {
11756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                x[j * rowSize] =  x[1 + j * rowSize];
11856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                x[(width + 1) + j * rowSize] =  x[width + j * rowSize];
11956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
12056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        }
12156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var maxEdge = (height + 1) * rowSize;
12256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        x[0]                 = 0.5 * (x[1] + x[rowSize]);
12356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        x[maxEdge]           = 0.5 * (x[1 + maxEdge] + x[height * rowSize]);
12456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        x[(width+1)]         = 0.5 * (x[width] + x[(width + 1) + rowSize]);
12556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        x[(width+1)+maxEdge] = 0.5 * (x[width + maxEdge] + x[(width + 1) + height * rowSize]);
12656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
12756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
12856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function lin_solve(b, x, x0, a, c)
12956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
13056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        if (a === 0 && c === 1) {
13156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var j=1 ; j<=height; j++) {
13256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var currentRow = j * rowSize;
13356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                ++currentRow;
13456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                for (var i = 0; i < width; i++) {
13556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    x[currentRow] = x0[currentRow];
13656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    ++currentRow;
13756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                }
13856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
13956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            set_bnd(b, x);
14056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        } else {
14156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var invC = 1 / c;
14256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var k=0 ; k<iterations; k++) {
14356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                for (var j=1 ; j<=height; j++) {
14456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    var lastRow = (j - 1) * rowSize;
14556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    var currentRow = j * rowSize;
14656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    var nextRow = (j + 1) * rowSize;
14756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    var lastX = x[currentRow];
14856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    ++currentRow;
14956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    for (var i=1; i<=width; i++)
15056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                        lastX = x[currentRow] = (x0[currentRow] + a*(lastX+x[++currentRow]+x[++lastRow]+x[++nextRow])) * invC;
15156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                }
15256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                set_bnd(b, x);
15356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
15456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        }
15556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
15656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
15756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function diffuse(b, x, x0, dt)
15856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
15956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var a = 0;
16056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        lin_solve(b, x, x0, a, 1 + 4*a);
16156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
16256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
16356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function lin_solve2(x, x0, y, y0, a, c)
16456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
16556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        if (a === 0 && c === 1) {
16656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var j=1 ; j <= height; j++) {
16756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var currentRow = j * rowSize;
16856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                ++currentRow;
16956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                for (var i = 0; i < width; i++) {
17056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    x[currentRow] = x0[currentRow];
17156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    y[currentRow] = y0[currentRow];
17256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    ++currentRow;
17356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                }
17456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
17556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            set_bnd(1, x);
17656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            set_bnd(2, y);
17756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        } else {
17856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var invC = 1/c;
17956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var k=0 ; k<iterations; k++) {
18056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                for (var j=1 ; j <= height; j++) {
18156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    var lastRow = (j - 1) * rowSize;
18256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    var currentRow = j * rowSize;
18356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    var nextRow = (j + 1) * rowSize;
18456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    var lastX = x[currentRow];
18556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    var lastY = y[currentRow];
18656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    ++currentRow;
18756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    for (var i = 1; i <= width; i++) {
18856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                        lastX = x[currentRow] = (x0[currentRow] + a * (lastX + x[currentRow] + x[lastRow] + x[nextRow])) * invC;
18956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                        lastY = y[currentRow] = (y0[currentRow] + a * (lastY + y[++currentRow] + y[++lastRow] + y[++nextRow])) * invC;
19056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    }
19156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                }
19256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                set_bnd(1, x);
19356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                set_bnd(2, y);
19456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
19556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        }
19656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
19756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
19856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function diffuse2(x, x0, y, y0, dt)
19956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
20056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var a = 0;
20156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        lin_solve2(x, x0, y, y0, a, 1 + 4 * a);
20256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
20356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
20456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function advect(b, d, d0, u, v, dt)
20556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
20656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var Wdt0 = dt * width;
20756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var Hdt0 = dt * height;
20856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var Wp5 = width + 0.5;
20956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var Hp5 = height + 0.5;
21056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        for (var j = 1; j<= height; j++) {
21156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var pos = j * rowSize;
21256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var i = 1; i <= width; i++) {
21356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var x = i - Wdt0 * u[++pos];
21456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var y = j - Hdt0 * v[pos];
21556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                if (x < 0.5)
21656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    x = 0.5;
21756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                else if (x > Wp5)
21856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    x = Wp5;
21956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var i0 = x | 0;
22056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var i1 = i0 + 1;
22156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                if (y < 0.5)
22256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    y = 0.5;
22356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                else if (y > Hp5)
22456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                    y = Hp5;
22556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var j0 = y | 0;
22656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var j1 = j0 + 1;
22756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var s1 = x - i0;
22856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var s0 = 1 - s1;
22956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var t1 = y - j0;
23056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var t0 = 1 - t1;
23156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var row1 = j0 * rowSize;
23256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                var row2 = j1 * rowSize;
23356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                d[pos] = s0 * (t0 * d0[i0 + row1] + t1 * d0[i0 + row2]) + s1 * (t0 * d0[i1 + row1] + t1 * d0[i1 + row2]);
23456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
23556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        }
23656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        set_bnd(b, d);
23756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
23856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
23956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function project(u, v, p, div)
24056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
24156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var h = -0.5 / Math.sqrt(width * height);
24256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        for (var j = 1 ; j <= height; j++ ) {
24356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var row = j * rowSize;
24456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var previousRow = (j - 1) * rowSize;
24556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var prevValue = row - 1;
24656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var currentRow = row;
24756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var nextValue = row + 1;
24856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var nextRow = (j + 1) * rowSize;
24956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var i = 1; i <= width; i++ ) {
25056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                div[++currentRow] = h * (u[++nextValue] - u[++prevValue] + v[++nextRow] - v[++previousRow]);
25156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                p[currentRow] = 0;
25256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
25356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        }
25456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        set_bnd(0, div);
25556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        set_bnd(0, p);
25656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
25756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        lin_solve(0, p, div, 1, 4 );
25856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var wScale = 0.5 * width;
25956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var hScale = 0.5 * height;
26056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        for (var j = 1; j<= height; j++ ) {
26156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var prevPos = j * rowSize - 1;
26256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var currentPos = j * rowSize;
26356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var nextPos = j * rowSize + 1;
26456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var prevRow = (j - 1) * rowSize;
26556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var currentRow = j * rowSize;
26656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            var nextRow = (j + 1) * rowSize;
26756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
26856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            for (var i = 1; i<= width; i++) {
26956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                u[++currentPos] -= wScale * (p[++nextPos] - p[++prevPos]);
27056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org                v[currentPos]   -= hScale * (p[++nextRow] - p[++prevRow]);
27156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            }
27256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        }
27356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        set_bnd(1, u);
27456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        set_bnd(2, v);
27556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
27656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
27756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function dens_step(x, x0, u, v, dt)
27856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
27956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        addFields(x, x0, dt);
28056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        diffuse(0, x0, x, dt );
28156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        advect(0, x, x0, u, v, dt );
28256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
28356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
28456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function vel_step(u, v, u0, v0, dt)
28556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
28656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        addFields(u, u0, dt );
28756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        addFields(v, v0, dt );
28856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var temp = u0; u0 = u; u = temp;
28956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var temp = v0; v0 = v; v = temp;
29056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        diffuse2(u,u0,v,v0, dt);
29156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        project(u, v, u0, v0);
29256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var temp = u0; u0 = u; u = temp;
29356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var temp = v0; v0 = v; v = temp;
29456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        advect(1, u, u0, u0, v0, dt);
29556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        advect(2, v, v0, u0, v0, dt);
29656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        project(u, v, u0, v0 );
29756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
29856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var uiCallback = function(d,u,v) {};
29956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
30056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function Field(dens, u, v) {
30156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        // Just exposing the fields here rather than using accessors is a measurable win during display (maybe 5%)
30256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        // but makes the code ugly.
30356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        this.setDensity = function(x, y, d) {
30456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org             dens[(x + 1) + (y + 1) * rowSize] = d;
30556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        }
30656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        this.getDensity = function(x, y) {
30756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org             return dens[(x + 1) + (y + 1) * rowSize];
30856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        }
30956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        this.setVelocity = function(x, y, xv, yv) {
31056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org             u[(x + 1) + (y + 1) * rowSize] = xv;
31156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org             v[(x + 1) + (y + 1) * rowSize] = yv;
31256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        }
31356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        this.getXVelocity = function(x, y) {
31456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org             return u[(x + 1) + (y + 1) * rowSize];
31556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        }
31656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        this.getYVelocity = function(x, y) {
31756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org             return v[(x + 1) + (y + 1) * rowSize];
31856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        }
31956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        this.width = function() { return width; }
32056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        this.height = function() { return height; }
32156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
32256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function queryUI(d, u, v)
32356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
32456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        for (var i = 0; i < size; i++)
32556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            u[i] = v[i] = d[i] = 0.0;
32656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        uiCallback(new Field(d, u, v));
32756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
32856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
32956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    this.update = function () {
33056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        queryUI(dens_prev, u_prev, v_prev);
33156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        vel_step(u, v, u_prev, v_prev, dt);
33256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        dens_step(dens, dens_prev, u, v, dt);
33356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        displayFunc(new Field(dens, u, v));
33456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
33556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    this.setDisplayFunction = function(func) {
33656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        displayFunc = func;
33756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
33856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
33956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    this.iterations = function() { return iterations; }
34056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    this.setIterations = function(iters) {
34156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        if (iters > 0 && iters <= 100)
34256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org           iterations = iters;
34356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
34456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    this.setUICallback = function(callback) {
34556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        uiCallback = callback;
34656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
34756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var iterations = 10;
34856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var visc = 0.5;
34956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var dt = 0.1;
35056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var dens;
35156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var dens_prev;
35256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var u;
35356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var u_prev;
35456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var v;
35556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var v_prev;
35656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var width;
35756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var height;
35856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var rowSize;
35956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var size;
36056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    var displayFunc;
36156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    function reset()
36256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
36356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        rowSize = width + 2;
36456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        size = (width+2)*(height+2);
36556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        dens = new Array(size);
36656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        dens_prev = new Array(size);
36756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        u = new Array(size);
36856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        u_prev = new Array(size);
36956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        v = new Array(size);
37056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        v_prev = new Array(size);
37156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        for (var i = 0; i < size; i++)
37256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            dens_prev[i] = u_prev[i] = v_prev[i] = dens[i] = u[i] = v[i] = 0;
37356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
37456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    this.reset = reset;
37556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    this.setResolution = function (hRes, wRes)
37656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    {
37756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        var res = wRes * hRes;
37856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        if (res > 0 && res < 1000000 && (wRes != width || hRes != height)) {
37956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            width = wRes;
38056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            height = hRes;
38156454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            reset();
38256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org            return true;
38356454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        }
38456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org        return false;
38556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
38656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    this.setResolution(64, 64);
38756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org}
388