Skip to content

Commit e56d735

Browse files
committed
Updated fluid dynamic chapter
1 parent 4b0bac3 commit e56d735

File tree

3 files changed

+45
-9
lines changed

3 files changed

+45
-9
lines changed

book/code-vectorization.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,11 +558,12 @@ and added a power normalized colormap (gamma=0.3) as well as light shading.
558558
.. admonition:: **Figure 4**
559559
:class: legend
560560

561-
The Mandelbrot set using recount normalization, power
561+
The Mandelbrot as rendered by maplotlib using recount normalization, power
562562
normalized colormap (gamma=0.3) and light shading.
563563

564564
.. figure:: ../data/mandelbrot.png
565565
:width: 100%
566+
:class: bordered
566567

567568

568569

book/problem-vectorization.rst

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,8 @@ cell new value is computed as the maximum value between the current cell value
362362
and the discounted (gamma=0.9 in the case below) 4 neighbour values. The
363363
process start as soon as the starting node value become strictly positive.
364364

365-
The numpy implementation is straightforward and we can take advanage of the
366-
`scipy.ndimage.generic_filter` for the diffusion process:
365+
The numpy implementation is straightforward if we take advantage of the
366+
`generic_filter` (from `scipy.ndimage`) for the diffusion process:
367367

368368
.. code:: python
369369
@@ -387,8 +387,8 @@ The numpy implementation is straightforward and we can take advanage of the
387387
[1, 1, 1],
388388
[0, 1, 0]])
389389
390-
But this is actually slow and it's better to cook-up our own solution, reusing
391-
part of the game of life code:
390+
But in this specific case, it is rather slow we'd better to cook-up our own
391+
solution, reusing part of the game of life code:
392392

393393
.. code:: python
394394
@@ -446,6 +446,8 @@ References
446446
Fluid Dynamics
447447
--------------
448448

449+
450+
449451
.. admonition:: **Figure 9**
450452
:class: legend
451453

@@ -457,7 +459,6 @@ Fluid Dynamics
457459
:width: 100%
458460

459461

460-
461462
Lagrangian vs Eulerian method
462463
+++++++++++++++++++++++++++++
463464

@@ -477,11 +478,45 @@ motion that focuses on specific locations in the space through which the fluid
477478
flows as time passes. This can be visualized by sitting on the bank of a river
478479
and watching the water pass the fixed location.
479480

481+
In other words, in the Eulerian case, you divide a portion of space into cells
482+
and each cell contains a velocity vector and other information, such as density
483+
and temperature. In the Lagrangian case, we need particle-based physics with
484+
dynamic interactions and generally we need a high number of particles. Both
485+
methods have advantages and disadvantages and the choice between the two
486+
methods depends on the nature of your problem. Of course, you can also mix the
487+
two methods into an hybrid method.
488+
489+
However, the biggest problem for particle based simulation is that particles
490+
interaction requires finding neighbouring particles and this has a cost as
491+
we've seen in the boids case. If we target Python and Numpy only, we probably
492+
better choose the Eulerian method since vectorization will be almost trivial
493+
compared to the Lagrangian method.
480494

481495

482496
Numpy implementation
483497
++++++++++++++++++++
484498

499+
I won't explain all the theory behind computational fluid dynamic because
500+
first, I cannot (I'm not an expert at all in this domain) and there are many
501+
resources online that explain this nicely (have a look at references below,
502+
especially tutorial by L.Barba). Why choose a computational fluid as an example
503+
then? Because results are (almost) always beautiful and fascinating. I couldn't
504+
resist (look at movie belows).
505+
506+
We'll further simplify the problem by implementing a method from computer
507+
graphics where the goal is not correctness but convincing behavior. Jos Stam
508+
wrote a very nice article for SIGGRAPH 1999 describing a technique to have
509+
stable fluids over time (i.e. whose solution in the long term does not
510+
diverge). `Alberto Santini <https://github.com/albertosantini/python-fluid>`_
511+
wrote a Python replication a long time ago (using numarray!) such that I only
512+
had to adapt it to modern numpy and accelerate it a bit using modern numpy
513+
tricks.
514+
515+
I won't comment the code since it would be too long, but you can read the
516+
original paper as well as the explanation by `Philip Rideout
517+
<http://prideout.net/blog/?p=58>`_ on his blog. Below are some movies I've made
518+
using this technique.
519+
485520

486521
.. admonition:: **Figure 9**
487522
:class: legend
@@ -523,11 +558,11 @@ References
523558
* `Stable Fluids <http://www.dgp.toronto.edu/people/stam/reality/Research/pdf/ns.pdf>`_, Jos Stam, 1999.
524559
* `Simple Fluid Simulation <http://prideout.net/blog/?p=58>`_, Philip Rideout, 2010
525560
* `Fast Fluid Dynamics Simulation on the GPU <http://http.developer.nvidia.com/GPUGems/gpugems_ch38.html>`_, Mark Harris, 2004.
561+
* `Animating Sand as a Fluid <https://www.cs.ubc.ca/%7Erbridson/docs/zhu-siggraph05-sandfluid.pdf>`_, Yongning Zhu & Robert Bridson, 2005.
526562

527563

528-
529-
Poisson disk sampling
530-
---------------------
564+
Blue noise
565+
----------
531566

532567
.. admonition:: **Figure 10**
533568
:class: legend

data/cubes.png

-808 KB
Loading

0 commit comments

Comments
 (0)