Deriving all allowed term symbols for a given electron configuration

Let's assume, we are interested in deriving all allowed term symbols for any electron configuration. Normally, this involves drawing a lot of arrows and coping with possible combinations. The following description is rather terse. Throughout the following text, all electrons in the last unoccupied shell share the same quantum number n:

  1. Build all combinations of electron spin and angular momentum quantum number and discard all of them that disagree with Pauli's principle, so all electrons' state differ in at least one quantum number. (The boring part.)
  2. Calculate the total spin and angular momentum for each of the combinations by summing over the electron's quantum numbers. (The tedious task.)
  3. Fill a table with all relevant values for the total spin (columns) and the total angular momentum (rows) by counting the combinations from step 1 that yielded the specific values from the table headers as calculated in step 2. (The least interesting part.)
  4. Search for term symbols within the table. (Hey - that's funny.)

As you may have noticed, I rather dislike the first three steps. This makes me being less attentive, thus introducing some errors. Therefore, I dislike these steps even more. However, a small python script solves my problem:

import itertools
from math import *

# Configuration
l=1
e=3

# Calculations
header = ["{0:^5}|".format(i) for i in range(-l, l+1)]
header.insert(0, "|")
print ("|{0:^" + repr((2*l+1)*6-1) + "}|{1:^5}|{2:^5}|").format('m_l', 'M_l', 'M_s')
print "".join(header) + '     |'*2;
print "|" + "-----|"*(2*l+1) + '-----|'*2

entries = []
mml = 0
for i in itertools.combinations(range(0,2*(2*l+1)),e):
    Ml = sum([-l+floor(x/2.0) for x in i])
    Ms = sum([.5 if x % 2 == 0 else -.5 for x in i])
    entries.append([Ml, Ms])
    mml = max(mml, int(Ml))
    labels = ['U D' if (x*2 in i and x*2+1 in i) else 'U' if (x*2 in i) else 'D' if (x*2+1 in i) else '' for x in range(0, 2*l+1)]
    labels = ['{0:^5}|'.format(x) for x in labels]
    print '|' + ''.join(labels) + '{0:^5}|{1:^5}|'.format(Ml, Ms)

header = ["{0:^5}|".format(i/2.0) for i in range(-e, e+1, 2)]
print "\n|M_l\M_s |" + ''.join(header)
for i in range(-mml, mml+1):
    t = []
    for j in range(-e, e+1, 2):
        t.append(len([x for x in entries if x[0] == i and x[1] == j/2.0]))
    print "|{0:^8}|".format(i) + ''.join(["{0:^5}|".format(x) for x in t])

All you have to do is to adjust the two 'configuration' lines. l takes the quantum number l for the only partial filled orbital and e holds the number of electrons within this orbital. Please keep in mind, that no error checking is performed. Some sample output for nitrogen with the electron configuration 1s2 2s2 2p3 (l=1, e=3):

|       m_l       | M_l | M_s |
| -1  |  0  |  1  |     |     |
|-----|-----|-----|-----|-----|
| U D |  U  |     |-2.0 | 0.5 |
| U D |  D  |     |-2.0 |-0.5 |
| U D |     |  U  |-1.0 | 0.5 |
| U D |     |  D  |-1.0 |-0.5 |
|  U  | U D |     |-1.0 | 0.5 |
|  U  |  U  |  U  | 0.0 | 1.5 |
|  U  |  U  |  D  | 0.0 | 0.5 |
|  U  |  D  |  U  | 0.0 | 0.5 |
|  U  |  D  |  D  | 0.0 |-0.5 |
|  U  |     | U D | 1.0 | 0.5 |
|  D  | U D |     |-1.0 |-0.5 |
|  D  |  U  |  U  | 0.0 | 0.5 |
|  D  |  U  |  D  | 0.0 |-0.5 |
|  D  |  D  |  U  | 0.0 |-0.5 |
|  D  |  D  |  D  | 0.0 |-1.5 |
|  D  |     | U D | 1.0 |-0.5 |
|     | U D |  U  | 1.0 | 0.5 |
|     | U D |  D  | 1.0 |-0.5 |
|     |  U  | U D | 2.0 | 0.5 |
|     |  D  | U D | 2.0 |-0.5 |

|M_l\M_s |-1.5 |-0.5 | 0.5 | 1.5 |
|   -2   |  0  |  1  |  1  |  0  |
|   -1   |  0  |  2  |  2  |  0  |
|   0    |  1  |  3  |  3  |  1  |
|   1    |  0  |  2  |  2  |  0  |
|   2    |  0  |  1  |  1  |  0  |

Of course, U and D are symbols for spin up and spin down. For the sake of completeness, I add the description how to get the term symbols from the last table. First, there is a state spanning from -2 to 2 for M_l and from -0.5 to 0.5 for M_s. Thus, L=2 and S=1/2. With J=|L-S|...|L+S|={3/2, 5/2}, we get ^2D_{3/2} and ^2D_{5/2}. After removing these states from the table, we get a new one:

|M_l\M_s |-1.5 |-0.5 | 0.5 | 1.5 |
|   -2   |  0  |  0  |  0  |  0  |
|   -1   |  0  |  1  |  1  |  0  |
|   0    |  1  |  2  |  2  |  1  |
|   1    |  0  |  1  |  1  |  0  |
|   2    |  0  |  0  |  0  |  0  |

Again, we find S=1/2. This time, M_l has the range -1 to 1, so L=1. With J={1/2, 3/2}, we get ^2P_{1/2} and ^2P_{3/2}. The new table looks like

|M_l\M_s |-1.5 |-0.5 | 0.5 | 1.5 |
|   -2   |  0  |  0  |  0  |  0  |
|   -1   |  0  |  0  |  0  |  0  |
|   0    |  1  |  1  |  1  |  1  |
|   1    |  0  |  0  |  0  |  0  |
|   2    |  0  |  0  |  0  |  0  |

Only one term symbol is left. One tip: it's ^4S_{3/2} - the ground state of nitrogen.

You may also like...