Atmospheric Dispersion model
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
Atmospheric Diffusion model
CONTEXT
Why is the sky blue ? Or sometimes red, orange and pink? It all has to do with how the light coming from the sun interacts with our atmosphere.
Light, which is constitued of photons of different wavelengths, is traveling in straight lines. However, when in our atmosphere, it collides with molecules it is deviated. This phenomenon is called diffusion.
The main mechanism for atmospheric diffusion is Rayleigh scattering, where the visible light interacts with small atoms and molecules in the atmosphere. The particularity of Rayleigh scattering is that it heavily depends on the wavelength of the incoming light ray: the scattering probability is proportional to λ^(−4). Red light (λ ~ 645 nm) nearly 5 times more likely to be scattered than blue light (λ ~ 440 nm). A consequence is that when looking at the atmosphere elsewhere than the sun, blue light is much more likely to be reflected of some molecule and end up in our eye than red light. Hence why during the day, the sky appears light blue!
This is illustrated in the below figure:
WHAT IS IT?
This model aims to simulate how light rays are diffused in an atmosphere and what colour the atmosphere would appear using various parameters. This model simulates a 2D atmosphere with a given height, by integrating light how many light rays of which colour arrive on the observer.
HOW IT WORKS
This model is an implementation of a basic ray tracing algorithm. In this context it is common to actually perform the simulation backwards: we emit rays from the observers and see if they collide with a light source or not. The reason behind simulating rays backwards is to save computations. If we were to send rays from the sun, only a small fraction would end up colliding with the observer.
While the rays are in the atmosphere, they have a chance of being scattered: i.e. be deflected. This chance is dependent on the ray colour: - green light is 1.8 times less likely to be scattered than blue light - red light is 2.6 times less likely to be scattered than green light
The Rayleigh mecanism doesn't scatter light rays uniformely, indeed a ray incoming with angle φ is more likely to be scattered either in the same direction or directly backwards. More precisely, the probabiliy is proportional to the cos^2 of the angle φ:
P(φ) = γ cos(φ)^2
Once a ray exits the atmosphere, we can check if it would have been emitted by the sun. Because the sun in "infinitely far", we don't actually need to simulate the sun and check for collision with the light ray. We can simply look at the angle the ray exits the atmosphere. If that angle is within the sun angular disk, then it is emitted. Note: periodic conditions are applied horizontally: this means that the simulation is infinitely wide which is only an approximation.
The simulation simply repeatedly sends rays in random directions and checks if they will "collide" with the sun after they exit the atmosphere. Then, for each direction and each color, we count the fraction of rays colliding with the sun. This yields for each direction an RGB triplet.
Once many light rays have been sent, we call that process integration, we can simply visualise what colour the atmosphere would look like in each direction.
HOW TO USE
The model has two modes: - Integration mode - Visualisation mode
The default mode, integration, shows how each ray is simulated and scatters through the atmosphere. It is possible to toggle traces behind the rays to see how they travel.
The visualisation mode can be activated by toggling the "show-result?" switch. In this mode, the simulation will send pseudo-light rays in every direction representing the overall color. These pseudo-rays aren't scattered nor do they count for integration, they only exist visually to see the resulting color.
In practice, I would recommend first playing around in integration mode with only a handful of light rays and see how they interact with the atmosphere, and how various parameter impact the simulation.
In order to produce a coherent image (good signal noise ratio, we need a lot of data points. Therefore we need to integrate a lot of rays. Therefore I recommend picking the maximum number of rays and turn off the "view updates". After about 10000 ticks or more, activate the "view updates" button, and toggle show-results?
Finally, this integrations gives us ratios between RGB values, but in order to produce a visible image, we need to multiply these values by a certain factor. This is what I called gain. There are two gain modes, one where the same gain is applied to the whole simulation, and one where the gain is applied separately on each direction separately. The latter shows colour better but doesn't show how disparately bright and dark areas of the sky are. Note that this gain is comparable to what ISO is in photography.
THINGS TO NOTICE
I suggest to try the default parameters, where the sun is right overhead and some default values. Once it is integrated enough, show the visualisation. The result should be a mainly blue sky, with a strongly white / pink cone overhead (where the sun is located). This is exactly how our atmosphere works: the blue rays are more likely to indireclty end up in our eyes from the atmospheric scattering! We also note that around the horizon (low elevation), the sky appears more pink-ish. This is akin to a red sunset sky, though I am not entirely sure if it is physically accurate in this situation.
THINGS TO TRY
The user can try to change all the parameters. In particular how changing the scattering probability, the atmosphere's height, or the sun's elevation affects the image.
EXTENDING THE MODEL
One could extend the model by adding more complex scattering mechanisms such as Mie scattering. Another option would be to improve the geometry: our atmosphere is curved and not infinitely large. In particular, our atmosphere is very thin (100km) with respect to the earth's curvature (6400km radius). This should improve the image at low sun elevation and make more realistic sunsets.
CREDITS AND REFERENCES
All code written by A Bedouch. Rayleigh scattering illustration from wikimedia
Comments and Questions
rays-own [initial-heading] breed [simulated-rays simulated-ray] breed [rays ray] globals [red_em blue_em green_em red_rec blue_rec green_rec test-list] ;;; HELPER PROCEDURES to-report is-scattered [t_color] ;; gives scattering probability as a function of the light ray color let probability (ifelse-value t_color = blue [base_probability] t_color = green [base_probability / 1.8] t_color = red [base_probability / 4.6] [0]) report (random-float 100 <= probability) end to-report scatter-angle ;; Rayleigh scattering has a scattering probability proportional to cos(theta)^2 let which_sign random 2 let sign (ifelse-value which_sign = 0 [ -1 ] which_sign = 1 [ 1 ] ) report ((acos (sign * sqrt(random-float 1))) * 2) - 90 end to-report is-oob [y] ;; check if the y coordinate is out of bounds ;; returns 1 if reached the top of the simulation (escaped the atmosphere) ;; returns 2 if collided with the ground ;; returns 0 if no collisions if y > max-pycor - 0.5 [report 1] if y < min-pycor + 0.5 [report 2] report 0 end to-report check-sun-collision [exit-angle] ;; Checks if the exit-angle is within the sun's diameter if exit-angle > 180 [set exit-angle (exit-angle - 360)] report ( (exit-angle > sun_angle - sun_diameter / 2 ) and (exit-angle < sun_angle + sun_diameter / 2 ) ) end to-report get-index [angle] ;; For a given angle, gets the index of the cone bin if angle > 180 [set angle (angle - 360)] set angle (angle + 90) report floor(angle / 180 * division-factor) end to-report get-color [red_emitted red_received green_emitted green_received blue_emitted blue_received] ;; yields an rgb vector of the color corresponding to the fraction of emitted and received rays ifelse relative-gain? [ let multiplier max rgb (red_received / red_emitted) (green_received / green_emitted) (blue_received / blue_emitted) ifelse multiplier = 0 [report rgb 0 0 0] [ let new-gain (relative-gain / 100) * (255 / multiplier) report rgb (new-gain * red_received / red_emitted) (new-gain * green_received / green_emitted) (new-gain * blue_received / blue_emitted) ] ] [report rgb (gain * red_received / red_emitted) (gain * green_received / green_emitted) (gain * blue_received / blue_emitted)] end ;;; SETUP PROCEDURES to setup clear-all setup-rays setup-atmosphere setup-simulated-rays setup-counters reset-ticks end to setup-rays ;; setup the rays with random colour and direction set-default-shape rays "line" create-rays n_rays [setxy 0 min-pycor + 1] ask rays [ let choice random 3 set color (ifelse-value who mod 3 = 0 [ red ] who mod 3 = 1 [ blue ] who mod 3 = 2 [ green ]) set heading (random-float 180) - 90 set initial-heading heading ] end to setup-counters ;; setup counters for emitted and received rays of each colours, one counter for each bin of sky set red_em (n-values division-factor [1]) set green_em (n-values division-factor [1]) set blue_em (n-values division-factor [1]) set red_rec (n-values division-factor [1]) set green_rec (n-values division-factor [1]) set blue_rec (n-values division-factor [1]) end to setup-simulated-rays ;; setup simulated rays with the calculated colours set-default-shape simulated-rays "line" let tot 180 * 3 create-simulated-rays tot [setxy 0 min-pycor + 1] ask simulated-rays [ set hidden? true set heading (((who - n_rays) * 180 / tot) - 90) set size 2 set pen-mode "down" set pen-size 2 ] end ;;; LOOP PROCEDURES to increment-color-counter [escaped init-heading escape-heading tcolor] ;; increment colour of the correct bin for a ray of color tcolor and initial and escape heading let index get-index init-heading ( ifelse tcolor = red [set red_em replace-item index red_em (item index red_em + 1)] tcolor = blue [set blue_em replace-item index blue_em (item index green_em + 1)] tcolor = green [set green_em replace-item index green_em (item index green_em + 1)] ) if escaped and (check-sun-collision escape-heading) [ ( ifelse tcolor = red [set red_rec replace-item index red_rec (item index red_rec + 1)] tcolor = blue [set blue_rec replace-item index blue_rec (item index green_rec + 1)] tcolor = green [set green_rec replace-item index green_rec (item index green_rec + 1)] ) ] end to setup-atmosphere ask patches [ ifelse pycor + max-pycor < 2 * max-pycor * atmosphere_height / 100 [ set pcolor blue + 3.5 ] [ set pcolor black] ] end to go ;; flow control of what to display and what to compute move-rays if-else draw-path [ask rays [pen-down]] [ask rays [pen-up]] setup-atmosphere ifelse show-result? [ set draw-path false ask rays [set hidden? true] ask simulated-rays [ set hidden? false set pen-mode "down" get-simulated-color ] move-simulated-rays ] [ ask rays [set hidden? false] ask simulated-rays [ set hidden? true set pen-mode "up" ] clear-drawing ] tick end to reset-ray set pen-mode "up" set xcor 0 set ycor min-pycor + 1 set heading (random-float 180) - 90 set initial-heading heading if draw-path [set pen-mode "down"] end to move-rays ;; move and scatter r ask rays [ if pcolor != black [ if is-scattered color [ right (heading + scatter-angle) ] ] forward light_path let oob is-oob ycor ;; escaped the atmosphere if oob = 1 [ increment-color-counter true initial-heading heading color reset-ray ] ;; collided with ground if oob = 2 [ increment-color-counter true initial-heading heading color reset-ray ] ] end to get-simulated-color ask simulated-rays [ let index get-index heading set color get-color (item index red_em) (item index red_rec) (item index green_em) (item index green_rec) (item index blue_em) (item index blue_rec) ] end to move-simulated-rays ask simulated-rays [ foreach (n-values 50 [1]) [ forward 0.1 if ((xcor < min-pxcor + 0.05) or (xcor > max-pxcor - 0.05) or (ycor > max-pycor - 0.05) ) [setxy 0 min-pycor + 1] ] ] end
There is only one version of this model, created over 1 year ago by A Bedouch.
Attached files
File | Type | Description | Last updated | |
---|---|---|---|---|
Atmospheric Dispersion model.png | preview | Preview for 'Atmospheric Dispersion model' | over 1 year ago, by A Bedouch | Download |
example.png | png | example output | over 1 year ago, by A Bedouch | Download |
rayleigh.jpg | png | physics principle illustration | over 1 year ago, by A Bedouch | Download |
This model does not have any ancestors.
This model does not have any descendants.