More fun with Lattice Boltzman Method (LBM) fluid simulations

Back in September 2010 I was experimenting with Lattice Boltzmann Method (LBM) fluid flows.

At that time I managed to translate some (probably Fortran) LBM source code provided by the now defunct “LB Method” website (here is how LB Method looked around that time). The algorithms worked and did give me some nice results, but there were problems like lack of detail and pulsating colors due to my display routines scaling minimum and maximum velocities to a color palette.

Yesterday I was looking around for some new LBM source code and found Daniel Schroeder‘s LBM page here. Daniel graciously shares the source code for his applet so I was able to convert his main LBM algorithms into something I could use in Visions of Chaos. Many thanks Dan!

Dan’s code was based on code by Alexander Wagner which you can see here including a PDF describing the LBM processes.

Using Dan’s code/algorithms was much faster than my older code. It also allows me to render much more finer detailed fluids without causing the system to blow out. I can push the simulation parameters further. Dan’s method of coloring solved the pulsing colors issue my older code had and includes a really nice way of visualizing the “curl” of the flowing fluid. Tracer particles are also used to follow the velocity of the underlying fluid to give another way of visualizing the fluid flow. Once particles leave the right side of the screen they are buffered up until they fill up and can be reinjected to the left side of the flow. Tracer particles help seeing the vortices easier than shading alone.

With less memory requirements (another plus from Dan’s code) I was able to render some nice 4K resolution LBM flows. This movie must be watched at 4K if possible as the compression of lower resolutions cannot handle displaying the tracer particles.

Years after the above movie was made I was revisiting the code to try and speed it up a bit by adding multi-threading support.  While doing this I found an error with the fluid collision code that caused incorrect results.

Have a look at the movie above and notice the initial part with flow past the three circles.  The curl patterns should initially be symmetric around the circles.  The background flow is an even speed from the left of the screen to the right.  Going around the circle should make the same shaped curls above and below the circles.  With a bit of tweaking I got the right bounce code working.  The next movie shows the corrected code results.

For that movie the fluid is visualized using only tracer particles.  Imagine a bunch of small confetti or glitter particles have been scattered on the fluid surface and are floating.  As the fluid flows it drags the floating tracer particles along with it.  This is a different way of seeing the curls and eddies the fluid forms as it flows past the various obstacles.

The next movie shows the fluid flow by displaying the curl of the fluid at each pixel location.

The new LBM code is now included with Visions of Chaos.

There are still some visual artifacts with this latest code and the maths can spontaneously explode crashing the simulation if the fluid speed is pushed too far or the viscosity is lowered too far.  The downside here is that you cannot get very detailed flows.  I will no doubt be revisiting LBM again in the future to experiment with new code and try to get more detailed (and faster) simulations running.

Jason.

Evolving Genetic Virtual Creatures

Inspiration

Back in 1994 Karl Sims developed his Evolved Virtual Creatures. More info here and here.

I have always found these sort of simulations fascinating, using the principals of genetics to evolve better solutions to a problem. For years I have wanted to try writing my own evolved creatures, but coding a physics engine to handle the movements and joints was beyond me so it was yet another entry on my to do list (until now).

2D Physics

For my virtual creatures I decided to start with 2D. I needed a general physics engine that takes care of all the individual world parts interacting and moving. Erin Catto’s Box2D has all the physics simulation features that I need to finally start experimenting with a 2D environment. Box2D is great. You only need some relatively simple coding to get the physics setup and then Box2D handles all the collisions etc for you.

Random Creatures

The creatures I am using are the simplest structures I could come up with that hopefully lead to some interesting movements. Creatures consist of three segments (rectangles) joined together by rotating (revolute joints in Box2D) joints. The size of the rectangle segments and joint rotation speeds are picked at random. Once the random creature is created it is set free into a virtual world to see what it does.

Virtual Creature

Many of them crunch up and go nowhere,

Virtual Creature

but some setups result in jumping and crawling creatures.

In only a few minutes thousands of random creatures can be setup and simulated. From these thousands the creatures that perform well are saved.

Performance Criteria

Once thousands of random virtual creatures have been created you need a way to pick the best ones. For these creatures I used three different criteria;

1. Distance traveled. The maximum X distance the creature travels in 5,000 time steps.

Virtual Creature

2. Distance crawled. The maximum X distance the creature travels in 5,000 time steps, but with a height restriction to weed out creatures that jump too high.

Virtual Creature

3. Height reached. The maximum Y height the creature reaches in 5,000 time steps.

Virtual Creature

The best picks become a set of creatures in the saved “gene pool”. If you have a large enough random set of creatures (say 10,000) and only take the top 10 performers then you do tend to get a set of creatures that perform the task well.

Mutations

Mutation takes a current “good creature” that passed criteria searching and scales segment length, segment width, joint rotation torque and joint rotation speed by a random percentage. The mutated creature is then run through 5,000 time steps and checked if it performs better than the original. If so, it is saved over the original and mutations continue. This process can be left to churn away for hours hands free and when the mutations are stopped you have a new set of best creatures.

For the creatures described here the features I randomly change are the segment widths and heights, the joint motor torques and the joint motor speeds (for 10 total attributes that can be tweaked by mutation). The user specifies a max mutation percentage and then each of the creature values are changed by


changepercentage:=maxmutationpercentage/100*random;
amount:=(MaxSegmentWidth-MinSegmentWidth)*changepercentage;
if random(2)=0 then amount:=-amount;
segmentwidth:=segmentwidth+amount;

The new attribute is clamped to a min and max value so as not to suddenly grow extremely long segments or super fast motors. You can also randomly mutate only 1 of the attributes rather than all 10 each mutation.

Choosing the right mutation amount can be tricky. Too high a random percentage and you may as well be randomly picking creatures. Too low a percentage and you will get very few mutations that beat the current creature. After some experimenting I am now using a mutation rate of 15% and mutating 3 of the attributes (ie a segment length, a motor’s torque, etc) each mutation.

Running on an i7-6800K CPU my current code can churn through up to 21 mutation tests per second. This screen shot shows 9 copies of Visions of Chaos running, each looking for mutations of different creature types, ie 3 segment distance, 4 segment height reached, etc etc.

Virtual Creatures

A mutation test requires the new mutated creature to be run for 5000 time steps and then comparing against its “parent” to see if it is better in the required fitness criteria (distance traveled, distance crawled or height reached).

Mutation Results

After mutating the best randomly found creatures for a while, this movie shows the best creature for distance traveled, distance crawled and height reached.

I will have to run the mutation searches overnight or for a few days to see if even better results are evolved.

4 Segment Creatures

Here are some results from evolving (mutating) 4 segment creatures. Same criteria of distance, crawl distance and height for best creatures. Note how only the white “arms” collide with each other. The grey “body” segments are set to pass through each other.

5 Segment Creatures

And finally, using 5 segments per creature. Only the 2 end arms collide with each other (otherwise the creatures always bunched up in a virtual knot and moved nowhere).

Availability

These Virtual Creatures are now included in the latest version of Visions of Chaos. I have also included the Box2D test bed to show some of the extra potential that I can use Box2D for in future creatures.

To Do

This is only the beginning. I have plenty of ideas for future improvements and expansions;

1. Using more than just mutations when evolving creatures. With more complex creatures crossover breeding could be experimented with.

2. Use more of the features of Box2D to create more complex creature setups. Arms and legs that “wave” back and forth like a fish tail rather than just spinning around.

3. 3D creatures and environments. I will need to find another physics engine supporting 3D hopefully as easily as Box2D supports 2D.

Jason.

2D Strange Attractors

Strange Attractors are plots of relatively simple formulas. They are created by repeating (or iterating) a formula over and over again and using the results at each iteration to plot a point. The result of each iteration is fed back into the equation. After millions of points have been plotted fractal structures appear. The repeated points fall within a basin of attraction (they are attracted to the points that make up these shapes).

I recently revisited my old strange attractor code in Visions of Chaos to add some new variations. This post will show many of the strange attractor formulas and some 4K resolution sample images they create. The images were created using over 1 billion points each. They have also been oversampled at least 3×3 pixels to reduce aliasing artifacts.

Bedhead Attractor

Discovered by Ivan Emrich.


x and y both start at 1.0

xnew=sin(x*y/b)*y+cos(a*x-y)
ynew=x+sin(y)/b

Variables a and b are floating point values bewteen -1 and +1

Bedhead Attractor

A=0.65343 B=0.7345345

Bedhead Attractor

A=-0.81 B=-0.92

Bedhead Attractor

A=-0.64 B=0.76

Bedhead Attractor

A=0.06 B=0.98

Bedhead Attractor

A=-0.67 B=0.83

Clifford Attractor

Discovered by Clifford A Pickover. I found them explained on Paul Bourke‘s page here.


x and y both start at 0.1

xnew=sin(a*y)+c*cos(a*x)
ynew=sin(b*x)+d*cos(b*y)

Variables a,b,c and d are floating point values bewteen -3 and +3

Clifford Attractor

A=-1.7 B=1.3 C=-0.1 D=-1.21

Clifford Attractor

A=-1.7 B=1.8 C=-0.9 D=-0.4

Clifford Attractor

A=1.5 B=-1.8 C=1.6 D=2

Clifford Attractor

A=-2.239 B=-2.956 C=1.272 D=1.419

Clifford Attractor

A=-1.7 B=1.8 C=-1.9 D=-0.4

Fractal Dream Attractor

Discovered by Clifford A Pickover and discussed in his book “Chaos In Wonderland”.


x and y both start at 0.1

xnew=sin(y*b)+c*sin(x*b)
ynew=sin(x*a)+d*sin(y*a)

Variables a and b are floating point values bewteen -3 and +3
Variables c and d are floating point values between -0.5 and +1.5

Fractal Dream Attractor

A=-0.966918 B=2.879879 C=0.765145 D=0.744728

Fractal Dream Attractor

A=-2.9585 B=-2.2965 C=-2.8829 D=-0.1622

Fractal Dream Attractor

A=-2.8276 B=1.2813 C=1.9655 D=0.597

Fractal Dream Attractor

A=-1.1554 B=-2.3419 C=-1.9799 D=2.1828

Fractal Dream Attractor

A=-1.9956 B=-1.4528 C=-2.6206 D=0.8517

Gumowski-Mira Attractor

The Gumowski-Mira equation was developed in 1980 at CERN by I. Gumowski and C. Mira to calculate the trajectories of sub-atomic particles. It can also be used to create attractor images.


x and y both start at any floating point value between -20 and +20

t=x
xnew=b*y+w
w=a*x+(1-a)*2*x*x/(1+x*x)
ynew=w-t

The a and b parameters can be any floating point value between -1 and +1.

Gumowski Mira Attractor

Initial X=0 Initial Y=0.5 A=0.008 B=-0.7

Gumowski Mira Attractor

Initial X=-0.723135391715914 Initial Y=-0.327585775405169 A=0.79253300698474 B=0.345703079365194

Gumowski Mira Attractor

Initial X=-0.312847771216184 Initial Y=-0.710899183526635 A=0.579161538276821 B=-0.820410779677331

Gumowski Mira Attractor

Initial X=-0.325819793157279 Initial Y=0.48573582014069 A=0.062683217227459 B=-0.436713613104075

Gumowski Mira Attractor

Initial X=0.78662442881614 Initial Y=0.919355855789036 A=0.900278024375439 B=0.661233567167073

Hopalong Attractor

The Hopalong attractor was discovered by Barry Martin.


x and y both start at 0

xnew=y-1-sqrt(abs(b*x-1-c))*sign(x-1)
ynew=a-x-1

The parameters a, b and c can be any floating point value between 0 and +10.

Hopalong Attractor

A=7.16878197155893 B=8.43659746693447 C=2.55983412731439

Hopalong Attractor

A=7.7867514709942 B=0.132189802825451 C=8.14610984409228

Hopalong Attractor

A=9.74546888144687 B=1.56320227775723 C=7.86818214459345

Hopalong Attractor

A=9.8724800767377 B=8.66862616268918 C=8.66950439289212

Hopalong Attractor

A=9.7671244922094 B=4.10973468795419 C=3.78332691499963

Jason Rampe 1

A variation I discovered while trying random formula changes.


x and y both start at 0.1

xnew=cos(y*b)+c*sin(x*b)
ynew=cos(x*a)+d*sin(y*a)

Variables a, b, c and d are floating point values between -3 and +3

Jason Rampe 1 Attractor

A=2.6 B=-2.5995 C=-2.9007 D=0.3565

Jason Rampe 1 Attractor

A=1.8285 B=-1.8539 C=0.3816 D=1.9765

Jason Rampe 1 Attractor

A=2.5425 B=2.8358 C=-0.8721 D=2.7044

Jason Rampe 1 Attractor

A=-1.8669 B=1.2768 C=-2.9296 D=-0.4121

Jason Rampe 1 Attractor

A=-2.7918 B=2.1196 C=1.0284 D=0.1384

Jason Rampe 2

Another variation I discovered while trying random formula changes.


x and y both start at 0.1

xnew=cos(y*b)+c*cos(x*b)
ynew=cos(x*a)+d*cos(y*a)

Variables a, b, c and d are floating point values between -3 and +3

Jason Rampe 2 Attractor

A=1.546 B=1.929 C=1.09 D=1.41

Jason Rampe 2 Attractor

A=2.907 B=-1.9472 C=1.2833 D=1.3206

Jason Rampe 2 Attractor

A=0.8875 B=0.7821 C=-2.3262 D=1.5379

Jason Rampe 2 Attractor

A=-2.4121 B=-1.0028 C=-2.2386 D=0.274

Jason Rampe 2 Attractor

A=-2.9581 B=0.927 C=2.7842 D=0.6267

Jason Rampe 3

Yet another variation I discovered while trying random formula changes.


x and y both start at 0.1

xnew=sin(y*b)+c*cos(x*b)
ynew=cos(x*a)+d*sin(y*a)

Variables a, b, c and d are floating point values between -3 and +3

Jason Rampe 3 Attractor

A=2.0246 B=-1.323 C=-2.8151 D=0.2277

Jason Rampe 3 Attractor

A=1.4662 B=-2.3632 C=-0.4167 D=2.4162

Jason Rampe 3 Attractor

A=-2.7564 B=-1.8234 C=2.8514 D=-0.8745

Jason Rampe 3 Attractor

A=-2.218 B=1.4318 C=-0.3346 D=2.4993

Jason Rampe 3 Attractor

A=1.2418 B=-2.4174 C=-0.7112 D=-1.9802

Johnny Svensson Attractor

See here.


x and y both start at 0.1

xnew=d*sin(x*a)-sin(y*b)
ynew=c*cos(x*a)+cos(y*b)

Variables a, b, c and d are floating point values between -3 and +3

Johnny Svensson Attractor

A=1.40 B=1.56 C=1.40 D=-6.56

Johnny Svensson Attractor

A=-2.538 B=1.362 C=1.315 D=0.513

Johnny Svensson Attractor

A=1.913 B=2.796 C=1.468 D=1.01

Johnny Svensson Attractor

A=-2.337 B=-2.337 C=0.533 D=1.378

Johnny Svensson Attractor

A=-2.722 B=2.574 C=1.284 D=1.043

Peter DeJong Attractor

See here.


x and y both start at 0.1

xnew=sin(y*a)-cos(x*b)
ynew=sin(x*c)-cos(y*d)

Variables a, b, c and d are floating point values between -3 and +3

Peter DeJong Attractor

A=0.970 B=-1.899 C=1.381 D=-1.506

Peter DeJong Attractor

A=1.4 B=-2.3 C=2.4 D=-2.1

Peter DeJong Attractor

A=2.01 B=-2.53 C=1.61 D=-0.33

Peter DeJong Attractor

A=-2.7 B=-0.09 C=-0.86 D=-2.2

Peter DeJong Attractor

A=-0.827 B=-1.637 C=1.659 D=-0.943

Peter DeJong Attractor

A=-2 B=-2 C=-1.2 D=2

Peter DeJong Attractor

A=-0.709 B=1.638 C=0.452 D=1.740

Symmetric Icon Attractor

These attractors came from the book “Symmetry in Chaos” by Michael Field and Martin Golubitsky. They give symmetric results to the attractors formed.


x and y both start at 0.01

zzbar=sqr(x)+sqr(y)
p=alpha*zzbar+lambda
zreal=x
zimag=y
for i=1 to degree-2 do
begin
     za=zreal*x-zimag*y
     zb=zimag*x+zreal*y
     zreal=za
     zimag=zb
end
zn=x*zreal-y*zimag
p=p+beta*zn
xnew=p*x+gamma*zreal-omega*y
ynew=p*y-gamma*zimag+omega*x
x=xnew
y=ynew

The Lambda, Alpha, Beta, Gamma, Omega and Degree parameters can be changed to create new plot shapes.

These sample images all come from paramters in the “Symmetry in Chaos” book.

Symmetric Icon - Chaotic Flower

L=-2.5 A=5 B=-1.9 G=1 O=0.188 D=5

Symmetric Icon - Clam Triple

L=1.56 A=-1 B=0.1 G=-0.82 O=0.12 D=3

Symmetric Icon - Emporer's Cloak

L=-1.806 A=1.806 B=0 G=1 O=0 D=5

Symmetric Icon - Fish and Eye

L=-2.195 A=10 B=-12 G=1 O=0 D=3

Symmetric Icon - Flintstone

L=2.5 A=-2.5 B=0 G=0.9 O=0 D=3

Symmetric Icon - French Glass

L=-2.05 A=3 B=-16.79 G=1 O=0 D=9

Symmetric Icon - Halloween

L=-2.7 A=5 B=1.5 G=1.0 O=0 D=6

Symmetric Icon - Kachina Dolls

L=2.409 A=-2.5 B=0 G=0.9 O=0 D=23

Symmetric Icon - Mayan Bracelet

L=-2.08 A=1 B=-0.1 G=0.167 O=0 D=7

Symmetric Icon - Pentacle

L=-2.32 A=2.32 B=0 G=0.75 O=0 D=5

Symmetric Icon - Pentagon

L=2.6 A=-2 B=0 G=-0.5 O=0 D=5

Symmetric Icon - Sanddollar

L=-2.34 A=2 B=0.2 G=0.1 O=0 D=5

Symmetric Icon - Swirling Streamers

L=-1.86 A=2 B=0 G=1 O=0.1 D=4

Symmetric Icon - Trampoline

L=1.56 A=-1 B=0.1 G=-0.82 O=0 D=3

Symmetric Icon - Trinity

L=1.5 A=-1 B=0.1 G=-0.805 O=0 D=3

Symmetric Icon - Untitled 01

L=1.455 A=-1 B=0.03 G=-0.8 O=0 D=3

Symmetric Icon - Unititled 02

L=2.39 A=-2.5 B=-0.1 G=0.9 O=-0.15 D=16

3D Alternatives

Strange Attractors can also be extended into three dimensions. See here and here for my previous experiments with 3D Strange Attractors.

All of the images in this post were created using Visions of Chaos.

Jason.