Search

Geek Girl Joy

Ancestor Simulations Elementary Cellular Automata Part 2

Today we’re going to continue our examination of 1 dimensional Wolfram Elementary Cellular Automata by examining Rule 1 (00000001) and manually step through a few cycles or generations.

We will create a 1D grid with a length of 24 + 1 (17) so that we have a center value equal distance from both ends, we will assign all cells the off state except for the center cell which we will turn on.

Like this

0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0

 

We will call this our “initial seed” value. Wolfram CA rules are usually demonstrated with some version of this seed, though it is important to remember that the length can be as long as you want, both shorter or longer and the cell states can be set however you need them to begin.

Before proceeding review the neighborhood because it is now important to understand this:

The Wolfram Neighborhood

 

Lets look at Rule 1(00000001) and get started computing new cell states.

Rule 1

R1 R2 R3 R4 R5 R6 R7 R8
111 110 101 100 011 010 001 000
0 0 0 0 0 0 0 1

 

If you imagine the rule 1 table above as an “array” then the first row represents the “keys” and below I will refer to R8 or R6 or other keys by these names as shortcuts that are referring to the  neighborhood patterns on the second row, example R3 refers to a neighborhood pattern of a left cell of 1, a center value of 0 and a right value of 1… got it?

Just to be sure that you are able to follow along  consult the center values in the initial seed, its a 1 and to its left is a 0 and to it’s right is also a 0, therefore on the center position in the “new seed” we will apply R6 which means the new center value would be a 0 Still with me? Good! 😉

Only one more thing to talk about before we get to computing and that is how to handle the edge cells which are the first cell $seed[0] and the last cell of the seed $seed[17] . Because there is no $seed[-1] and $seed[18] there are two options for handling this scenario. A lot of people simply say those positions are 0’s (or 1’s depending on the case) but I like the second option which is to wrap around and grab the value at the other end of the seed. This methodology allows the patterns to wrap rather than stop when an edge is encountered however depending on your use needs you may want to wrap or use a hard value, neither way is technically correct.

So now that we are on the same page lets start figuring out what rules to use to compute the new seed.

 

0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
R8 R8 R8 R8 R8 R8 R8 R7 R6 R4 R8 R8 R8 R8 R8 R8 R8

 

 

We can replace the rules with their values and then figure out what rules to use next:

0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1
R1 R1 R1 R1 R1 R1 R2 R4 R6 R7 R5 R1 R1 R1 R1 R1 R1

 

And if we replace the rules with the rule values you can see we are back where we started:

0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0

 

This pattern will repeat over and over again until we decide to stop, here’s 14 more generations to demonstrate:

The Finished Rule 1 Image

 

This isn’t always the case however, lets look at a different rule that will give us many more interesting neighborhood patterns, Rule 26 (00011010)!

Rule 26

R1 R2 R3 R4 R5 R6 R7 R8
111 110 101 100 011 010 001 000
0 0 0 1 1 0 1 0

 

Notice that we reset the seed to what we started with so that we can illustrate the differences in the rules. Nothing prevents us from using the output of Rule 1 (or any rule) as the input seed for another rule, in fact you can get some very interesting results by doing that!

Notice also that because the seed is the same as before, if we fill in the cell rules they are same neighborhood patterns that we used before, what’s different this time is the values the patterns are mapped to.

0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
R8 R8 R8 R8 R8 R8 R8 R7 R6 R4 R8 R8 R8 R8 R8 R8 R8

 

If we replace the neighborhood pattern with the rule value we get a completely different result than we got with Rule 1 before! While we’re at it lets also fill out the next set of rules too:

0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0
R8 R8 R8 R8 R8 R8 R7 R6 R3 R6 R4 R8 R8 R8 R8 R8 R8

 

Once again we replace the cell rule with the rule value and we have a completely different grid, we also figure out the next row’s rule patterns:

0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0
R8 R8 R8 R8 R8 R7 R6 R4 R8 R7 R6 R4 R8 R8 R8 R8 R8

 

OK lets now convert those rules to values to see what we get:

 

0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0

 

Here’s 12 more generations, there is a pattern but its not quite like the pattern that Rule 1 gave us:

The Finished Rule 26 Image

 

I was going to start looking at code with you today but it’s getting late and this post is already fairly long so come back tomorrow and we will FINALLY dig into the code 😛  have a great evening everyone!

Please Fund, Subscribe, Like, Share & Comment:

This post was made possible by the generous contributions of my sponsors on Patreon & anonymous contributions to my Bitcoin Tip Jar.

 

 

I will see you all in my next post!

Much Love,

~Joy

 

 

Advertisements

Ancestor Simulations Elementary Cellular Automata

Today we open another chapter in Ancestor Simulations, namely “LIFE” or rather our exploration of simulating our “Ancestors” and therefore it behooves us to start with Cellular Automata.

Originally conceived of in the 1940’s by Stanislaw Ulam and John von Neumann (who should be among your personal heroes because of their scientific brilliance by the way 😛 ) consist of a discreet grid of “cells” which can be represented in one or more dimensions.

5x5-grid

Example of a 5×5 two dimensional grid

The cells can have properties assigned to them and cells can exhibit varying types of behaviors called “states” which the cells are said to be “in”.

Various “Rules” are applied to determine when cells can change states and if so, what states can they change to, the most common of which (and simplest) are “Alive” and “Dead“.

Often the grid is encoded as digital data using 0 to mean the cell is switched “Off” or “Dead” and 1 to mean the cell is switched “On” or “Alive”.

Frequently it is more convenient for people to view the grid encoded as pixels rather than ones and zeros and the simplest way to go about visualizing the data is to assign the on and off states separate color values, such as white and black, although black and red or white and blue are also fairly popular.

Often the rules used to determine the cell states involve checking to see what states the “neighborhood” (the cells around the current cell ) are in.

The Von Neumann Neighborhood

If the blue cell is the current cell being examined then the “Von Neumann Neighborhood” examines the four cells surrounding it in the four  cardinal directions directly around the current cell (shown in red) and the “extended neighborhood” would then include the cells in pink.

 

The Moore Neighborhood

If the blue cell is the current cell being examined then the “Moore Neighborhood” examines the eight cells surrounding it directly around the current cell (shown in red) and the “extended neighborhood” would then include the ring of cells around the red cells.

 

The Wolfram Code

We’ll cover 2D Cellular Automata  in future posts because today we are going to look at one of the simplest cases of a CA, namely a 1 dimensional Wolfram CA called the Wolfram Code.

Originally discovered by Stephen  Wolfram in the early 1980’s when he was studying computer simulations and the nature of the universe… kinda like we are doing with our Ancestor Simulation! 😉

I called the Wolfram code “simple” only because it “has fewer moving parts” so to speak, it is still capable of complex behavior, including modeling Chaos Theory so as such the Wolfram code embodies emergent behavior very elegantly!

Emergence is the idea that simple rules can be implemented and followed and their results can lead to highly complex behaviors and structures that somehow “emerge” without having to be specifically implemented or designed into the system.

Unlike the 2D grid “neighborhoods” (Von Neumann & Moore) outlined above the 1D Wolfram CA is just a single row of boxes. Technically It need not be 1D but the Wolfram CA is usually introduced and discussed as a 1D CA and as such, when we think of the resulting output we think of it more as a series of time steps away from the original pattern. That is to say that while we display the output of the Wolfram CA in 2D image just like other CA’s, the 2D grids are computed row by row whereas any given image of a 2D CA is computed entirely and then rendered.

This means that that the image generated by the Wolfram CA is the sum of all the states or calculations that occurred and each row, being the resulting sum of states or calculations occurring at n-generation and is n rows (steps) away from the originating pattern.

The Wolfram CA allows for an arbitrary length (meaning the length can be as long as you want) with a minimum size of 3 because the Wolfram CA has a neighborhood that consists of 3 cells. the cells to the direct left and the direct right (shown in red) of the cell being considered (shown in blue).

The Wolfram Neighborhood

 

An interesting result of this is that with a 3 cell neighborhood and 2 states (on & off) there are 23 (8) possible state combinations for a given neighborhood and 28 (256) possible rules.


$number_of_rules = pow(2, pow(2,3)); // 256

 

Because there are only 2 possible cell states and only 8 values are needed to encode each possible rule, we can generate all of the Wolfram CA rules using this code:

 

for($i = 0; $i < $number_of_rules; $i++ ){
    printf("$i: " . '%08b' . PHP_EOL, $i);
}
/*
0: 00000000
1: 00000001
2: 00000010
3: 00000011
4: 00000100
5: 00000101
6: 00000110
7: 00000111
8: 00001000
9: 00001001
10: 00001010
...
250: 11111010
251: 11111011
252: 11111100
253: 11111101
254: 11111110
255: 11111111
*/

 

The cell states are checked against these rule patterns and in this order:

R1 R2 R3 R4 R5 R6 R7 R8
111 110 101 100 011 010 001 000

Therefore if the neighborhood pattern was 111, the first value of the rule is applied. If it is 110 the second it used and so forth.

Some of the rules like Rule 30 (00011110) in combination with Rules 86 (01010110) , 135 (10000111) and 149 (10010101) have been shown to encode chaotic behavior.

Other rules are either suspected of being “Turing Complete” (without a “formal proof” having been created or discovered yet) or ARE known to be Turing complete such as Rule 110 (note this refers to the octet binary representation for the number 110 (01101110)  not the 3 cell neighborhood pattern 110 (R2) as shown in the table above).

For example, here is the results of Rule 73 (01001001) when initialized with a single “living” cell in the center of the image on row: 0 col: 513:

Click for full Size

And with that, have a great evening everyone!

Come back tomorrow for the next part of this post which will include my implementation of a 1D Wolfram Automata which I used to generate the image above.

Please Fund, Subscribe, Like, Share & Comment:

This post was made possible by the generous contributions of my sponsors on Patreon & anonymous contributions to my Bitcoin Tip Jar.

 

 

I will see you all in my next post!

Much Love,

~Joy

 

 

Ancestor Simulations Wednesday Winnowing

The term “winnowing” literally means to remove and separate grain (something desirable and good) from it’s husk or chaff (something undesirable) so that you are left with a filtered grain (endosperm, bran and germ) ready to be “milled” or otherwise prepared for human consumption or use.

That’s what this post is about, winnowing the undesirable parts of our Solar System Generator so that we are left with something better than when we started.

Predominately this means “facing the music”  and accepting that browsers are impatient creatures and simply don’t like sitting around and waiting for 19+ hours while the server “chunks” out orbital dynamics calculations and then turns the resulting data set into a series of images that when strung together create an animation of what was computed to have occurred during the simulation.

Speaking of “facing the music”, I’m currently listening to the song “Vampires” by the New Retro Wave (Synthwave) group “The Midnight” (not a sponsor) I just love the amazing saxophone in this song and I’ve got it on repeat! 😛 I highly recommend checking them out over on YouTube though I have embedded the video below.

 

So now lets talk about what I “winnowed” from the code.

First, I removed the $_POST statements in favor of variables that can be adjusted as needed since we are removing everything browser-centric (mainly HTML) since I am now almost exclusively interacting with the “Solar Systems Generator” from the command line.

I also made the image output optional which it the main causal  source of most of the speed improvement since writing out the orbital data to the images is what takes the most time. My tests show that by disabling the image output enables us to run about 50 thousand simulations in the course of about 5 minutes on my machine.

That’s with 1 Million objects in the Solar Nebula and equates to ~10 thousand years at a “$delta_time” of 0.1, which means that in order to simulate the entire 4.6 Billion year life cycle of our solar system we would need ~58.298611 days! Interesting little tidbit, If we started the simulation today and actually ran that 4.6 billion year sim it wouldn’t finish until ~7:10 am PST | Friday, November 24, 2017.

If we included the image & animation generation we would have to reduce the number of objects in the Solar Nebula to ~100K and it would then then take ~1538.612874531963 years (slightly over 1.5 millennia) and the simulation wouldn’t finish until 7:29:23 am PDT | Tuesday, May 8, 3556 (a REALLY LONG time from now). 😛

Therefore our speed performance improvements amount to roughly an increase of 963205.4537168415% in our favor! 😎 🤓

I still need to finish the clean merging of the elements when there are collisions but that’s coming and I will highlight that is my next Ancestor Simulations post.

For now here is a small sampling of the elements.txt report generated:


[Planet 2]
Americium 18.181818181818
Fermium 18.181818181818
Nihonium 18.181818181818
Neodymium 18.181818181818
Astatine 18.181818181818
Hafnium 18.181818181818
Promethium 18.181818181818
Tungsten 18.181818181818
Fluorine 18.181818181818
Strontium 18.181818181818
Polonium 18.181818181818
Oganesson 18.181818181818
Cerium 18.181818181818
Oxygen 18.181818181818
[Planet 3]
Sulfur 150
Titanium 150
Thallium 150
Americium 150
Gadolinium 150
Fluorine 150
Oganesson 150
Bromine 150
Mercury 150
Krypton 150
Bromine 150
Oganesson 150
Krypton 150
Beryllium 150
Cerium 150
[Planet 4]
Oganesson 15.66265060241
Dubnium 15.66265060241
Bromine 15.66265060241
Osmium 15.66265060241
Krypton 15.66265060241
Fermium 15.66265060241
Scandium 15.66265060241
Mendelevium 15.66265060241
Lanthanum 15.66265060241
Manganese 15.66265060241
Osmium 15.66265060241
Neodymium 15.66265060241
Seaborgium 15.66265060241
[Planet 5]
Nihonium 46.666666666667
Oganesson 46.666666666667
Dubnium 46.666666666667
Europium 46.666666666667
Cerium 46.666666666667
Mendelevium 46.666666666667
Osmium 46.666666666667
Cerium 46.666666666667
Protactinium 46.666666666667
Tungsten 46.666666666667
Seaborgium 46.666666666667
Cadmium 46.666666666667
Lead 46.666666666667
Hassium 46.666666666667
...

You will notice that all the elements have the same values and are sometimes duplicated rather than merged into a single quantity which will just not do! I mean, sure we could say they are separate quantities and are part of the whole and treat them accordingly. This would give us the option if we wanted to have impacts knock off sections of planets like in the Giant Impact Hypothesis  and do less math when we do that but I really don’t see us running that high of fidelity simulation so I will work to merge them.

And that’s it for today!

You can find the updated code for this project over on my GitHub profile.

Please Like, Comment below & Share this post with your friends and followers on social media.

Please Fund & Subscribe:

This post was made possible by the generous contributions of my sponsors on Patreon.


 
 

If you would prefer to support me anonymously using bitcoins please use the address below or scan the QR code using your bitcoin wallet app, thank you!

Please Send Here: 1GgUHjVAYqFLBWufFTpkoDEti16DSSNNG7

As always, have a great week and I will see you all in my next post!

Much Love,

~Joy

Today

Hello everyone, Happy Monday! I hope you had a great weekend!

On Saturday I went to a baby shower for my sister who is due to have her second child in November 🙂 and as such I had limited time to work on our Ancestor Simulation and while I have made quite a bit of improvement (how does ~50K epochs in about 5 minutes sound? 😉) but it’s not really ready and I am going to need a day or two to clean up the code and write the post so instead of leaving you hanging I thought I would write a post anyway!

The the featured image above is of Xavier sleeping next to me this morning during his mid morning nap. I have attached the uncropped image below at the end of this post. My little Xavier is my everything! ❤

Recently I got my first Patreon supporter! THANK YOU!!! Every dollar contributed will seriously help! Still trying to get the PT Cruiser fixed but the funds I am collecting from my supporters will go toward improving this site and obtaining a better hosting plan that would let us do bigger and better things! 🙂

I hope you have been enjoying the Ancestor posts! I know they are a bit ‘advanced’ for a lot of programmers and are somewhat philosophical and more “sciencey” (which means they tend to be very long and dry) than most people care for. Some of you have expressed the sentiment that they can be difficult for junior coders and passive readers to follow, I hear you!

Personally, I’ve been having a blast making the Ancestor Simulation projects for my readers who tend to be “compsci majors” but again, I understand they are not everyone’s “cup of tea” and therefore I would like to announce that we will be starting a new series soon.

I will cover the details of the new series in a different post but what I can say is that this will be an additional series and I intend to continue to do the Ancestor Simulation posts.

I know what the series will be about but I have not started writing it yet and it will take the form of a narrative that supports an ongoing project’s code and vise versa. I’ve discussed the idea with friends and colleague’s who generally seem to have a positive response to the concept.

My goal is to add a second multi-post (series) project that is aimed at a broader audience.

I will publish the next Ancestor post covering improvements to the elements system as well as the speed improvements I mentioned above.

Also of note, later this week (probably Thursday) I will be “running some copper” for a friend’s new business, well the business isn’t new but the ‘brick and morter‘ is.

If it should prove interesting I might also do a post about that too! 🙂

Please Like, Comment below & Share this post with your friends and followers on social media.

This post was made possible by the generous contributions of my sponsors on Patreon.

If you would prefer to support me anonymously using bitcoins please use the address below or scan the QR code using your bitcoin wallet app, thank you!

Please Send Here: 1GgUHjVAYqFLBWufFTpkoDEti16DSSNNG7

As always, have a great week and I will see you all in my next post!

Much Love,

~Joy

Ancestor Simulations Adding Elements & Solar Nebulae

It’s Friday so that means your probably planning to pick up a 6..er 24 pack of beer and holding up in front of your computer all weekend and reviewing and modifying all my recent changes to the solar systems generator prototype. Frankly I can’t say that I blame you because there is quite a bit to go over! 😛

Before we proceed I want to welcome and thank directly Erich Weidtmann over on Patreon for becoming my supporter! With your help I will be able to continue to bring you these great posts! The funds you contribute will go towards the fund to improve our hosting and computational capacity!

I have already added him over on my Sponsors page as a public and on going thank you for continuing to sponsor my posts and projects. If you would also like to add your name to my sponsors list then support me over on Patreon for as little as $12 a year!

 

Solar Nebulae

I know in my last post Monday Mini Makeup I didn’t think we were going to add Solar Nebulae  due to the large number of computations required (SO MANY) which results in a simulation that takes hours or days to complete. I did however say that I would attempt it and get back to you and well, I am pleased to say that it bugged me enough that I went ahead and added it anyway!

I conducted my first long simulation (15,000 epochs) after adding solar nebula and took 19 hours (roughly 1 epoch (cycle or frame of the simulation) every 13 Minutes & 12 Seconds) to complete the run and it had over 100 thousand orbital bodies ranging in size from ~marble or “ball bearing” size up to several hundred kilometers in diameter.

Before we look at the code let’s talk about what a solar Nebula is and look at some pretty pictures while we’re at it! 😛

Protoplanetary-diskAn artist’s concept of a protoplanetary disk, where particles of dust and grit collide and accrete forming planets or asteroids

 

SolarnebulaShock waves through icy parts of the solar nebula may be the mechanism that enriched ancient meteorites (called chondrites) with water — water that some believe provided an otherwise dry Earth with oceans.

Basically a solar nebula (protoplanetary disk) is all the stuff (rocks, minerals and elements) that make up a solar system just spread out and not congealed into large bodies like planets and moons because the system is still “young” and forming.

In practice this means that the main difference between the nebula and the protoplanets is size and by extension due to the additional mass and volume a larger chemical element diversity.

In our simulation, the orbital bodies that comprise the solar nebula are much smaller than protoplanets and we also don’t compute their orbits (movement). Further still, we do not enable collision detection from the perspective of the nebula.What this means is that although the objects will accrete if a planet passes close enough to them, they do not accrete with each other, which sucks but since they are not moving anyway this significantly reduces the computation required per frame but at the cost of a stationary cloud that would in reality orbit the star like the protoplanets.

I feel like this is a fair tradeoff however as it still enables the planets to grow and this even approximates the planets “clearing their neighborhood” as can be seen in this frame from one of the simulation I recently ran. Notice the empty areas that look like striations in the laminar flow of the orbits through the nebula.

Here is the code that creates the nebula, notice 3 things.

  1. The sizes are listed in both metric and imperial for your convenience! 😉
  2. The code is not much different from the code that creates the planets. We do this separately for simplicity however we could wrap this up into a single step if and when we clean up the code (remember this is a prototype).
  3. The code that positions the cloud objects is the same logarithmic spiral algorithm that we implemented when we were creating galaxies.

 if(isset($_POST['enable-solar-nebula'])){ 

	$a = 0.9759 + RandomFloat(0);
	$b = 0.1759;
	$steps = 7; 
	$radius = 0.8 * pi()* $steps;
	$max_spread = 0.7;
	$lower_disk_radius = -6;
	$higher_disk_radius = 6;
    
	
	for($i = 0; $i < 200000; $i++){

		// Nebula
		
		// Debris size
		$size = mt_rand(0,6);
		if($size == 0){
			$size = "0.0" . mt_rand(1,9); // 31.855 Kilometers - 286.695 Kilometers in Diameter
		}                                 // 19.7937793 Miles - 178.144014 Miles in Diameter
		
		elseif($size == 1){
			$size = "0.00" . mt_rand(1,9); // 3.1855 Kilometers - 28.6695 Kilometers in Diameter
		}                                  // 1.97937793 Miles - 17.8144014 Miles in Diameter
		
		elseif($size == 2){ 
			$size = "0.000" . mt_rand(1,9); // 318.55 Meters - 2.86695 Kilometers in Diameter
		}                                   // 348.370516208 Yards - 1.78144014 Miles in Diameter
		
		elseif($size == 3){
			$size = "0.0000" . mt_rand(1,9); // 31.855 Meters - 286.695 Meters in Diameter
		}                                    // 34.837051619 Yards - 313.53346457 Yards in Diameter
		
		elseif($size == 4){
			$size = "0.00000" . mt_rand(1,9); // 3.1855 Meters - 28.6695 Meters in Diameter
		}                                     // 3.48370516185 Yards - 31.3533464567 Yards in Diameter
		
		elseif($size == 5){
			$size = "0.000000" . mt_rand(1,9); // 0.00031855 - 0.00286695 Kilometers in Diameter
		}                                      // 1.04511155 Feet - 9.406003937008 Feet in Diameter

		elseif($size == 6){
			$size = "0.0000000" . mt_rand(1,9); // 3.1855 Centimeters - 28.6695 Centimeters in Diameter
		}                                       // 1.25413386 Inches - 11.28720472 Inches in Diameter
		

		
		
		
		  $angle = $radius * RandomFloat(3); // Pick a random point in the Spiral
		  $row = $a * exp($b * $angle) * cos($angle);
		  $row = $row + ($max_spread * $row * RandomFloat(0)) - ($max_spread * $row * RandomFloat(0));
		  $col = $a * exp($b * $angle) * sin($angle); 
		  $col = $col + ($max_spread * $col * RandomFloat(0)) - ($max_spread * $col * RandomFloat(0));

		  // Flip a coin to determine which arm 
		  // the star should be on.
		  if (mt_rand(0, 1) == 1){
			  // if heads put it on the second arm
			  // by inverting the values
			  $row = ($row/-1);
			  $col = ($col/-1);
		  } 

		  // Normalize positions to be within the image bounds
		  $row = MinMax($row, $lower_disk_radius, $higher_disk_radius, $img_size);
		  $col = MinMax($col, $lower_disk_radius, $higher_disk_radius, $img_size);

			
		$color = imagecolorallocate($system, mt_rand(10, 50), mt_rand(10, 50), mt_rand(10, 50));
		@imagefilledellipse ( $system, round($row), round($col), (float)$size, (float)$size, $color);
		
		
		array_push($planets, array(
	   'au'=>$row+$col,
	   'size'=>$size,
	   'color'=>$color,
	   'vy'=>0,
	   'vx'=>0,
	   'x'=>$col,
	   'y'=>$row,
	   'r'=>$radius,
	   'a'=>$angle,
	   'ax'=>0,
	   'ay'=>0,
	   'row'=>$row,
	   'col'=>$col,
	   'plot'=>true,
	   'motion'=>false
	   ));

	}
 }

I wish we had the computation capacity available to include motion on the nebula as well but we really have hit a brick wall in this regard. I may attempt to improve this by using the few remaining tricks up my sleeves but I highly doubt I will get enough improvement what would allow the sim to speed up enough for modeling the orbital dynamics of the nebula, but I’ll try and see what comes out the other side. 😛

Elements

Now lets talk about our burgeoning chemical system for a minute. It gets a few things right and a lot wrong or rather it simply omits quite a bit of whats makes elements, “elements” (namely subatomic particles).

The main thing to keep in mind is that it’s still an early implementation and treats all volumes of each element equally. Obviously this is nonsensical and I intend to improve this by accounting for the size of the orbital bodies so that we get a more accurate simulation.

Currently what is occurring is we track the correct distribution, transfer and spread of the elements but not their correct volumes. I intend to fix this issue and discus elements in more detail in my next post (I wasn’t actually planing to be implementing the solar nebula) so although a basic implementation is in place it requires a lot of work before we can consider the elements even remotely “done”. Having said that here is the code that initializes the elements:

 

if(isset($_POST['enable-elemental-simulation'])){
	////
	// Meet the elements
	////
	$chemical_elements = array('Hydrogen', 'Helium', 'Lithium', 'Beryllium', 'Boron', 'Carbon', 'Nitrogen', 'Oxygen', 'Fluorine', 'Neon', 'Sodium', 'Magnesium', 'Aluminium', 'Silicon', 'Phosphorus', 'Sulfur', 'Chlorine', 'Argon', 'Potassium', 'Calcium', 'Scandium', 'Titanium', 'Vanadium', 'Chromium', 'Manganese', 'Iron', 'Cobalt', 'Nickel', 'Copper', 'Zinc', 'Gallium', 'Germanium', 'Arsenic', 'Selenium', 'Bromine', 'Krypton', 'Rubidium', 'Strontium', 'Yttrium', 'Zirconium', 'Niobium', 'Molybdenum', 'Technetium', 'Ruthenium', 'Rhodium', 'Palladium', 'Silver', 'Cadmium', 'Indium', 'Tin', 'Antimony', 'Tellurium', 'Iodine', 'Xenon', 'Caesium', 'Barium', 'Lanthanum', 'Cerium', 'Praseodymium', 'Neodymium', 'Promethium', 'Samarium', 'Europium', 'Gadolinium', 'Terbium', 'Dysprosium', 'Holmium', 'Erbium', 'Thulium', 'Ytterbium', 'Lutetium', 'Hafnium', 'Tantalum', 'Tungsten', 'Rhenium', 'Osmium', 'Iridium', 'Platinum', 'Gold', 'Mercury', 'Thallium', 'Lead', 'Bismuth', 'Polonium', 'Astatine', 'Radon', 'Francium', 'Radium', 'Actinium', 'Thorium', 'Protactinium', 'Uranium', 'Neptunium', 'Plutonium', 'Americium', 'Curium', 'Berkelium', 'Californium', 'Einsteinium', 'Fermium', 'Mendelevium', 'Nobelium', 'Lawrencium', 'Rutherfordium', 'Dubnium', 'Seaborgium', 'Bohrium', 'Hassium', 'Meitnerium', 'Darmstadtium', 'Roentgenium', 'Copernicium', 'Nihonium', 'Flerovium', 'Moscovium', 'Livermorium', 'Tennessine', 'Oganesson');

	// initialize unique element spawn probability "weights" for this solar system
	$element_weights = array();
	$number_of_elements = count($chemical_elements); // count the elements
	for($i = 0; $i < $number_of_elements; $i++){
		array_push($element_weights, mt_rand(0, $number_of_elements));
	}
	// combine the element names as keys and the weights as values
	$chemical_elements = array_combine($chemical_elements, $element_weights);
}

 

This code generates the elements for a protoplanet based on the probability distribution (weights) for this unique solar system (not all systems will have the same amount of elements):



$body_elements = array();
	if(isset($_POST['enable-elemental-simulation']) && $_POST['enable-elemental-simulation'] == true){
		// Add Elements
		$number_of_elements_to_spawn = mt_rand(10,15);
		for($elem = 0; $elem < $number_of_elements_to_spawn; $elem++){

			//select an element
			$select_element = mt_rand(1,array_sum($chemical_elements));

			// Find the selected element
			$num = 0;
			foreach($chemical_elements as $value=>$weight){
				if(($num += $weight) >= $select_element){
					//echo "$weight $value" . PHP_EOL;
					
					// push element onto the orbital body
					array_push($body_elements, $value);
					break;
				}
			}
		}
	}

And that’s it for today!

You can find the updated code for this project over on my GitHub profile.

Please Like, Comment below & Share this post with your friends and followers on social media.

This post was made possible by the generous contributions of my sponsors on Patreon.

If you would prefer to support me anonymously using bitcoins please use the address below or scan the QR code using your bitcoin wallet app, thank you!

Please Send Here: 1GgUHjVAYqFLBWufFTpkoDEti16DSSNNG7

As always, have a great weekend and I will see you all in my next post!

Much Love,

~Joy

 

Ancestor Simulations Generating New Solar Systems Monday Mini Makeup

Happy Monday!

MY LOGIC IT FEELS GOOD TO BE BACK POSTING! Did you miss me? I know it has been only one week but I missed me! 😛

The truth is that as much as I keep making these projects and posts for you guys, I REALLY need this! The act of sitting down and thinking up not just a programming project every week, but also something that is intelligent (and hopefully entertaining) has been extremely cathartic for me!

You see, as much as your job may be difficult (it probably is) and boring at times (likely) and as much as your coworkers, clients, boss or employees can be a pain (It’s Monday so I know you are thinking it), all of those people are rational and you have every right to your frustrations!

I share no such luxury my friend because my boss is an irrational 7 month old baby who only loosely knows the words “baba” and “momma” !

Don’t misunderstand me, I certainly love my little Xavier, it’s just that unlike your adult employees, bosses, coworkers, clients, G/F, B/F, spouse, lover, spouse’s lover… what have you 😛 whose thoughts and motivations you can basically understand with a reasonable amount of effort and discussion, no matter how many times I carefully explain the dangers of wantonly crawling off the edge of the bed head first onto a hardwood floor he still takes every opportunity to try!

Further still, no matter how many times I explain how it hurts momma when he imagines himself as Tarzan and attempts to use my hair as vines to swing on and yet alas… he is just not amenable to the idea!

Regardless of the countless times I elaborate on why wiggling around when I am changing his “poopy” diapers creates “yucky messes” for momma to clean up, it is none the less… ineffectual!

The jarring truth is that you simply cannot reason with a 7 month old baby! Odds are at the very least, the people you deal with every day are leaps and bounds (many orders of magnitude) more acquiescent to compromise than Xavier is!

As such, I have confidence that you will get through this week with aplomb! 😉

Now, let’s talk about our Ancestor Simulation, shall we?

When you last saw this project Generating New Solar Systems I was getting ready for a “Friday Fun Fix” and I was contemplating the following three modifications to the Solar Systems Generator:

  • Adding loss of mass  to thermal energy release and heat transfer when there are impacts of orbital bodies.
  • Improved agglomeration of smaller particulates into larger bodies.
  • Adding chemical properties and transfer those chemicals during impacts.

First let me say that I feel like accounting for mass lost as thermal radiation released during orbital body impacts is an absolutely wonderful idea! However, at this point it is seemingly a bit more complex than we currently have the resources to model. If you think about it, we would have to keep track of subdivisions of masses and implement a much more complex particle simulation (not to mention model all the subatomic particles) and then extend that system (additional computation) to every frame (epoch) of the simulation… while this is a wildly fun idea, I don’t really feel like we would get all that much out of adding this at this juncture. So, I have decided that we are going to shelve this concept for the time being and perhaps at a later date, once we have upgraded our computational capacity we may revisit this.

In regard to improving agglomeration and instantiating our solar system from smaller particulates into larger bodies. We had implement collision detection and our planets would eat each other, quite vigorously in fact! However, more often than not we would end up with few stable orbits (one or two) but usually no sustained orbits. After a bunch of minor tweaks late this past week and weekend throughout the generator I have managed to get it to a state of routinely generating complex multi-body orbital patterns and I tweeted a teaser GIF on Friday:

Many of the code “tweaks” involved modifying the initialization of the orbital velocities and distance from the center star. What the planets currently do is basically “find their orbits” starting with an orbit larger than their velocity can sustain so their orbits decay from their initial position to an inner orbit closer to the sun. Once their velocity is sufficient to maintain the bodies distance from the sun it continues to orbit until it collides with something or the simulation ends.

I am now quite pleased with the behavior of the simulation in regard to agglomeration at this point however I really wish we had the ability to extend this further and implement something akin to an accretion disk from which the orbital bodies form from clouds of material rather than instantiating small but fully formed planetoid’s which then proceed to ‘consume’ one another in order to grow. This too would require an improved particle system and at this time I don’t have enough ‘big iron‘ to make this a reality. Again though, I am really pleased with what I have accomplished already!

Further, I am toying with the idea of imposing a second “grid” overlay on the solar system that would contain a probability distribution of “virtual particles‘ (perhaps using a modified version of the plasma fractal which we already implemented over in my post on Generating Planet Terrain) that could be used to organically “grow” planets without the need to simulate each and every atom and collision directly.

In this case we would say that as an orbital body passes through each position in the probability distribution, based on the density of “virtual particles” the centaurs would grow by some amount based on that position’s material abundance and at the same time reduce the available particulate in the cloud (probability distribution) thereby actually accreting using only probability and not simulating the individual interactions of the collisions.

If I have the opportunity I will toy with this concept a little and see if it is worth implementing in full.

Which brings us to the final enhancement under consideration, implementing a chemical or elemental system. Let me first say that this is HAPPENING for sure! I have the initial element system partially implemented already and if all goes well I expect to unveil this feature in this upcoming “Friday Fun Fix”. Additionally, while we need not limit ourselves to real elements (nothing says we can’t just make up a new periodic table for our simulated universe) we will however be using the same chemical elements as are available in our universe. 🙂

In any case here is a newly rendered solar system containing 19 stable orbital bodies.

Click or tap the animation to view it full size.

 

You can find the updated code for this project over on my GitHub profile.

Please Like, Comment below & Share this post with your friends and followers on social media.

Please support me over on Patreon and if you would like to support me anonymously using bitcoins please use the address below or scan the QR code using your bitcoin wallet app, thank you!

Please Send Here: 1GgUHjVAYqFLBWufFTpkoDEti16DSSNNG7

If you would like to suggest a topic or project for an upcoming post feel free to contact me.

As always, have a great week and I will see you all in my next post!

Much Love,

~Joy

When Good Parts Go Bad!

Surprise!

Okay, so on Monday I published my article ‘No Posts‘ to inform everyone of some equipment trouble that befell my computer.

I notified everyone that I had to restore my computer to operational status prior to resuming my blogging activities.

Well I am now pleased to inform everyone that I believe I have resolved the problem with my computer that prevented me from working. It turns out that an electrolytic capacitor on my video card leaked and I had to desolder the bad capacitor, clean the board and replace the capacitor with an equivalent component from my home workshop. YAY!!!!

I don’t see this as a good long term solution or repair however because I am aware of the concept of ‘The Bathtub Curve‘ which I briefly mentioned in my post Are You Prepared For Disaster? and as my system is already quite well used and worn, I expect to be on the latter half of the increasing failure curve.

Therefore before proceeding with further posts I believe it to be prudent to take a few days off posting and projects to put my machine through it’s paces and confirm to my satisfaction that the machine is production ready. If everything goes well expect me to resume posting next Monday, September the 18th.

Should we continue with the Ancestor Simulations Series or are you getting tired of this topic and prefer I blog about something else? Personally I am rather enjoying these Ancestor Simulation posts but I know a lot of you love, yes I said just ABSOLUTELY LOVE my neural networking posts! 😛

Getting Started with Neural Networks Series

Pathfinding From Scratch Using A Neural Network Series

Lets Teach AI How To Read Using PHP Series (Optical Character Recognition)

Machine Learning from a Database Series

 

These posts are some of your favorites and among my most read and reread articles.

Especially the ‘Getting Started’ series!

I’ve been looking for interesting and unique topics and problems to create Neural Network to solve and I think when we get to the “aliens / creatures / ancestors” posts we will be implementing some Neural Networks so that they behave in intelligent ways and will hopefully display emergent behavior but it all depends on how much time I have to dedicate to the project, how interested you guys are and how much raw processing and computation is required to produce a successful result.

For example I have a neural network project sitting on my ‘cutting room floor‘ where I attempt to do ‘text to speech‘ synthesis using raw wav files as ‘training data‘ however there was too many data points and WAY TOO MUCH processing to be viable as I had implemented it. The only thing it really generated consistently was ‘white noise‘ however I may try again in the future to use ‘phonemes‘ and we’ll see how it goes with a simplified methodology.

In any case, I’d like to leave you with another example of ‘good parts going bad’ and how this applies to the concept of the ‘The Bathtub Curve‘, it also further stresses the concept that you cannot plan for every failure!

Years ago I was working on an old used HP DC Series Business Desktop in a Small Form Factor.

As I recall I was performing refurb maintenance on it so that it could be redeployed to a factory environment. I had the case open and the computer sitting on my grounded work bench.

I was wearing my grounding strap and everything was all fairly routine.

I booted up HP DIAGS (or was it Hiren’s Boot CD? Can’t recall 😛) to perform a system wide hardware ‘stress test‘ (I will be doing something similar in the coming days with this computer) and then I retired to my ‘SysAdmin‘ desk to respond to emails. After about 5 minutes I get up and walk over to the machine and as I am looking (just looking) into the case at the CPU fan spinning I am instantly showered in sparks and there is a fountain of fireworks spewing from inside the computer!

With my Adrenalin starting to flow and my heart beating like a 555 timer I reached through the sparks to the surge protector and yank the NEMA 5-15 end of the IEC C13 to NEMA 5-15 Power Cable and just as quickly as the fireworks started the calm returned.

Of course I immediately reported everything to the IT Director who insisted I determine the cause!

After a through examination of the machine I had discovered that it was the PSU and not the CPU that had so epically failed!

After further research I discovered that the particular manufacturing batch that the PSU was a member of, used an inferior glue inside the power supply which became ‘hydrophilic‘ over time and absorbed ambient humidity in the air leading to a greater likelihood of failure over time, just as the bathtub curve generally predicts!

Fortuitously there was a recall on the PSU with the batch number we had and since this was a known issue to the manufacturer I was able to get the part replaced under warranty! 🙂

There was no way we could have prevented the PSU from catastrophic failure however I was able to quickly diagnose and resolve the problem because I knew what I was doing, I had the right resources at my disposal and I had a vendor who was willing to work with me to resolve the issue to my satisfaction.

Fast forward to my recent video card failure and repair, its WAY out of warranty and so far from ‘state of the art‘ that you could call it a cave painting! 😛

As I said I expect that this minor setback is merely a harbinger that signals future hardware failure is on the horizon for my production PC so if you would like to help me upgrade my equipment so that we can avoid additional (potentially longer) interruptions to my posting or assist me with paying the $1,200 to repair the transmission on my PT Cruiser, or simply just want to say thanks for all the cool posts and code then consider supporting me over on Patreon.

If you would like to support me anonymously using bitcoins please use the address below or scan the QR code using your bitcoin wallet app, thank you!

Please Send Here: 1GgUHjVAYqFLBWufFTpkoDEti16DSSNNG7

With that, have a great week & I hope to see you all in the next post!

Please Like, Comment below & Share this post with your friends and followers on social media.

If you would like to suggest a topic or project for an upcoming post feel free to contact me.

Much Love,

~Joy

No Posts

Sorry I haven’t posted anything however I ended up getting called for jury and between taking the bus to that and a wedding across the state as well as child care and everything else… I’ve just had so little time to work on posts.

Additionally my computer seemingly died today 😭 so everything’s up in the air right now. I will try to resume posting ASAP and I will try to keep to you posted on my progress by using my phone to write updates on whats going on but I will be unable to work from just my phone.

PLEASE PLEASE PLEASE consider supporting me on Patreon or supporting me by sending bitcoins to my tip jar.

Please Send Here: 1GgUHjVAYqFLBWufFTpkoDEti16DSSNNG7

At this point I would like to say that if you have enjoyed my posts and want to see them resume, please help!

Thank you and much love,

~Joy

Ancestor Simulations Generating New Solar Systems

Happy labor day everyone! While the rest of your family is getting ready to barbecue, putting drinks on ice and otherwise getting ready to celebrate the holiday… your exceptionally high IQ’d self is waiting for a post from little o’l me… as it should be! 😛

Why do we celebrate ‘labor day’ by not working anyway? I mean we’re literally ‘celebrating labor’ right? But then how do you not do the very thing you are celebrating on the day you celebrate it? Hmmm :-/ Bazaar don’t you think?

So after last weeks posts:

The natural next step to creating new solar systems would seem to be using another generator as we had in my Ancestor Series posts… and that is in fact the case.

After more than few minutes of hacking away I stepped back from my keyboard to admire the frankencode proto solar system simulation I had assembled and then it occurred to me, there is just no way I can host this for everyone. The raw computation alone is… ‘hefty’ to say the least but then to generate the animations as well… its just more processing capacity than I have available on my web server.

So I will publish some of the code below for you to read and the full project over on my GitHub profile. You are welcome to obtain a copy and play with the code yourself and I encourage you to do so! 🙂

Here’s a very early render of my results, notice that while planets do orbit, they pass right through each other and the center star as well!

 

A great first attempt but certainly not ready for our ‘ancestors’ to live in! Most of the planets are flung out of the system and the others all seem to plunge into the star at some point, not stable enough to safely call this place home!

I then proceeded to implement collision detection on the orbital bodies with each other as well as with the sun! Now things are starting to take shape!

Currently the planets will grow when they ‘eat’ (impact) one another however 100% is merged and there is 0 lost as thermal energy so I might address that if it bugs me enough! 😛

I was also thinking about Astronaut Don Petti’s experiment that I wrote about over in my post on Ancestor Simulations Generating Galaxies, where he demonstrated the role in which microgravity caused the initial formation of the so called ‘agglomerates’ from which larger and larger orbital bodies would form until you end up with an active solar system and stuff smashing into other stuff all the time!

Well, if possible I would also like to see if we can’t simulate that by starting our system with maybe hundreds or thousands of really small particles and having them grow into larger orbital bodies that become planets.

If so, perhaps we might also be able to assign each initial asteroid or comet a set of chemical properties and transfer those chemicals during impacts. We might even use that data to get some kind of read out regarding the available chemicals on each orbital body, if I have time I think it would really add a nice layer of information that our ‘ancestors’ can use to decide on where to go  if they ever become space faring! Further, we might use it to decide where it is even possible for life to evolve let alone colonize if it’s not their home planet.

Here is the Code

set_time_limit(3000); // Adjust as needed


function MinMax($value, $min, $max, $size){
    return abs(($value - $min) / ($max - $min) * $size);
}


function RandomFloat($big){
    return mt_rand(0, $big) . "." . mt_rand(0,99);
}

// Get the file extension 
function GetFileExtension($image){
    $path_data = pathinfo('images/' . $image);
    return strtolower($path_data['extension']);
}

// Load an image resource
function LoadImage($image){
    $ext = GetFileExtension($image);
    if($ext == 'jpg' || $ext == 'jpeg'){$image = imageCreateFromJpeg('images/' . $image);}
    elseif($ext == 'png'){$image = imageCreateFromPng('images/' . $image);}
    elseif($ext == 'bmp'){$image = imageCreateFromBmp('images/' . $image);}
    else{return null;}
    return $image;
}

// Buffer Images
function EncodeImage($image){
    
    global $images, $buffered;
    ob_start(); // Start the buffer
    imagegif($image); // Output image buffer as a gif encoded still
    $images[]=ob_get_contents(); // add the gif still to the images array
    //$buffered[]=$delay; // Delay in the animation.
    $buffered[]= (1); // Delay in the animation (ms * delay in seconds)
    ob_end_clean(); // Stop the buffer
}
 
// Create Gif
function CreateGif($num_images){
    global $images, $buffered;
    
    // Do something with each image
    for($i = 1; $i < $num_images; $i++)
    {
        $image = LoadImage("$i.png");
        EncodeImage($image); // Buffer image
        imagedestroy($image); // Free memory
    }
    // Generate the animation
    $gif = new GIFEncoder($images,$buffered,0,0,0,0,0,'bin');
    
    
    // Save the gif
    $animation_file = fopen('orbit.gif', 'w');
    fwrite($animation_file, $gif->GetAnimation());
    fclose($animation_file);
}


$delta_time = 0.1; // 0.1 // 0.03
if(isset($_POST["epocs"])){$simulations = $_POST["epocs"];}
else{$simulations = 210;}


if(isset($_POST["zoom"])){$high = $_POST["zoom"];}
else{$high = 6;}
$low = $high * -1;


////
// Create Solar System
////
if(isset($_POST["exponent"])){$exponent = $_POST["exponent"];}
else{$exponent = 9;}

$img_size = pow(2, $exponent) + 1;

if(isset($_POST["number-of-bodies"])){$number_of_orbital_bodies = $_POST["number-of-bodies"];}
else{$number_of_orbital_bodies = 9;}

$system = imagecreatetruecolor($img_size, $img_size);
$space_black = imagecolorallocate($system, 0, 0, 0);


////
// Define Sun
////
$sun_size=mt_rand(8,30); // Size
$sun_x = $img_size/2; // center the sun on x
$sun_y = $img_size/2; // center the sun on y
$sun_yellow = imagecolorallocate($system, 255, 255, 0); // Color
@imagefilledellipse ( $system, $sun_y, $sun_x, $sun_size, $sun_size, $sun_yellow);


$planets = array();
// generate system
for($i = 0; $i < $number_of_orbital_bodies; $i++){

    ////
    // Define Planets
    ////
    $au_from_sun=RandomFloat(2+$i); // AU from Sun
    $size=RandomFloat(8); // Size
    $color = imagecolorallocate($system, mt_rand(50, 255), mt_rand(50, 255), mt_rand(50, 255)); // Color
    $vy = RandomFloat(1); // Velocity
    $vx = 0;              // Velocity    
    $x = $au_from_sun; // Initial x position
    $y = $au_from_sun; // Initial y position


    // randomly flip spawn quadrant
    if(mt_rand(0,1) == 1){
        $y = $y / -1;
    }
    if(mt_rand(0,1) == 1){
        $x = $x / -1;
    }
    
    // randomly shift to half
    if(mt_rand(0,1) == 1){
        // position is in 
        if($y + $y/2 > $img_size){
            $y -= $y/2;
        }else{
            $y += $y/2;
        }
    }
    if(mt_rand(0,1) == 1){
        // position is in 
        if($x + $x/2 > $img_size){
            $x -= $x/2;
        }else{
            $x += $x/2;
        }
    }

    $r = sqrt(pow($x,2) + pow($y,2)); // Orbital radius at this position
    $a =  ($au_from_sun * 0.00002) / pow($r, 2);
    $ax = -$a * $x / $r; // Divide the force for the angle between x & y
    $ay = -$a * $y / $r; // Divide the force for the angle between x & y
    // Normalize positions to be within the image bounds
    $row = round(MinMax($y, $low, $high, $img_size));
    $col = round(MinMax($x, $low, $high, $img_size));
        
    // plot planet
    @imagefilledellipse ( $system, $row, $col, $size, $size, $color);
    
    array_push($planets, array(
       'au'=>$au_from_sun,
       'size'=>$size,
       'color'=>$color,
       'vy'=>$vy,
       'vx'=>$vx,
       'x'=>$x,
       'y'=>$y,
       'r'=>$r,
       'a'=>$a,
       'ax'=>$ax,
       'ay'=>$ay,
       'row'=>$row,
       'col'=>$col,
       'plot'=>true));
}


// Output image
imagepng($system, "images/0.png");
// free memory
imagedestroy($system);


for($i = 0; $i < $simulations; $i++){
    ////
    // Solar System
    ////
    $system = imagecreatetruecolor($img_size, $img_size);
    
    ////
    // Sun
    ////
    // Plot Sun
    @imagefilledellipse ( $system, $sun_y, $sun_x, $sun_size, $sun_size, $sun_yellow );
    
    foreach($planets as $key=>&$planet){
        if($planet['plot'] == true){
            ////
            // Planet
            ////
            $planet['vx'] = $planet['vx'] + $planet['ax'] * $delta_time; // New velocity
            $planet['vy'] = $planet['vy'] + $planet['ay'] * $delta_time; // New velocity
            $planet['x'] = $planet['x'] + $planet['vx'] * $delta_time; // New position
            $planet['y'] = $planet['y'] + $planet['vy'] * $delta_time; // New position
            $planet['r'] = sqrt(pow($planet['x'],2) + pow($planet['y'],2)); // Orbital radius at this position
            $planet['a'] =  $planet['au'] / pow($planet['r'], 2); // Acceleration / angle
            $planet['ax'] = -$planet['a'] * $planet['x'] / $planet['r']; // Divide the force for the angle between x & y
            $planet['ay'] = -$planet['a'] * $planet['y'] / $planet['r']; // Divide the force for the angle between x & y
            // Normalize positions to be within the image bounds
            $planet['row'] = MinMax($planet['y'], $low, $high, $img_size);
            $planet['col'] = MinMax($planet['x'], $low, $high, $img_size);
            // Plot Planet
            @imagefilledellipse ($system, $planet['row'], $planet['col'], $planet['size'], $planet['size'], $planet['color']);
            
            // planet went out of bounds
            /*
             _____
           .|     |.
            |  *  |
            |_____|
                .  */
            if($planet['row'] <= 0 + ($planet['size']/2) + 5 || $planet['col'] <= 0 + ($planet['size']/2) + 5 || $planet['row'] >= $img_size - ($planet['size']/2) + 5 || $planet['col'] >= $img_size - ($planet['size']/2) + 5){
                $planet['color'] = $space_black;
                $planet['plot'] = false;
            }
            // if planet got too close to sun
            // as defind by the the center point of the sun
			// sourrounded by a box of:
			// the radius of the sun + n pixels
            /*
             _______
            |       |
            |  [*]  |
            |_______|
            */
            if( ($planet['row'] >= $sun_x - ($sun_size/2)+5) && ($planet['row'] <= $sun_x + ($sun_size/2)+5) && ($planet['col'] >= $sun_y - ($sun_size/2)+ 5) && ($planet['col'] <= $sun_y + ($sun_size/2)+5))
            {
                $planet['color'] = $space_black;
                $planet['plot'] = false;
            }
            
            
            // orbital body other than the sun collision handeling
            /*
             ________
            |        |
            |  >..<  |
            |________|
            */
            // for all the planets 
            foreach($planets as $key2=>&$planet2){
                if($planet2['plot'] == true){
                    if($key != $key2){ // that are not this planet
                        
                        // deturmine the larger of the two
                        if($planet['size'] > $planet2['size']){ // planet is bigger than planet 2
                            
                            // then check for collisions
                            if(($planet2['row'] >= $planet['row'] - ($planet['size']/2)+5) && ($planet2['row'] <= $planet['row'] + ($planet['size']/2)+5)
                              && ($planet2['col'] >= $planet['col'] - ($planet['size']/2) + 5) && ($planet2['col'] <= $planet['col'] + ($planet['size']/2)+5))
                            {
                                // remove smaller planet
                                $planet2['color'] = $space_black;
                                $planet2['plot'] = false;
                                
                                // add the mass of the
                                // small orbital body to
                                // the larger orbital body
                                $planet['size'] = $planet['size'] + $planet2['size'];
								
								// Planet may not be larger than our arbitrarily sized sun
                                if ($planet['size'] > $sun_size){$planet['size'] = $sun_size; }

                            }
                        }else{// planet2 is bigger than planet 1
                            
                            // then check for collisions
                            if(($planet['row'] >= $planet2['row'] - ($planet2['size']/2)+5) && ($planet['row'] <= $planet2['row'] + ($planet2['size']/2)+5)
                              && ($planet['col'] >= $planet2['col'] - ($planet2['size']/2) + 5) && ($planet['col'] <= $planet2['col'] + ($planet2['size']/2)+5))
                            {
                                // remove smaller planet
                                $planet['color'] = $space_black;
                                $planet['plot'] = false;
                                
                                
                                // add the mass of the
                                // small orbital body to
                                // the larger orbital body
                                $planet2['size'] = $planet2['size'] + $planet['size'];
                                
								// Planet may not be larger than our arbitrarily sized sun
                                if ($planet2['size'] > $sun_size){$planet2['size'] = $sun_size; }
                            }
                        }
                    }
                }
            }
        }
    }
    
    // Output Solar System
    imagepng($system, "images/" . ($i + 1) . ".png");
    // Free Memory
    imagedestroy($system);
}

include('GIFEncoder.class.php'); // GIFEncoder class
$images;
$buffered;
@CreateGif($simulations);

 

Here is an example of the output of the generator as it is currently, click or tap the animation to view it full size. It might take a second or two for it to load. More preview animations are available over on GitHub!

If you would rather I had this project running right here on this page, consider supporting me over on Patreon. One of the many things I would like to do with the funding my patrons give me is upgrade my servers!

Please Like, Comment below & Share this post with your friends and followers on social media.

If you would like to suggest a topic or project for an upcoming post feel free to contact me.

With that, I’m going to go eat a hot dog!

Have a great week and I will see you all in my next post!

Much Love,

~Joy

Blog at WordPress.com.

Up ↑