Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 67 additions & 86 deletions tenMinutePhysics/17-fluidSim.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@
var V_FIELD = 1;
var S_FIELD = 2;

var cnt = 0;

function cX(x) {
return x * cScale;
}
Expand All @@ -105,52 +103,51 @@
this.m = new Float32Array(this.numCells);
this.newM = new Float32Array(this.numCells);
this.m.fill(1.0)
var num = numX * numY;
}

integrate(dt, gravity) {
var n = this.numY;
for (var i = 1; i < this.numX; i++) {
for (var j = 1; j < this.numY-1; j++) {
if (this.s[i*n + j] != 0.0 && this.s[i*n + j-1] != 0.0)
this.v[i*n + j] += gravity * dt;
const index = i*n + j;
if (this.s[index] != 0.0 && this.s[index-1] != 0.0)
this.v[index] += gravity * dt;
}
}
}

solveIncompressibility(numIters, dt) {

var n = this.numY;
var cp = this.density * this.h / dt;

for (var iter = 0; iter < numIters; iter++) {

for (var i = 1; i < this.numX-1; i++) {
for (var j = 1; j < this.numY-1; j++) {

if (this.s[i*n + j] == 0.0)
const index = i*n + j;
if (this.s[index] == 0.0)
continue;

var s = this.s[i*n + j];
var sx0 = this.s[(i-1)*n + j];
var sx1 = this.s[(i+1)*n + j];
var sy0 = this.s[i*n + j-1];
var sy1 = this.s[i*n + j+1];
var s = this.s[index];
var sx0 = this.s[index-n];
var sx1 = this.s[index+n];
var sy0 = this.s[index-1];
var sy1 = this.s[index+1];
var s = sx0 + sx1 + sy0 + sy1;
if (s == 0.0)
continue;

var div = this.u[(i+1)*n + j] - this.u[i*n + j] +
this.v[i*n + j+1] - this.v[i*n + j];
var div = this.u[index+n] - this.u[index] +
this.v[index+1] - this.v[index];

var p = -div / s;
p *= scene.overRelaxation;
this.p[i*n + j] += cp * p;
this.p[index] += cp * p;

this.u[i*n + j] -= sx0 * p;
this.u[(i+1)*n + j] += sx1 * p;
this.v[i*n + j] -= sy0 * p;
this.v[i*n + j+1] += sy1 * p;
this.u[index] -= sx0 * p;
this.u[index+n] += sx1 * p;
this.v[index] -= sy0 * p;
this.v[index+1] += sy1 * p;
}
}
}
Expand Down Expand Up @@ -186,7 +183,6 @@
case U_FIELD: f = this.u; dy = h2; break;
case V_FIELD: f = this.v; dx = h2; break;
case S_FIELD: f = this.m; dx = h2; dy = h2; break

}

var x0 = Math.min(Math.floor((x-dx)*h1), this.numX-1);
Expand All @@ -210,21 +206,21 @@

avgU(i, j) {
var n = this.numY;
var u = (this.u[i*n + j-1] + this.u[i*n + j] +
this.u[(i+1)*n + j-1] + this.u[(i+1)*n + j]) * 0.25;
const index = i*n + j;
var u = (this.u[index-1] + this.u[index] +
this.u[index+n-1] + this.u[index+n]) * 0.25;
return u;

}

avgV(i, j) {
var n = this.numY;
var v = (this.v[(i-1)*n + j] + this.v[i*n + j] +
this.v[(i-1)*n + j+1] + this.v[i*n + j+1]) * 0.25;
const index = i*n + j;
var v = (this.v[index-n] + this.v[index] +
this.v[index-n+1] + this.v[index+1]) * 0.25;
return v;
}

advectVel(dt) {

this.newU.set(this.u);
this.newV.set(this.v);

Expand All @@ -234,60 +230,56 @@

for (var i = 1; i < this.numX; i++) {
for (var j = 1; j < this.numY; j++) {

cnt++;

const index = i*n + j;
// u component
if (this.s[i*n + j] != 0.0 && this.s[(i-1)*n + j] != 0.0 && j < this.numY - 1) {
if (this.s[index] != 0.0 && this.s[index-n] != 0.0 && j < this.numY - 1) {
var x = i*h;
var y = j*h + h2;
var u = this.u[i*n + j];
var u = this.u[index];
var v = this.avgV(i, j);
// var v = this.sampleField(x,y, V_FIELD);
x = x - dt*u;
y = y - dt*v;
u = this.sampleField(x,y, U_FIELD);
this.newU[i*n + j] = u;
this.newU[index] = u;
}
// v component
if (this.s[i*n + j] != 0.0 && this.s[i*n + j-1] != 0.0 && i < this.numX - 1) {
if (this.s[index] != 0.0 && this.s[index-1] != 0.0 && i < this.numX - 1) {
var x = i*h + h2;
var y = j*h;
var u = this.avgU(i, j);
// var u = this.sampleField(x,y, U_FIELD);
var v = this.v[i*n + j];
var v = this.v[index];
x = x - dt*u;
y = y - dt*v;
v = this.sampleField(x,y, V_FIELD);
this.newV[i*n + j] = v;
this.newV[index] = v;
}
}
}
}

this.u.set(this.newU);
this.v.set(this.newV);
}

advectSmoke(dt) {

this.newM.set(this.m);

var n = this.numY;
var h = this.h;
var h2 = 0.5 * h;
const scaleFactor = dt * 0.5;

for (var i = 1; i < this.numX-1; i++) {
for (var j = 1; j < this.numY-1; j++) {

if (this.s[i*n + j] != 0.0) {
var u = (this.u[i*n + j] + this.u[(i+1)*n + j]) * 0.5;
var v = (this.v[i*n + j] + this.v[i*n + j+1]) * 0.5;
var x = i*h + h2 - dt*u;
var y = j*h + h2 - dt*v;

this.newM[i*n + j] = this.sampleField(x,y, S_FIELD);
}
}
const index = i*n + j;
if (this.s[index] != 0.0) {
var du = (this.u[index] + this.u[index+n]) * scaleFactor;
var dv = (this.v[index] + this.v[index+1]) * scaleFactor;
var x = i*h + h2 - du;
var y = j*h + h2 - dv;

this.newM[index] = this.sampleField(x,y, S_FIELD);
}
}
}
this.m.set(this.newM);
}
Expand Down Expand Up @@ -339,11 +331,12 @@

var res = 100;

if (sceneNr == 0)
if (sceneNr == 0) {
res = 50;
else if (sceneNr == 3)
} else if (sceneNr == 3) {
res = 200;

}

var domainHeight = 1.0;
var domainWidth = domainHeight / simHeight * simWidth;
var h = domainHeight / res;
Expand All @@ -362,8 +355,9 @@
for (var i = 0; i < f.numX; i++) {
for (var j = 0; j < f.numY; j++) {
var s = 1.0; // fluid
if (i == 0 || i == f.numX-1 || j == 0)
if (i == 0 || i == f.numX-1 || j == 0) {
s = 0.0; // solid
}
f.s[i*n + j] = s
}
}
Expand All @@ -379,8 +373,9 @@
for (var i = 0; i < f.numX; i++) {
for (var j = 0; j < f.numY; j++) {
var s = 1.0; // fluid
if (i == 0 || j == 0 || j == f.numY-1)
if (i == 0 || j == 0 || j == f.numY-1) {
s = 0.0; // solid
}
f.s[i*n + j] = s

if (i == 1) {
Expand Down Expand Up @@ -433,17 +428,6 @@

// draw -------------------------------------------------------

function setColor(r,g,b) {
c.fillStyle = `rgb(
${Math.floor(255*r)},
${Math.floor(255*g)},
${Math.floor(255*b)})`
c.strokeStyle = `rgb(
${Math.floor(255*r)},
${Math.floor(255*g)},
${Math.floor(255*b)})`
}

function getSciColor(val, minVal, maxVal) {
val = Math.min(Math.max(val, minVal), maxVal- 0.0001);
var d = maxVal - minVal;
Expand Down Expand Up @@ -472,8 +456,9 @@
n = f.numY;

var cellScale = 1.1;

var h = f.h;
var cx = Math.floor(cScale * cellScale * h) + 1;
var cy = Math.floor(cScale * cellScale * h) + 1;

minP = f.p[0];
maxP = f.p[0];
Expand All @@ -488,11 +473,13 @@
var color = [255, 255, 255, 255]

for (var i = 0; i < f.numX; i++) {
var x = Math.floor(cX(i * h));
for (var j = 0; j < f.numY; j++) {

const index = i*n + j;
if (scene.showPressure) {
var p = f.p[i*n + j];
var s = f.m[i*n + j];
var p = f.p[index];
var s = f.m[index];
color = getSciColor(p, minP, maxP);
if (scene.showSmoke) {
color[0] = Math.max(0.0, color[0] - 255*s);
Expand All @@ -501,23 +488,20 @@
}
}
else if (scene.showSmoke) {
var s = f.m[i*n + j];
color[0] = 255*s;
color[1] = 255*s;
color[2] = 255*s;
var v = f.m[index] * 255;
color[0] = v;
color[1] = v;
color[2] = v;
if (scene.sceneNr == 2)
color = getSciColor(s, 0.0, 1.0);
}
else if (f.s[i*n + j] == 0.0) {
else if (f.s[index] == 0.0) {
color[0] = 0;
color[1] = 0;
color[2] = 0;
}

var x = Math.floor(cX(i * h));
var y = Math.floor(cY((j+1) * h));
var cx = Math.floor(cScale * cellScale * h) + 1;
var cy = Math.floor(cScale * cellScale * h) + 1;

r = color[0];
g = color[1];
Expand All @@ -544,14 +528,14 @@
scale = 0.02;

for (var i = 0; i < f.numX; i++) {
x0 = cX(i * h);
for (var j = 0; j < f.numY; j++) {

var u = f.u[i*n + j];
var v = f.v[i*n + j];
const index = i*n + j;
var u = f.u[index];
var v = f.v[index];

c.beginPath();

x0 = cX(i * h);
x1 = cX(i * h + u * scale);
y = cY((j + 0.5) * h );

Expand All @@ -574,7 +558,6 @@

if (scene.showStreamlines) {

var segLen = f.h * 0.2;
var numSegs = 15;

c.strokeStyle = "#000000";
Expand All @@ -592,8 +575,6 @@
var u = f.sampleField(x, y, U_FIELD);
var v = f.sampleField(x, y, V_FIELD);
l = Math.sqrt(u*u + v*v);
// x += u/l * segLen;
// y += v/l * segLen;
x += u * 0.01;
y += v * 0.01;
if (x > f.numX * f.h)
Expand All @@ -608,7 +589,6 @@

if (scene.showObstacle) {

c.strokeW
r = scene.obstacleRadius + f.h;
if (scene.showPressure)
c.fillStyle = "#000000";
Expand Down Expand Up @@ -760,9 +740,10 @@

function simulate()
{
if (!scene.paused)
if (!scene.paused) {
scene.fluid.simulate(scene.dt, scene.gravity, scene.numIters)
scene.frameNr++;
}
}

function update() {
Expand Down