OLD | NEW |
---|---|
(Empty) | |
1 /** | |
2 * Copyright (c) 2012 the V8 project authors. All rights reserved. | |
3 * Copyright (c) 2009 Oliver Hunt <http://nerget.com> | |
4 * | |
5 * Permission is hereby granted, free of charge, to any person | |
6 * obtaining a copy of this software and associated documentation | |
7 * files (the "Software"), to deal in the Software without | |
8 * restriction, including without limitation the rights to use, | |
9 * copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 * copies of the Software, and to permit persons to whom the | |
11 * Software is furnished to do so, subject to the following | |
12 * conditions: | |
13 * | |
14 * The above copyright notice and this permission notice shall be | |
15 * included in all copies or substantial portions of the Software. | |
16 * | |
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
24 * OTHER DEALINGS IN THE SOFTWARE. | |
25 */ | |
26 | |
27 var NavierStokes = new BenchmarkSuite('Navier-Stokes', 1484000, | |
kasperl
2012/02/14 10:50:17
Maybe make the string NavierStokes instead of usin
kasperl
2012/02/14 10:50:17
Where did you get the 1484000 number from? You may
ulan
2012/02/14 13:17:12
Done.
ulan
2012/02/14 13:17:12
Done.
| |
28 [new Benchmark('Navier-Stokes', | |
29 runNavierStokes, | |
30 setupNavierStokes, | |
31 teardownNavierStokes)]); | |
32 | |
33 var solver = null; | |
34 | |
35 function runNavierStokes() | |
36 { | |
37 solver.update(); | |
38 } | |
39 | |
40 function setupNavierStokes() | |
41 { | |
42 solver = new FluidField(null); | |
43 solver.setResolution(128, 128); | |
44 solver.setIterations(20); | |
45 solver.setDisplayFunction(function(){}); | |
46 solver.setUICallback(prepareFrame); | |
47 solver.reset(); | |
48 } | |
49 | |
50 function teardownNavierStokes() | |
kasperl
2012/02/14 10:50:17
tearDownNavierStokes (tDNS not tdNS) to be consist
ulan
2012/02/14 13:17:12
Done.
| |
51 { | |
52 solver = null; | |
53 } | |
54 | |
55 function addPoints(field) { | |
56 var n = 64; | |
57 for (var i = 1; i <= n; i++) { | |
58 field.setVelocity(i, i, n, n); | |
59 field.setDensity(i, i, 5); | |
60 field.setVelocity(i, n - i, -n, -n); | |
61 field.setDensity(i, n - i, 20); | |
62 field.setVelocity(128 - i, n + i, -n, -n); | |
63 field.setDensity(128 - i, n + i, 30); | |
64 } | |
65 } | |
66 | |
67 var framesTillAddingPoints = 0; | |
68 var framesBetweenAddingPoints = 5; | |
69 | |
70 function prepareFrame(field) | |
71 { | |
72 if (framesTillAddingPoints == 0) { | |
73 addPoints(field); | |
74 framesTillAddingPoints = framesBetweenAddingPoints; | |
75 framesBetweenAddingPoints++; | |
76 } else { | |
77 framesTillAddingPoints--; | |
78 } | |
79 } | |
80 | |
81 // Code from Oliver Hunt (http://nerget.com/fluidSim/pressure.js) starts here. | |
82 function FluidField(canvas) { | |
83 function addFields(x, s, dt) | |
84 { | |
85 for (var i=0; i<size ; i++ ) x[i] += dt*s[i]; | |
86 } | |
87 | |
88 function set_bnd(b, x) | |
89 { | |
90 if (b===1) { | |
91 for (var i = 1; i <= width; i++) { | |
92 x[i] = x[i + rowSize]; | |
93 x[i + (height+1) *rowSize] = x[i + height * rowSize]; | |
94 } | |
95 | |
96 for (var j = 1; i <= height; i++) { | |
97 x[j * rowSize] = -x[1 + j * rowSize]; | |
98 x[(width + 1) + j * rowSize] = -x[width + j * rowSize]; | |
99 } | |
100 } else if (b === 2) { | |
101 for (var i = 1; i <= width; i++) { | |
102 x[i] = -x[i + rowSize]; | |
103 x[i + (height + 1) * rowSize] = -x[i + height * rowSize]; | |
104 } | |
105 | |
106 for (var j = 1; j <= height; j++) { | |
107 x[j * rowSize] = x[1 + j * rowSize]; | |
108 x[(width + 1) + j * rowSize] = x[width + j * rowSize]; | |
109 } | |
110 } else { | |
111 for (var i = 1; i <= width; i++) { | |
112 x[i] = x[i + rowSize]; | |
113 x[i + (height + 1) * rowSize] = x[i + height * rowSize]; | |
114 } | |
115 | |
116 for (var j = 1; j <= height; j++) { | |
117 x[j * rowSize] = x[1 + j * rowSize]; | |
118 x[(width + 1) + j * rowSize] = x[width + j * rowSize]; | |
119 } | |
120 } | |
121 var maxEdge = (height + 1) * rowSize; | |
122 x[0] = 0.5 * (x[1] + x[rowSize]); | |
123 x[maxEdge] = 0.5 * (x[1 + maxEdge] + x[height * rowSize]); | |
124 x[(width+1)] = 0.5 * (x[width] + x[(width + 1) + rowSize]); | |
125 x[(width+1)+maxEdge] = 0.5 * (x[width + maxEdge] + x[(width + 1) + heigh t * rowSize]); | |
126 } | |
127 | |
128 function lin_solve(b, x, x0, a, c) | |
129 { | |
130 if (a === 0 && c === 1) { | |
131 for (var j=1 ; j<=height; j++) { | |
132 var currentRow = j * rowSize; | |
133 ++currentRow; | |
134 for (var i = 0; i < width; i++) { | |
135 x[currentRow] = x0[currentRow]; | |
136 ++currentRow; | |
137 } | |
138 } | |
139 set_bnd(b, x); | |
140 } else { | |
141 var invC = 1 / c; | |
142 for (var k=0 ; k<iterations; k++) { | |
143 for (var j=1 ; j<=height; j++) { | |
144 var lastRow = (j - 1) * rowSize; | |
145 var currentRow = j * rowSize; | |
146 var nextRow = (j + 1) * rowSize; | |
147 var lastX = x[currentRow]; | |
148 ++currentRow; | |
149 for (var i=1; i<=width; i++) | |
150 lastX = x[currentRow] = (x0[currentRow] + a*(lastX+x[++c urrentRow]+x[++lastRow]+x[++nextRow])) * invC; | |
151 } | |
152 set_bnd(b, x); | |
153 } | |
154 } | |
155 } | |
156 | |
157 function diffuse(b, x, x0, dt) | |
158 { | |
159 var a = 0; | |
160 lin_solve(b, x, x0, a, 1 + 4*a); | |
161 } | |
162 | |
163 function lin_solve2(x, x0, y, y0, a, c) | |
164 { | |
165 if (a === 0 && c === 1) { | |
166 for (var j=1 ; j <= height; j++) { | |
167 var currentRow = j * rowSize; | |
168 ++currentRow; | |
169 for (var i = 0; i < width; i++) { | |
170 x[currentRow] = x0[currentRow]; | |
171 y[currentRow] = y0[currentRow]; | |
172 ++currentRow; | |
173 } | |
174 } | |
175 set_bnd(1, x); | |
176 set_bnd(2, y); | |
177 } else { | |
178 var invC = 1/c; | |
179 for (var k=0 ; k<iterations; k++) { | |
180 for (var j=1 ; j <= height; j++) { | |
181 var lastRow = (j - 1) * rowSize; | |
182 var currentRow = j * rowSize; | |
183 var nextRow = (j + 1) * rowSize; | |
184 var lastX = x[currentRow]; | |
185 var lastY = y[currentRow]; | |
186 ++currentRow; | |
187 for (var i = 1; i <= width; i++) { | |
188 lastX = x[currentRow] = (x0[currentRow] + a * (lastX + x [currentRow] + x[lastRow] + x[nextRow])) * invC; | |
189 lastY = y[currentRow] = (y0[currentRow] + a * (lastY + y [++currentRow] + y[++lastRow] + y[++nextRow])) * invC; | |
190 } | |
191 } | |
192 set_bnd(1, x); | |
193 set_bnd(2, y); | |
194 } | |
195 } | |
196 } | |
197 | |
198 function diffuse2(x, x0, y, y0, dt) | |
199 { | |
200 var a = 0; | |
201 lin_solve2(x, x0, y, y0, a, 1 + 4 * a); | |
202 } | |
203 | |
204 function advect(b, d, d0, u, v, dt) | |
205 { | |
206 var Wdt0 = dt * width; | |
207 var Hdt0 = dt * height; | |
208 var Wp5 = width + 0.5; | |
209 var Hp5 = height + 0.5; | |
210 for (var j = 1; j<= height; j++) { | |
211 var pos = j * rowSize; | |
212 for (var i = 1; i <= width; i++) { | |
213 var x = i - Wdt0 * u[++pos]; | |
214 var y = j - Hdt0 * v[pos]; | |
215 if (x < 0.5) | |
216 x = 0.5; | |
217 else if (x > Wp5) | |
218 x = Wp5; | |
219 var i0 = x | 0; | |
220 var i1 = i0 + 1; | |
221 if (y < 0.5) | |
222 y = 0.5; | |
223 else if (y > Hp5) | |
224 y = Hp5; | |
225 var j0 = y | 0; | |
226 var j1 = j0 + 1; | |
227 var s1 = x - i0; | |
228 var s0 = 1 - s1; | |
229 var t1 = y - j0; | |
230 var t0 = 1 - t1; | |
231 var row1 = j0 * rowSize; | |
232 var row2 = j1 * rowSize; | |
233 d[pos] = s0 * (t0 * d0[i0 + row1] + t1 * d0[i0 + row2]) + s1 * ( t0 * d0[i1 + row1] + t1 * d0[i1 + row2]); | |
234 } | |
235 } | |
236 set_bnd(b, d); | |
237 } | |
238 | |
239 function project(u, v, p, div) | |
240 { | |
241 var h = -0.5 / Math.sqrt(width * height); | |
242 for (var j = 1 ; j <= height; j++ ) { | |
243 var row = j * rowSize; | |
244 var previousRow = (j - 1) * rowSize; | |
245 var prevValue = row - 1; | |
246 var currentRow = row; | |
247 var nextValue = row + 1; | |
248 var nextRow = (j + 1) * rowSize; | |
249 for (var i = 1; i <= width; i++ ) { | |
250 div[++currentRow] = h * (u[++nextValue] - u[++prevValue] + v[++n extRow] - v[++previousRow]); | |
251 p[currentRow] = 0; | |
252 } | |
253 } | |
254 set_bnd(0, div); | |
255 set_bnd(0, p); | |
256 | |
257 lin_solve(0, p, div, 1, 4 ); | |
258 var wScale = 0.5 * width; | |
259 var hScale = 0.5 * height; | |
260 for (var j = 1; j<= height; j++ ) { | |
261 var prevPos = j * rowSize - 1; | |
262 var currentPos = j * rowSize; | |
263 var nextPos = j * rowSize + 1; | |
264 var prevRow = (j - 1) * rowSize; | |
265 var currentRow = j * rowSize; | |
266 var nextRow = (j + 1) * rowSize; | |
267 | |
268 for (var i = 1; i<= width; i++) { | |
269 u[++currentPos] -= wScale * (p[++nextPos] - p[++prevPos]); | |
270 v[currentPos] -= hScale * (p[++nextRow] - p[++prevRow]); | |
271 } | |
272 } | |
273 set_bnd(1, u); | |
274 set_bnd(2, v); | |
275 } | |
276 | |
277 function dens_step(x, x0, u, v, dt) | |
278 { | |
279 addFields(x, x0, dt); | |
280 diffuse(0, x0, x, dt ); | |
281 advect(0, x, x0, u, v, dt ); | |
282 } | |
283 | |
284 function vel_step(u, v, u0, v0, dt) | |
285 { | |
286 addFields(u, u0, dt ); | |
287 addFields(v, v0, dt ); | |
288 var temp = u0; u0 = u; u = temp; | |
289 var temp = v0; v0 = v; v = temp; | |
290 diffuse2(u,u0,v,v0, dt); | |
291 project(u, v, u0, v0); | |
292 var temp = u0; u0 = u; u = temp; | |
293 var temp = v0; v0 = v; v = temp; | |
294 advect(1, u, u0, u0, v0, dt); | |
295 advect(2, v, v0, u0, v0, dt); | |
296 project(u, v, u0, v0 ); | |
297 } | |
298 var uiCallback = function(d,u,v) {}; | |
299 | |
300 function Field(dens, u, v) { | |
301 // Just exposing the fields here rather than using accessors is a measur able win during display (maybe 5%) | |
302 // but makes the code ugly. | |
303 this.setDensity = function(x, y, d) { | |
304 dens[(x + 1) + (y + 1) * rowSize] = d; | |
305 } | |
306 this.getDensity = function(x, y) { | |
307 return dens[(x + 1) + (y + 1) * rowSize]; | |
308 } | |
309 this.setVelocity = function(x, y, xv, yv) { | |
310 u[(x + 1) + (y + 1) * rowSize] = xv; | |
311 v[(x + 1) + (y + 1) * rowSize] = yv; | |
312 } | |
313 this.getXVelocity = function(x, y) { | |
314 return u[(x + 1) + (y + 1) * rowSize]; | |
315 } | |
316 this.getYVelocity = function(x, y) { | |
317 return v[(x + 1) + (y + 1) * rowSize]; | |
318 } | |
319 this.width = function() { return width; } | |
320 this.height = function() { return height; } | |
321 } | |
322 function queryUI(d, u, v) | |
323 { | |
324 for (var i = 0; i < size; i++) | |
325 u[i] = v[i] = d[i] = 0.0; | |
326 uiCallback(new Field(d, u, v)); | |
327 } | |
328 | |
329 this.update = function () { | |
330 queryUI(dens_prev, u_prev, v_prev); | |
331 vel_step(u, v, u_prev, v_prev, dt); | |
332 dens_step(dens, dens_prev, u, v, dt); | |
333 displayFunc(new Field(dens, u, v)); | |
334 } | |
335 this.setDisplayFunction = function(func) { | |
336 displayFunc = func; | |
337 } | |
338 | |
339 this.iterations = function() { return iterations; } | |
340 this.setIterations = function(iters) { | |
341 if (iters > 0 && iters <= 100) | |
342 iterations = iters; | |
343 } | |
344 this.setUICallback = function(callback) { | |
345 uiCallback = callback; | |
346 } | |
347 var iterations = 10; | |
348 var visc = 0.5; | |
349 var dt = 0.1; | |
350 var dens; | |
351 var dens_prev; | |
352 var u; | |
353 var u_prev; | |
354 var v; | |
355 var v_prev; | |
356 var width; | |
357 var height; | |
358 var rowSize; | |
359 var size; | |
360 var displayFunc; | |
361 function reset() | |
362 { | |
363 rowSize = width + 2; | |
364 size = (width+2)*(height+2); | |
365 dens = new Array(size); | |
366 dens_prev = new Array(size); | |
367 u = new Array(size); | |
368 u_prev = new Array(size); | |
369 v = new Array(size); | |
370 v_prev = new Array(size); | |
371 for (var i = 0; i < size; i++) | |
372 dens_prev[i] = u_prev[i] = v_prev[i] = dens[i] = u[i] = v[i] = 0; | |
373 } | |
374 this.reset = reset; | |
375 this.setResolution = function (hRes, wRes) | |
376 { | |
377 var res = wRes * hRes; | |
378 if (res > 0 && res < 1000000 && (wRes != width || hRes != height)) { | |
379 width = wRes; | |
380 height = hRes; | |
381 reset(); | |
382 return true; | |
383 } | |
384 return false; | |
385 } | |
386 this.setResolution(64, 64); | |
387 } | |
OLD | NEW |