13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch/** 23ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * Copyright 2012 the V8 project authors. All rights reserved. 33ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * Copyright 2009 Oliver Hunt <http://nerget.com> 43ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * 53ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * Permission is hereby granted, free of charge, to any person 63ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * obtaining a copy of this software and associated documentation 73ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * files (the "Software"), to deal in the Software without 83ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * restriction, including without limitation the rights to use, 93ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * copy, modify, merge, publish, distribute, sublicense, and/or sell 103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * copies of the Software, and to permit persons to whom the 113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * Software is furnished to do so, subject to the following 123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * conditions: 133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * 143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * The above copyright notice and this permission notice shall be 153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * included in all copies or substantial portions of the Software. 163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * 173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch * OTHER DEALINGS IN THE SOFTWARE. 253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch */ 263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar NavierStokes = new BenchmarkSuite('NavierStokes', 1484000, 283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch [new Benchmark('NavierStokes', 293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch runNavierStokes, 303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch setupNavierStokes, 313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch tearDownNavierStokes)]); 323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar solver = null; 343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochfunction runNavierStokes() 363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch{ 373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch solver.update(); 383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochfunction setupNavierStokes() 413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch{ 423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch solver = new FluidField(null); 433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch solver.setResolution(128, 128); 443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch solver.setIterations(20); 453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch solver.setDisplayFunction(function(){}); 463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch solver.setUICallback(prepareFrame); 473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch solver.reset(); 483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochfunction tearDownNavierStokes() 513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch{ 523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch solver = null; 533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochfunction addPoints(field) { 563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var n = 64; 573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i = 1; i <= n; i++) { 583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch field.setVelocity(i, i, n, n); 593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch field.setDensity(i, i, 5); 603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch field.setVelocity(i, n - i, -n, -n); 613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch field.setDensity(i, n - i, 20); 623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch field.setVelocity(128 - i, n + i, -n, -n); 633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch field.setDensity(128 - i, n + i, 30); 643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar framesTillAddingPoints = 0; 683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvar framesBetweenAddingPoints = 5; 693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochfunction prepareFrame(field) 713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch{ 723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (framesTillAddingPoints == 0) { 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch addPoints(field); 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch framesTillAddingPoints = framesBetweenAddingPoints; 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch framesBetweenAddingPoints++; 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch framesTillAddingPoints--; 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Code from Oliver Hunt (http://nerget.com/fluidSim/pressure.js) starts here. 823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochfunction FluidField(canvas) { 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function addFields(x, s, dt) 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i=0; i<size ; i++ ) x[i] += dt*s[i]; 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function set_bnd(b, x) 893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (b===1) { 913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i = 1; i <= width; i++) { 923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[i] = x[i + rowSize]; 933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[i + (height+1) *rowSize] = x[i + height * rowSize]; 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var j = 1; i <= height; i++) { 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[j * rowSize] = -x[1 + j * rowSize]; 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[(width + 1) + j * rowSize] = -x[width + j * rowSize]; 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (b === 2) { 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i = 1; i <= width; i++) { 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[i] = -x[i + rowSize]; 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[i + (height + 1) * rowSize] = -x[i + height * rowSize]; 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var j = 1; j <= height; j++) { 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[j * rowSize] = x[1 + j * rowSize]; 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[(width + 1) + j * rowSize] = x[width + j * rowSize]; 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i = 1; i <= width; i++) { 1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[i] = x[i + rowSize]; 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[i + (height + 1) * rowSize] = x[i + height * rowSize]; 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var j = 1; j <= height; j++) { 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[j * rowSize] = x[1 + j * rowSize]; 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[(width + 1) + j * rowSize] = x[width + j * rowSize]; 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var maxEdge = (height + 1) * rowSize; 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[0] = 0.5 * (x[1] + x[rowSize]); 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[maxEdge] = 0.5 * (x[1 + maxEdge] + x[height * rowSize]); 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[(width+1)] = 0.5 * (x[width] + x[(width + 1) + rowSize]); 1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[(width+1)+maxEdge] = 0.5 * (x[width + maxEdge] + x[(width + 1) + height * rowSize]); 1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function lin_solve(b, x, x0, a, c) 1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (a === 0 && c === 1) { 1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var j=1 ; j<=height; j++) { 1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var currentRow = j * rowSize; 1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++currentRow; 1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i = 0; i < width; i++) { 1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[currentRow] = x0[currentRow]; 1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++currentRow; 1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_bnd(b, x); 1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var invC = 1 / c; 1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var k=0 ; k<iterations; k++) { 1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var j=1 ; j<=height; j++) { 1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var lastRow = (j - 1) * rowSize; 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var currentRow = j * rowSize; 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var nextRow = (j + 1) * rowSize; 1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var lastX = x[currentRow]; 1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++currentRow; 1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i=1; i<=width; i++) 1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lastX = x[currentRow] = (x0[currentRow] + a*(lastX+x[++currentRow]+x[++lastRow]+x[++nextRow])) * invC; 1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_bnd(b, x); 1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function diffuse(b, x, x0, dt) 1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var a = 0; 1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lin_solve(b, x, x0, a, 1 + 4*a); 1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function lin_solve2(x, x0, y, y0, a, c) 1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (a === 0 && c === 1) { 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var j=1 ; j <= height; j++) { 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var currentRow = j * rowSize; 1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++currentRow; 1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i = 0; i < width; i++) { 1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x[currentRow] = x0[currentRow]; 1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch y[currentRow] = y0[currentRow]; 1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++currentRow; 1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_bnd(1, x); 1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_bnd(2, y); 1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var invC = 1/c; 1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var k=0 ; k<iterations; k++) { 1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var j=1 ; j <= height; j++) { 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var lastRow = (j - 1) * rowSize; 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var currentRow = j * rowSize; 1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var nextRow = (j + 1) * rowSize; 1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var lastX = x[currentRow]; 1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var lastY = y[currentRow]; 1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++currentRow; 1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i = 1; i <= width; i++) { 1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lastX = x[currentRow] = (x0[currentRow] + a * (lastX + x[currentRow] + x[lastRow] + x[nextRow])) * invC; 1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lastY = y[currentRow] = (y0[currentRow] + a * (lastY + y[++currentRow] + y[++lastRow] + y[++nextRow])) * invC; 1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_bnd(1, x); 1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_bnd(2, y); 1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function diffuse2(x, x0, y, y0, dt) 1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var a = 0; 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lin_solve2(x, x0, y, y0, a, 1 + 4 * a); 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function advect(b, d, d0, u, v, dt) 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var Wdt0 = dt * width; 2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var Hdt0 = dt * height; 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var Wp5 = width + 0.5; 2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var Hp5 = height + 0.5; 2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var j = 1; j<= height; j++) { 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var pos = j * rowSize; 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i = 1; i <= width; i++) { 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var x = i - Wdt0 * u[++pos]; 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var y = j - Hdt0 * v[pos]; 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (x < 0.5) 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x = 0.5; 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch else if (x > Wp5) 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch x = Wp5; 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var i0 = x | 0; 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var i1 = i0 + 1; 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (y < 0.5) 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch y = 0.5; 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch else if (y > Hp5) 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch y = Hp5; 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var j0 = y | 0; 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var j1 = j0 + 1; 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var s1 = x - i0; 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var s0 = 1 - s1; 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var t1 = y - j0; 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var t0 = 1 - t1; 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var row1 = j0 * rowSize; 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var row2 = j1 * rowSize; 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch d[pos] = s0 * (t0 * d0[i0 + row1] + t1 * d0[i0 + row2]) + s1 * (t0 * d0[i1 + row1] + t1 * d0[i1 + row2]); 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_bnd(b, d); 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function project(u, v, p, div) 2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var h = -0.5 / Math.sqrt(width * height); 2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var j = 1 ; j <= height; j++ ) { 2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var row = j * rowSize; 2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var previousRow = (j - 1) * rowSize; 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var prevValue = row - 1; 2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var currentRow = row; 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var nextValue = row + 1; 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var nextRow = (j + 1) * rowSize; 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i = 1; i <= width; i++ ) { 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch div[++currentRow] = h * (u[++nextValue] - u[++prevValue] + v[++nextRow] - v[++previousRow]); 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch p[currentRow] = 0; 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_bnd(0, div); 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_bnd(0, p); 2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lin_solve(0, p, div, 1, 4 ); 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var wScale = 0.5 * width; 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var hScale = 0.5 * height; 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var j = 1; j<= height; j++ ) { 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var prevPos = j * rowSize - 1; 2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var currentPos = j * rowSize; 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var nextPos = j * rowSize + 1; 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var prevRow = (j - 1) * rowSize; 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var currentRow = j * rowSize; 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var nextRow = (j + 1) * rowSize; 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i = 1; i<= width; i++) { 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch u[++currentPos] -= wScale * (p[++nextPos] - p[++prevPos]); 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch v[currentPos] -= hScale * (p[++nextRow] - p[++prevRow]); 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_bnd(1, u); 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_bnd(2, v); 2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function dens_step(x, x0, u, v, dt) 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch addFields(x, x0, dt); 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch diffuse(0, x0, x, dt ); 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch advect(0, x, x0, u, v, dt ); 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function vel_step(u, v, u0, v0, dt) 2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch addFields(u, u0, dt ); 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch addFields(v, v0, dt ); 2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var temp = u0; u0 = u; u = temp; 2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var temp = v0; v0 = v; v = temp; 2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch diffuse2(u,u0,v,v0, dt); 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch project(u, v, u0, v0); 2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var temp = u0; u0 = u; u = temp; 2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var temp = v0; v0 = v; v = temp; 2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch advect(1, u, u0, u0, v0, dt); 2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch advect(2, v, v0, u0, v0, dt); 2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch project(u, v, u0, v0 ); 2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var uiCallback = function(d,u,v) {}; 2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function Field(dens, u, v) { 3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Just exposing the fields here rather than using accessors is a measurable win during display (maybe 5%) 3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // but makes the code ugly. 3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.setDensity = function(x, y, d) { 3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch dens[(x + 1) + (y + 1) * rowSize] = d; 3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.getDensity = function(x, y) { 3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return dens[(x + 1) + (y + 1) * rowSize]; 3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.setVelocity = function(x, y, xv, yv) { 3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch u[(x + 1) + (y + 1) * rowSize] = xv; 3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch v[(x + 1) + (y + 1) * rowSize] = yv; 3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.getXVelocity = function(x, y) { 3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return u[(x + 1) + (y + 1) * rowSize]; 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.getYVelocity = function(x, y) { 3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return v[(x + 1) + (y + 1) * rowSize]; 3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.width = function() { return width; } 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.height = function() { return height; } 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function queryUI(d, u, v) 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i = 0; i < size; i++) 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch u[i] = v[i] = d[i] = 0.0; 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uiCallback(new Field(d, u, v)); 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.update = function () { 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch queryUI(dens_prev, u_prev, v_prev); 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch vel_step(u, v, u_prev, v_prev, dt); 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch dens_step(dens, dens_prev, u, v, dt); 3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch displayFunc(new Field(dens, u, v)); 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.setDisplayFunction = function(func) { 3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch displayFunc = func; 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.iterations = function() { return iterations; } 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.setIterations = function(iters) { 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (iters > 0 && iters <= 100) 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch iterations = iters; 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.setUICallback = function(callback) { 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uiCallback = callback; 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var iterations = 10; 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var visc = 0.5; 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var dt = 0.1; 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var dens; 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var dens_prev; 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var u; 3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var u_prev; 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var v; 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var v_prev; 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var width; 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var height; 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var rowSize; 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var size; 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var displayFunc; 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function reset() 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rowSize = width + 2; 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size = (width+2)*(height+2); 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch dens = new Array(size); 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch dens_prev = new Array(size); 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch u = new Array(size); 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch u_prev = new Array(size); 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch v = new Array(size); 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch v_prev = new Array(size); 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (var i = 0; i < size; i++) 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch dens_prev[i] = u_prev[i] = v_prev[i] = dens[i] = u[i] = v[i] = 0; 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.reset = reset; 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.setResolution = function (hRes, wRes) 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var res = wRes * hRes; 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (res > 0 && res < 1000000 && (wRes != width || hRes != height)) { 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch width = wRes; 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch height = hRes; 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reset(); 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this.setResolution(64, 64); 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 388