Orbitals

Standard
x16 BATMAN!

x16 BATMAN!

 

Here’s a little C++ program I wrote that I wished would help me draw the Bohr model of the various elements. I wrote for two reasons:

  1. To get acquainted with PNGwriter; and,
  2. To make it easier to draw stuff like this.

It works fine for a few elements (that obey the general rules of electron configuration), but overall – it’s a disaster. There’re lots of nuances for each element that I don’t think I can code down in a general sense so I’m going to just leave it like this for now. Code and a few output pictures right after the break.

//Draws Bohr models of all elements in the periodic table

#include <pngwriter.h>
#include
#include <map>
<map>
#define PI 3.14159
#define rad(theta) (double)((PI/180.0)*theta)

using namespace std;

int main(int argc, char* argv[]){
	if (argc != 3){
		cerr << "Error   : You have not provided the correct number of arguments." << endl;
		cerr << "Usage   : " << argv[0] << " image-size background-colour" << endl;
		cerr << "          Images smaller than 1250px*1250px will be resized to accomodate the full models of higher elements." << endl;
		cerr << "Example : " << argv[0] << " 1500 0.0" << endl;
		return -1;
	}
	cout << "If specified size is less than 1250px*1250px, it will be resized to fit the full models of higher elements." << endl;
	cin;
	int imgHeight = atoi(argv[1]) < 1250 ? 1250 : atoi(argv[1]);
	int orbitalLimit[] = {2, 8, 18, 32, 50, 72};
    map<string, int=""> periodicTable = {  {"H", 1}, {"He", 2}, {"Li", 3}, {"Be", 4}, {"B", 5}, {"C", 6},
                                        {"N", 7}, {"O", 8}, {"F", 9}, {"Ne", 10}, {"Na", 11}, {"Mg", 12},
                                        {"Al", 13}, {"Si", 14}, {"P", 15}, {"S", 16}, {"Cl", 17}, {"Ar", 18},
                                        {"K", 19}, {"Ca", 20}, {"Sc", 21}, {"Ti", 20}, {"V", 21}, {"Cr", 24},
                                        {"Mn", 25}, {"Fe", 26}, {"Co", 27}, {"Ni", 28}, {"Cu", 29}, {"Zn", 30},
                                        {"Ga", 31}, {"Ge", 32}, {"As", 33}, {"Se", 34}, {"Br", 35}, {"Kr", 36},
                                        {"Rb", 37}, {"Sr", 38}, {"Y", 39}, {"Zr", 40}, {"Nb", 41}, {"Mo", 42},
                                        {"Tc", 43}, {"Ru", 44}, {"Rh", 45}, {"Pd", 46}, {"Ag", 47}, {"Cd", 48},
                                        {"In", 49}, {"Sn", 50}, {"Sb", 51}, {"Te", 52}, {"I", 53}, {"Xe", 54},
                                        {"Cs", 55}, {"Ba", 56}, {"La", 57}, {"Ce", 58}, {"Pr", 59}, {"Nd", 60},
                                        {"Pm", 61}, {"Sm", 62}, {"Eu", 63}, {"Gd", 64}, {"Tb", 65}, {"Dy", 66},
                                        {"Ho", 67}, {"Er", 68}, {"Tm", 69}, {"Yb", 70}, {"Lu", 71}, {"Hf", 72},
                                        {"Ta", 73}, {"W", 74}, {"Re", 75}, {"Os", 76}, {"Ir", 77}, {"Pt", 78},
                                        {"Au", 79}, {"Hg", 80}, {"Tl", 81}, {"Pb", 82}, {"Bi", 83}, {"Po", 84},
                                        {"At", 85}, {"Rn", 86}, {"Fr", 87}, {"Ra", 88}, {"Ac", 89}, {"Th", 90},
                                        {"Pa", 91}, {"U", 92}, {"Np", 93}, {"Pu", 94}, {"Am", 95}, {"Cm", 96},
                                        {"Bk", 97}, {"Cf", 98}, {"Es", 99}, {"Fm", 100}, {"Md", 101}, {"No", 102},
                                        {"Lr", 103}, {"Rf", 104}, {"Db", 105}, {"Sg", 106}, {"Bh", 107}, {"Hs", 108},
                                        {"Mt", 109}, {"Ds", 110}, {"Rg", 111}, {"Cn", 112}, {"Uut", 113}, {"Fl", 114},
                                        {"Uup", 115}, {"Lv", 116}, {"Uus", 117}, {"Uuo", 118}
                                    };

    for (map<string, int="">::iterator it = periodicTable.begin(); it != periodicTable.end(); it++){
        int numElectrons = it->second;
        string name = it->first;
        pngwriter img(imgHeight, imgHeight, atof(argv[2]), name.c_str());
		cout << "Now drawing element " << name << "..." << endl;

	    int numOrbitals = 	numElectrons <= 2 ? 1 :
							numElectrons <= 10 ? 2 :
							numElectrons <= 28 ? 3 :
							numElectrons <= 60 ? 4 :
							numElectrons <= 110 ? 5 : 6;
        int numElectronsToDraw = 0;
        int rem = numElectrons;

	    int originX = img.getheight()/2;
	    int originY = img.getwidth()/2;
	    int electronRadius = img.getheight()/150;
	    int orbitalRadius = img.getheight()/8;
		double electronColour = atof(argv[2]) < 0.5 ? 1.0 : 0.0;

	    int i = 0, j = 0;
		img.filledcircle(originX, originY, imgHeight/15, 65535, 46774, 0);
	    for (j = 0; j < numOrbitals; j++, orbitalRadius += imgHeight/15){ 		    //Drawing orbital path 		    img.circle(originX, originY, orbitalRadius, 55769, 0, 23387);             numElectronsToDraw = rem > orbitalLimit[j] ? orbitalLimit[j] : rem;
            rem -= numElectronsToDraw;
		    double increment = 360.0/numElectronsToDraw;
		    //Begin drawing electrons
		    for (double angle = 90.0, i = 0; i < numElectronsToDraw; angle += increment, i++){
			    img.filledcircle(	originX + orbitalRadius*cos(rad(angle)),
						            originY + orbitalRadius*sin(rad(angle)),
                                    electronRadius, electronColour, electronColour, electronColour);
		    }
		    //End drawing electrons
	    }
	    img.close();
    }
	return 0;
}

Lines 13-19 makes sure that two parameters are passed to the program, and if they’re not, a message is output to stderr (the standard error stream) along with an example use. It would be helpful here to explain to the user what the parameters do, just in case they didn’t know. I was using this myself so I didn’t. 😀

Lines 20-22 ensures that the smallest output size is 1250px*1250px because for larger models, the model would be clipped.

Lines 23-44 initialise the most important (arguably) data of the program. A map container (similar to a dictionary if you’ve used Python, or generally, a hash table) holds the element symbol as the key and the atomic number as the value. Querying the map with a key returns its value.

Line 47-84 is a for-loop that draws one element. For each element, we create a PNGwriter object with the user-supplied dimensions. We then calculate the number of orbitals required for this element based on its atomic number (BIG MISTAKE!).

Line 68 draws the nucleus – a yellow circle with one-fifteenth the radius of the width of the image – in the centre. Line 69-80 is the inner for-loop that draws the orbital first, and then determines how many electrons should be drawn in the orbital. If the number of remaining orbitals is more than the allowed limit of that orbital, the orbital limit values are used. If not, the remaining electrons are drawn in the same orbital.

The for-loop on lines 76-80 draws the electrons on the orbital a fixed angle apart.

The PNGwriter object is then closed and then the outer for-loop repeats for other elements.

Now for some output. This is going to be embarrassing.

Hydrogen (1), okay!

Hydrogen (1), okay!

Nitrogen (2, 5), correct!

Nitrogen (2, 5), correct!

Neon (2, 8), correct!

Neon (2, 8), correct!

Iron (2, 8, 16), when it should be Iron (2, 8, 14, 2)

Iron (2, 8, 16), when it should be Iron (2, 8, 14, 2)

I had fun with this one. Definitely my kind of programming, but still stumped at how I never saw the wrong configurations coming out. Maybe some day we’ll figure this out. 🙂

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s