Coding Stories: Demystifying Drops

On a recent family trip we delayed our start of the day in a cabin for a few hours because of a morning rainstorm. I usually get antsy when I can’t get going first thing in the morning, but between the beautiful damp forest, the soothing sound of rainfall, and the fascinating accumulation of water on the bottom of the roof I was pretty content just sitting and experiencing the rain. I even took this video of it on my phone.

As I was sitting there admiring the beautiful artwork that nature was creating in front of me, I considered how I might capture some of it artistically. Unfortunately, I lacked a macro lens to make the raindrops a prominent subject of a photograph. Additionally, my painting skills are not developed enough to give justice to the nuanced beauty of this scene. So I decided to attempt to convey some of what moved me using p5.js.

I would like to first point out that as aesthetically engaging are these falling drops of water, the range of scientific concepts addressed is equally impressive. Perhaps it is in the interconnection of these two domains where the real beauty of the scene can be found. That is, if I can figure out how to animate it.

To get started I decided I to make one drop in the center of the canvas. Now in the absence of gravity or an obstacle water tends to form into a sphere due to surface tension. So on my 2D screen I drew a circle in the middle of the canvas.

Image for post
Image for post

For the next step I added in some gravity. To do this I had to track the position and velocity of the drop. Since I will probably want to add more drops later I decided to create a Drop object.

class Drop {
constructor(x) {
this.x = x;
this.y = -30;
this.vy = 0; // drops only move vertically so vy is sufficient
}

update() {
this.vy += 0.35;
this.y += this.vy;
}
show() {
ellipse(this.x,this.y,30);
}
}

When a drop falls through the air it deforms slightly because of the increased pressure on the bottom of the drop, but I haven’t added air to my model yet, and to be honest it is close enough to spherical that a circle will look fairly realistic. Also to model the drops speed I should note that they will reach their terminal velocity pretty quickly, but since my scene will only capture the beginning of the fall I will skip adding that adjustment as well. Here is a gif of falling drops that I created with my sketch.

This is starting to look like something. Now I just need to figure out the drop formation part. Let’s start with the assumption that the drops will remain spherical throughout the simulation and so they will always be drawn as circles. This is a bit too simplistic, but it is actually fairly accurate except for the moment when the drop releases from the roof. During the other times the drops look fairly spherical and so I am going to pursue this approximation. In fact a classic experiment that is used to measure the surface tension of a liquid makes this assumption and then measures the surface tension based on the geometry of a sphere. I found the following article online that explains it. In the article was included the following diagram to show what happens right before the drop releases.

Image for post
Image for post

In the above diagram a drop of water forms at the bottom of a cylindrical tube of diameter d filled with the liquid. The spherical drop adheres to the circular bottom of the tube. This means that the center of the sphere represents one vertex in an isosceles triangle where the adjacent sides to this vertex each have lengths equivalent to the radius of the sphere. The third side of the triangle which is opposite this vertex is the diameter of the tube. Now using the pythagorean theorem I can exactly place the sphere in this scene. Later I will add that to my code for the Drop class. Also from the article I found an equation for the critical mass of the drop when it will fall from the tube.

Image for post
Image for post

So now I will program this for one drop. I drew a tube with two parallel lines originating from the top of the screen. The starting diameter of the drop is equal to the diameter of the tube and the center of the drop is in the center of the circle is aligned with the end of the tube. Here is what it looks like at the start.

Image for post
Image for post

From these initial conditions I can calculate the change of the drop over time. Let’s assume that water that is accumulating in the drop is traveling down a rectangular channel on the roof. If the rain is falling at a constant rate then the rate of flow on the roof is also constant. Therefore the rate of water flow into the drop depends on the width of the channel of water which I will equate with the tube that I have drawn on the screen. Now I can write an expression that increases the mass of the drop over time in my .update() method of the Drop class.

this.m += this.w * rate;

This of course does not have units but it correctly depends on the width of the tube and the rate constant can be adjusted to match realistic conditions. Using the formula for the volume of a sphere I know that the diameter of the drop depends on the cube root of the mass. Using the volume formula and the density of water I get:

Image for post
Image for post

I am removing units and constants in my program but they all ultimately get absorbed into the value for rate so I will just make it look realistic as I am not trying to make a numerical prediction here.

show() {
line(this.x-this.w/2,0,this.x-this.w/2,tubeLength);
line(this.x+this.w/2,0,this.x+this.w/2,tubeLength);
let d = pow(this.m,1/3);
ellipse(this.x,this.y,d);
}

I can also located the drop so that the sphere always exactly intersects the circle that forms the bottom of the tube. This requires the pythagorean theorem that I explained above. This gives us the following y value for the position of the circle.

this.y = tubeLength+sqrt(sq(this.d/2)-sq(this.w/2))

So now we have an accurately growing spherical drop of water. Now since we already know the surface tension of water at room temperature we can calculate the critical mass when it will release, which as we saw above depends on the diameter of the tube. For the purposes of this program I set a limit value for the quotient of mass/width. When it hits that limit then I will assign a value of false to this.grow triggering the drop to stop growing and start falling due to gravity.

if (this.m/this.w > limit) {
this.grow = false;
}

I also built in a repeat so that when the drop falls off the screen a new drop forms in the original location.

if (this.y>height+this.d*2) {
this.y=tubeLength;
this.m=pow(this.w,3);
this.vy=0;
this.grow=true;
}

This is a decent start to my animation. Since I implemented this with a Drop class it is easy to create more falling drops. Based on what I see in the video I decided to place the drops at somewhat randomly spaced locations along the roof using this code.

let x=0;
while(x<width) {
let w = random(10)+35;
drops.push(new Drop(x+w/2,w*0.5));
x+=w;
}

Note that I gave each tube a slightly different width resulting in a different flow rate of water into the drop. I also decided to make the shade of the drop change over time as that seemed to be a feature of the lighting in the video. Finally I included my original image from above into the sketch and altered the alpha value of the drops so that you could see through them just a bit.

The drops in this sketch do not look entirely realistic in terms of the the shape of the drops when they release or the lighting of the drops since water drops act like tiny lenses. I could spend more time adding these features to my sketch. A physicist friend of mine suggested I model the molecules of water in the drop using the Lennard-Jones equation which is a decent combination of the repulsive effects of electrostatics and the attractive influence of the Van der Waals force. That would probably reproduce the elongated drop look that I saw in the original video. Perhaps I will do that in another article. Another colleague pointed me to some javascript tutorials on rendering the lighting of drops using a shader and some blurring. This one looked really good and worth reading. In the end I decided that there is something very satisfying in the sketch that I created. It captures something important about the movement and randomness from the original sketch. So I think I will end this journey here. I do hope you also see something wonderful in marrying the beauty of a morning rain with the power of scientific prediction.

Image for post
Image for post

Written by

exploring the intersection of coding, education and disciplinary knowledge

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store