/**
* Copyright 2012 the V8 project authors . All rights reserved .
* Copyright 2009 Oliver Hunt < http : //nerget.com>
*
* Permission is hereby granted , free of charge , to any person
* obtaining a copy of this software and associated documentation
* files ( the " Software " ) , to deal in the Software without
* restriction , including without limitation the rights to use ,
* copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following
* conditions :
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND ,
* EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY ,
* WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE .
*/
var NavierStokes =
new BenchmarkSuite(
'NavierStokes' ,
1484000 ,
[
new Benchmark(
'NavierStokes' ,
runNavierStokes,
setupNavierStokes,
tearDownNavierStokes)]);
var solver =
null ;
function runNavierStokes()
{
solver.update();
}
function setupNavierStokes()
{
solver =
new FluidField(
null );
solver.setResolution(
128 ,
128 );
solver.setIterations(
20 );
solver.setDisplayFunction(
function (){});
solver.setUICallback(prepareFrame);
solver.reset();
}
function tearDownNavierStokes()
{
solver =
null ;
}
function addPoints(field) {
var n =
64 ;
for (
var i =
1 ; i <= n; i++) {
field.setVelocity(i, i, n, n);
field.setDensity(i, i,
5 );
field.setVelocity(i, n - i, -n, -n);
field.setDensity(i, n - i,
20 );
field.setVelocity(
128 - i, n + i, -n, -n);
field.setDensity(
128 - i, n + i,
30 );
}
}
var framesTillAddingPoints =
0 ;
var framesBetweenAddingPoints =
5 ;
function prepareFrame(field)
{
if (framesTillAddingPoints ==
0 ) {
addPoints(field);
framesTillAddingPoints = framesBetweenAddingPoints;
framesBetweenAddingPoints++;
}
else {
framesTillAddingPoints--;
}
}
// Code from Oliver Hunt (http://nerget.com/fluidSim/pressure.js) starts here.
function FluidField(canvas) {
function addFields(x, s, dt)
{
for (
var i=
0 ; i<size ; i++ ) x[i] += dt*s[i];
}
function set_bnd(b, x)
{
if (b===
1 ) {
for (
var i =
1 ; i <= width; i++) {
x[i] = x[i + rowSize];
x[i + (height+
1 ) *rowSize] = x[i + height * rowSize];
}
for (
var j =
1 ; i <= height; i++) {
x[j * rowSize] = -x[
1 + j * rowSize];
x[(width +
1 ) + j * rowSize] = -x[width + j * rowSize];
}
}
else if (b ===
2 ) {
for (
var i =
1 ; i <= width; i++) {
x[i] = -x[i + rowSize];
x[i + (height +
1 ) * rowSize] = -x[i + height * rowSize];
}
for (
var j =
1 ; j <= height; j++) {
x[j * rowSize] = x[
1 + j * rowSize];
x[(width +
1 ) + j * rowSize] = x[width + j * rowSize];
}
}
else {
for (
var i =
1 ; i <= width; i++) {
x[i] = x[i + rowSize];
x[i + (height +
1 ) * rowSize] = x[i + height * rowSize];
}
for (
var j =
1 ; j <= height; j++) {
x[j * rowSize] = x[
1 + j * rowSize];
x[(width +
1 ) + j * rowSize] = x[width + j * rowSize];
}
}
var maxEdge = (height +
1 ) * rowSize;
x[
0 ] =
0 .
5 * (x[
1 ] + x[rowSize]);
x[maxEdge] =
0 .
5 * (x[
1 + maxEdge] + x[height * rowSize]);
x[(width+
1 )] =
0 .
5 * (x[width] + x[(width +
1 ) + rowSize]);
x[(width+
1 )+maxEdge] =
0 .
5 * (x[width + maxEdge] + x[(width +
1 ) + height * rowSize]);
}
function lin_solve(b, x, x0, a, c)
{
if (a ===
0 && c ===
1 ) {
for (
var j=
1 ; j<=height; j++) {
var currentRow = j * rowSize;
++currentRow;
for (
var i =
0 ; i < width; i++) {
x[currentRow] = x0[currentRow];
++currentRow;
}
}
set_bnd(b, x);
}
else {
var invC =
1 / c;
for (
var k=
0 ; k<iterations; k++) {
for (
var j=
1 ; j<=height; j++) {
var lastRow = (j -
1 ) * rowSize;
var currentRow = j * rowSize;
var nextRow = (j +
1 ) * rowSize;
var lastX = x[currentRow];
++currentRow;
for (
var i=
1 ; i<=width; i++)
lastX = x[currentRow] = (x0[currentRow] + a*(lastX+x[++currentRow]+x[++lastRow]+x[++ne
xtRow])) * invC;
}
set_bnd(b, x);
}
}
}
function diffuse(b, x, x0, dt)
{
var a = 0 ;
lin_solve(b, x, x0, a, 1 + 4 *a);
}
function lin_solve2(x, x0, y, y0, a, c)
{
if (a === 0 && c === 1 ) {
for (var j=1 ; j <= height; j++) {
var currentRow = j * rowSize;
++currentRow;
for (var i = 0 ; i < width; i++) {
x[currentRow] = x0[currentRow];
y[currentRow] = y0[currentRow];
++currentRow;
}
}
set_bnd(1 , x);
set_bnd(2 , y);
} else {
var invC = 1 /c;
for (var k=0 ; k<iterations; k++) {
for (var j=1 ; j <= height; j++) {
var lastRow = (j - 1 ) * rowSize;
var currentRow = j * rowSize;
var nextRow = (j + 1 ) * rowSize;
var lastX = x[currentRow];
var lastY = y[currentRow];
++currentRow;
for (var i = 1 ; i <= width; i++) {
lastX = x[currentRow] = (x0[currentRow] + a * (lastX + x[currentRow] + x[lastRow] + x[nextRow])) * invC;
lastY = y[currentRow] = (y0[currentRow] + a * (lastY + y[++currentRow] + y[++lastRow] + y[++nextRow])) * invC;
}
}
set_bnd(1 , x);
set_bnd(2 , y);
}
}
}
function diffuse2(x, x0, y, y0, dt)
{
var a = 0 ;
lin_solve2(x, x0, y, y0, a, 1 + 4 * a);
}
function advect(b, d, d0, u, v, dt)
{
var Wdt0 = dt * width;
var Hdt0 = dt * height;
var Wp5 = width + 0 .5 ;
var Hp5 = height + 0 .5 ;
for (var j = 1 ; j<= height; j++) {
var pos = j * rowSize;
for (var i = 1 ; i <= width; i++) {
var x = i - Wdt0 * u[++pos];
var y = j - Hdt0 * v[pos];
if (x < 0 .5 )
x = 0 .5 ;
else if (x > Wp5)
x = Wp5;
var i0 = x | 0 ;
var i1 = i0 + 1 ;
if (y < 0 .5 )
y = 0 .5 ;
else if (y > Hp5)
y = Hp5;
var j0 = y | 0 ;
var j1 = j0 + 1 ;
var s1 = x - i0;
var s0 = 1 - s1;
var t1 = y - j0;
var t0 = 1 - t1;
var row1 = j0 * rowSize;
var row2 = j1 * rowSize;
d[pos] = s0 * (t0 * d0[i0 + row1] + t1 * d0[i0 + row2]) + s1 * (t0 * d0[i1 + row1] + t1 * d0[i1 + row2]);
}
}
set_bnd(b, d);
}
function project(u, v, p, div)
{
var h = -0 .5 / Math.sqrt(width * height);
for (var j = 1 ; j <= height; j++ ) {
var row = j * rowSize;
var previousRow = (j - 1 ) * rowSize;
var prevValue = row - 1 ;
var currentRow = row;
var nextValue = row + 1 ;
var nextRow = (j + 1 ) * rowSize;
for (var i = 1 ; i <= width; i++ ) {
div[++currentRow] = h * (u[++nextValue] - u[++prevValue] + v[++nextRow] - v[++previousRow]);
p[currentRow] = 0 ;
}
}
set_bnd(0 , div);
set_bnd(0 , p);
lin_solve(0 , p, div, 1 , 4 );
var wScale = 0 .5 * width;
var hScale = 0 .5 * height;
for (var j = 1 ; j<= height; j++ ) {
var prevPos = j * rowSize - 1 ;
var currentPos = j * rowSize;
var nextPos = j * rowSize + 1 ;
var prevRow = (j - 1 ) * rowSize;
var currentRow = j * rowSize;
var nextRow = (j + 1 ) * rowSize;
for (var i = 1 ; i<= width; i++) {
u[++currentPos] -= wScale * (p[++nextPos] - p[++prevPos]);
v[currentPos] -= hScale * (p[++nextRow] - p[++prevRow]);
}
}
set_bnd(1 , u);
set_bnd(2 , v);
}
function dens_step(x, x0, u, v, dt)
{
addFields(x, x0, dt);
diffuse(0 , x0, x, dt );
advect(0 , x, x0, u, v, dt );
}
function vel_step(u, v, u0, v0, dt)
{
addFields(u, u0, dt );
addFields(v, v0, dt );
var temp = u0; u0 = u; u = temp;
var temp = v0; v0 = v; v = temp;
diffuse2(u,u0,v,v0, dt);
project(u, v, u0, v0);
var temp = u0; u0 = u; u = temp;
var temp = v0; v0 = v; v = temp;
advect(1 , u, u0, u0, v0, dt);
advect(2 , v, v0, u0, v0, dt);
project(u, v, u0, v0 );
}
var uiCallback = function (d,u,v) {};
function Field(dens, u, v) {
// Just exposing the fields here rather than using accessors is a measurable win during display (maybe 5%)
// but makes the code ugly.
this .setDensity = function (x, y, d) {
dens[(x + 1 ) + (y + 1 ) * rowSize] = d;
}
this .getDensity = function (x, y) {
return dens[(x + 1 ) + (y + 1 ) * rowSize];
}
this .setVelocity = function (x, y, xv, yv) {
u[(x + 1 ) + (y + 1 ) * rowSize] = xv;
v[(x + 1 ) + (y + 1 ) * rowSize] = yv;
}
this .getXVelocity = function (x, y) {
return u[(x + 1 ) + (y + 1 ) * rowSize];
}
this .getYVelocity = function (x, y) {
return v[(x + 1 ) + (y + 1 ) * rowSize];
}
this .width = function () { return width; }
this .height = function () { return height; }
}
function queryUI(d, u, v)
{
for (var i = 0 ; i < size; i++)
u[i] = v[i] = d[i] = 0 .0 ;
uiCallback(new Field(d, u, v));
}
this .update = function () {
queryUI(dens_prev, u_prev, v_prev);
vel_step(u, v, u_prev, v_prev, dt);
dens_step(dens, dens_prev, u, v, dt);
displayFunc(new Field(dens, u, v));
}
this .setDisplayFunction = function (func) {
displayFunc = func;
}
this .iterations = function () { return iterations; }
this .setIterations = function (iters) {
if (iters > 0 && iters <= 100 )
iterations = iters;
}
this .setUICallback = function (callback) {
uiCallback = callback;
}
var iterations = 10 ;
var visc = 0 .5 ;
var dt = 0 .1 ;
var dens;
var dens_prev;
var u;
var u_prev;
var v;
var v_prev;
var width;
var height;
var rowSize;
var size;
var displayFunc;
function reset()
{
rowSize = width + 2 ;
size = (width+2 )*(height+2 );
dens = new Array(size);
dens_prev = new Array(size);
u = new Array(size);
u_prev = new Array(size);
v = new Array(size);
v_prev = new Array(size);
for (var i = 0 ; i < size; i++)
dens_prev[i] = u_prev[i] = v_prev[i] = dens[i] = u[i] = v[i] = 0 ;
}
this .reset = reset;
this .setResolution = function (hRes, wRes)
{
var res = wRes * hRes;
if (res > 0 && res < 1000000 && (wRes != width || hRes != height)) {
width = wRes;
height = hRes;
reset();
return true ;
}
return false ;
}
this .setResolution(64 , 64 );
}
Messung V0.5 in Prozent C=96 H=96 G=95
¤ Dauer der Verarbeitung: 0.6 Sekunden
¤
*© Formatika GbR, Deutschland