Simulating epidemics with WebGL
In a recent post, I looked at the SIR model for simulating epidemics. The SIR model only tracks three numbers: the number of “Susceptible”, “Infected”, and “Recovered” people. This doesn’t account for location: all simulated meetings are between two random members of the global population. This is clearly unrealistic, so let’s fix that. Below is a spatial SIR model, simulated with WebGL:
The world is modelled as a 2D grid. Each cell tracks the number of Susceptible, Infected and Recovered people. We visualize the state of the world with Blue and Red: Blue is the number of Susceptible people, and Red is the number of Infected people. (I’ve omitted the green Recovered people. See below.)
Each day, there are meetings between people. Two people meet if they are in the same or adjacent cells. Each meeting has a 10% chance of transmissing the infection. The infection lasts for an average of 30 days before “recovery”. As in the non-spatial SIR model, death is modelled as a form of recovery. Make what you will of this.
This model is certainly more realistic than the non-spatial SIR model. The infection dies out where the population density is too low to sustain the spread. It reminds me of a mould spreading. But this model is also still unrealistic in many ways. Real meetings don’t just happen between “adjacent” people: infections can jump from one city to another via airplanes.
To make this simulation efficient, I’ve implemented it as a WebGL fragment shader. This draws on a previous simulation of the Game of Life that I wrote in 2017. The entire state is stored as a 1024x1024 texture. I have one “stepper” fragment shader which reads this texture, and generates the next state. The initial process is bootstrapped with this 1024x1024 image, which I screenshotted from a population density map of Shanghai.
My simulation has a significant bug. You’ll notice that the number of red Infected people decreases after the height of the infection, But it never reaches zero. I don’t know why this is!
In future posts, I intend to fix this bug. I might also try modelling flights. I might also add some sliders, so you the reader can adjust the parameters of the model.