CO Fundamental Transition with Design Recipe#

Jay Foley, University of North Carolina Charlotte

Overview and Motivation for Using the Design Recipe#

This notebook introduces a structured pedagogical approach to function design known as the Design Recipe. The Design Recipe offers a systematic, step-by-step framework to help students design, implement, and test functions in a repeatable and transparent way.

There are two primary motivations for incorporating this approach into instruction:


1. Research-Based Support for Teaching Programming Skills in Disciplinary Contexts

A recent study by Fuchs, McDonald, Gautam, and Kzerouni (2024) highlights the challenges students face when learning to program in domains like Physical Chemistry. The study identifies several persistent barriers:

  • Difficulty transferring programming skills to new contexts and representations

  • Absence of reliable, structured strategies for solving programming problems

To address these challenges, the authors recommend that instructors explicitly teach three core cognitive skills:
abstraction, decomposition, and metacognitive awareness.

The Design Recipe directly supports this recommendation. By requiring students to articulate function goals, design examples, and incrementally refine their code, it makes the process of problem-solving visible and teachable. Instructors can use it to scaffold not just coding, but computational thinking more broadly.


2. Enhancing Student Engagement When Using AI-Based Coding Tools

A second motivation is the hypothesis that structured approaches like the Design Recipe may improve how students interact with AI-based coding agents. With tools such as ChatGPT increasingly integrated into programming workflows, students often lack the skills to guide these tools effectively or interpret their outputs critically.

By giving students a clear framework for specifying and testing their intentions, the Design Recipe can promote:

  • Greater agency in directing code generation

  • Improved precision when communicating with AI tools

  • Better judgment when reviewing and debugging AI-generated code

This notebook explores how the Design Recipe can be used to support both disciplinary learning and productive human–AI collaboration in code development.


The Design Recipe: Step-by-Step#

  1. Header
    Define the function’s name, input parameters, and their data types. Also specify the data type of the return value.

  2. Purpose
    Provide a concise, one-sentence description of what the function is intended to do.

  3. Examples
    Supply one or more examples showing how the function should be called and what it should return. These serve both as documentation and as test cases.

  4. Body
    Write the function logic, using the header, purpose, and examples as your guide.

  5. Test
    Execute your example cases to verify correctness. Think critically about edge cases and incorporate additional tests as needed.

  6. Debug/Iterate
    If the function fails a test, revisit your logic and syntax. Add more targeted test cases to isolate and resolve errors. Iterate until the function performs as expected.


We will illustrate this process with functions relevant to modeling the vibrational spectroscopy of the carbon monoxide molecule!

Learning Outcomes#

By the end of this workbook, students should be able to:

  • Explain the Morse potential and its parameters for modeling diatomic molecules

  • Apply Taylor expansions to approximate anharmonic potentials up to quartic order

  • Convert molecular parameters from common units into atomic units for quantum calculations

  • Write Python functions to evaluate Morse potential and its approximations

  • Visualize potentials and compare exact and approximate vibrational energies

  • Utilize the Morse model to estimate spectral positions of the fundamental, first overtone, and first hot band of a diatomic


Summary#

In this activity, we study vibrational transitions of the carbon monoxide (CO) molecule using the Morse potential, a realistic model of molecular bonding that captures anharmonicity. We compare exact solutions of the Morse and harmonic oscillator potentials with perturbative approximations using cubic and quartic Taylor expansions of the Morse potential. We will implement these calculations using Python and NumPy, convert parameters into atomic units, and visualize the results. This provides a comprehensive example of connecting quantum mechanical theory with computational practice.


Background and Theory#

We model the vibrational Hamiltonian as:

(48)#\[\begin{equation} \hat{H}_{vib} = -\frac{\hbar^2}{2\mu} \frac{d^2}{dr^2} + V_{Morse}(r), \end{equation}\]

where the Morse potential is

(49)#\[\begin{equation} V_{Morse}(r) = D_e \left( 1 - e^{-\beta (r - r_{eq})} \right)^2. \end{equation}\]

The parameters for CO are:

  • \(D_e = 11.225 \text{ eV}\) (dissociation energy)

  • \(r_{eq} = 1.1283 \text{ Å}\) (equilibrium bond length)

  • \(\beta = 2.5944 \text{ Å}^{-1}\) (potential curvature)

  • \(\mu = 6.8606 \text{ amu}\) (reduced mass)

The exact energy levels are given by:
$\( E_n = \hbar \omega \left( n + \frac{1}{2} - \chi_e \left( n + \frac{1}{2} \right)^2 \right), \)\( where \)\( \omega = \sqrt{\frac{2 D_e \beta^2}{\mu}}, \quad \chi_e = \frac{\hbar \omega}{4 D_e}. \)$

The Morse potential can be approximated by a Taylor expansion around \(r_{eq}\):
$\( V_T(r) = \sum_{n=0}^\infty \frac{f^{(n)}(r_{eq})}{n!} (r - r_{eq})^n, \)$

where \(f^{(n)}(r_{eq})\) is the \(n^{th}\)-order derivative of the Morse potential evaluated at the equilibrium bondlength, e.g. \(f^{(1)}(r_{eq}) = \frac{d}{dr}V_{Morse}(r_{eq}).\)

We can define the harmonic oscillator model by truncating this Taylor series at the quadratic term,

(50)#\[\begin{equation} V_H(r) = \frac{ f^{''}(r_{eq})}{2} \left(r-r_{eq} \right)^2 = \frac{1}{2} k \left(r-r_{eq} \right)^2 \end{equation}\]

the cubic approximation to the potential as

(51)#\[\begin{equation} V_C(r) = V_H(r) + \frac{ f^{'''}(r_{eq})}{6} \left(r-r_{eq} \right)^3 = V_H(r) + \frac{1}{6} g \left(r-r_{eq} \right)^3, \end{equation}\]

and the quartic approximation as

(52)#\[\begin{equation} V_Q(r) = V_C(r) + \frac{ f^{''''}(r_{eq})}{24} \left(r-r_{eq} \right)^4 = V_C(r) + \frac{1}{24}h(r-r_{eq})^4. \end{equation}\]

As we have already seen, the harmonic oscillator has an exact solution, as does the Morse potential. The quartic and qubit oscillators do not have exact solutions, but they can be approximated using perturbation theory, as we will see later!

Molecular Parameters and Unit Conversion Factors#

The parameters for the CO molecule are given below in common units:

Parameter

Symbol

Value

Units

Dissociation Energy

\(D_e\)

11.225

electron volts (eV)

Equilibrium Bond Length

\(r_{eq}\)

1.1283

angstroms (Å)

Potential Curvature

\(\beta\)

2.5944

inverse angstroms (\(\text{Å}^{-1}\))

Reduced Mass

\(\mu\)

6.8606

atomic mass units (amu)

Conversion factors to atomic units (au) needed for calculations:

Conversion

Factor

Description

amu to atomic units of mass

1822.89

angstrom to atomic units of length

0.52917721067121

1 Bohr radius = 0.529 Å

electron volts to atomic units of energy

\(1/27.2114\)

1 Hartree = 27.2114 eV


Exercise: Convert Molecular Parameters to Atomic Units#

For each parameter below, write the expression to convert it into atomic units using the conversion factors above.


1. What is \(D_e\) in atomic units?

Click to reveal the solution for $D_e$

The dissociation energy conversion:

\[ D_e (\text{au}) = D_e (\text{eV}) \times \frac{1}{27.2114} \]

Numerically:

\[ D_e (\text{au}) = 11.225 \times \frac{1}{27.2114} \approx 0.4125 \]

2. What is \(r_{eq}\) in atomic units?

Click to reveal the solution for $r_{eq}$

The equilibrium bond length conversion:

\[ r_{eq} (\text{au}) = \frac{r_{eq} (\text{Å})}{0.529177} \]

Numerically:

\[ r_{eq} (\text{au}) = \frac{1.1283}{0.529177} \approx 2.132 \]

3. What is \(\beta\) in atomic units?

Click to reveal the solution for $\beta$

The potential curvature conversion:

\[ \beta (\text{au}) = \beta (\text{Å}^{-1}) \times 0.529177 \]

Numerically:

\[ \beta (\text{au}) = 2.5944 \times 0.529177 \approx 1.3755 \]

4. What is \(\mu\) in atomic units?

Click to reveal the solution for $\mu$

The reduced mass conversion:

\[ \mu (\text{au}) = \mu (\text{amu}) \times 1822.89 \]

Numerically:

\[ \mu (\text{au}) = 6.8606 \times 1822.89 \approx 12506.1 \]

import numpy as np
from scipy.special import hermite
from math import factorial

# TODO: Convert the molecular parameters to atomic units.
# Assign the converted values to the variables De_au, r_eq_au, beta_au, and mu_au respectively.

# Given parameters in common units:
De_eV = 11.225
r_eq_ang = 1.1283
beta_inv_ang = 2.5944
mu_amu = 6.8606

# Conversion factors:
amu_to_au = 1822.89
ang_to_au = 0.52917721067121
eV_to_au = 1 / 27.2114

# TODO: Add your code here to perform the conversions
# De_au = ...
# r_eq_au = ...
# beta_au = ...
# mu_au = ...

# Uncomment below to print your results for verification
# print(f"Dissociation energy in atomic units: {De_au}")
# print(f"Equilibrium bond length in atomic units: {r_eq_au}")
# print(f"Beta in atomic units: {beta_au}")
# print(f"Reduced mass in atomic units: {mu_au}")

Reflection Questions#

  • Why do we convert molecular parameters into atomic units?

  • How does the Morse potential capture anharmonicity? What features does the harmonic oscillator fail to capture about molecular vibrational motion?

  • What physical feature of the molecular system does the parameter \(\beta\) capture?

  • What physical feature of the molecular system does \(D_e\) capture?

Evaluating the Morse Potential Using Python Functions#

In this section, we will write a Python function to evaluate the Morse potential at given bond lengths using the Design Recipe approach we practiced earlier.

Recall the Design Recipe steps for writing functions:

  1. Header: Define the function name, input parameters with types, and return type.

  2. Purpose: Write a concise description of what the function does.

  3. Examples: Provide example calls with expected outputs to clarify usage.

  4. Body: Implement the function logic.

  5. Test: Run your function against the examples to verify correctness.

  6. Debug/Iterate: Fix any issues that arise in testing.


Function specification:

We want to create a function evaluate_Morse that takes as inputs:

  • r — a float or NumPy array of floats representing bond lengths (in atomic units)

  • De — dissociation energy (atomic units)

  • beta — Morse parameter related to curvature (atomic units)

  • r_eq — equilibrium bond length (atomic units)

The function returns the Morse potential value(s) V_Morse at r.


Writing the evaluate_Morse Function Using the Design Recipe#

We will create the evaluate_Morse function step-by-step following the Design Recipe. Try to answer each prompt on your own before clicking to reveal the suggested content.


Step 1 and 2: Header and Purpose

Define the function name, input parameters with their expected types, and the return type.

Suggested header and purpose:

def evaluate_Morse(r, De, beta, r_eq):
    """
    Evaluate the Morse potential at bond length(s) r.

    Arguments
    ---------
    
    r : float or np.ndarray
        Bond length(s) in atomic units
    De : float
        Dissociation energy in atomic units
    beta : float
        Morse parameter in atomic units
    r_eq : float
        Equilibrium bond length in atomic units
    """

Step 3: Examples Write two example calls showing how the function should be used, including expected output comments.
# Example 1:
evaluate_Morse(r_eq, De=0.4127, beta=1.372, r_eq=2.132) == 0.0  # Expected output: ~0.0

# Example 2:
evaluate_Morse(3.0, De=0.4127, beta=1.372, r_eq=2.132)  # <==  complete with expected output

Step 4: Body Implement the formula for the Morse potential:
V_Morse = De * (1 - np.exp(-beta * (r - r_eq)))**2
return V_Morse

Step 5: Test

Test the function with your example inputs using assertions or print statements.

assert np.isclose(evaluate_Morse(2.132, De_au, beta_au, r_eq_au), 0.0, atol=1e-6)

# TODO: Calculate by hand the expected Morse potential value at r = 3.0 au,
#       and assign it to the variable expected_Morse_3_au, e.g.
# expected_Morse_3_au = <your calculated value>

# TODO: Uncomment the line below after assigning expected_Morse_3_au
# assert np.isclose(evaluate_Morse(3.0, De_au, beta_au, r_eq_au), expected_Morse_3_au, atol=1e-6)
# TODO: Add the evaluate_Morse function here by following the Design Recipe steps above!

Plotting the Morse potential#

Now that you have defined the evaluate_Morse function, we will use it to create an array of potential values corresponding to an array of bond length values. This will define the Morse potential energy surface (PES) for the CO molecule.

import numpy as np
import matplotlib.pyplot as plt

r_values = np.linspace(0.2 * r_eq_au, 2.5 * r_eq_au, 500)
V_values = evaluate_Morse(r_values, De_au, beta_au, r_eq_au)

plt.plot(r_values, V_values, label="Morse Potential")
plt.axhline(0, color='gray', linestyle='--')
plt.axhline(0.4127, color='red', linestyle='--', label=r"$D_e$ (Dissociation Energy)")
plt.axvline(2.132, color='green', linestyle='--', label=r"$r_{eq}$ (Equilibrium Bond Length)")

plt.xlabel("Bond Length (au)")
plt.ylabel("Potential Energy (au)")
plt.title("Morse Potential for CO Molecule")
plt.tight_layout()
plt.legend()
plt.ylim(-0.05, 0.45)
plt.show()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[3], line 4
      1 import numpy as np
      2 import matplotlib.pyplot as plt
----> 4 r_values = np.linspace(0.2 * r_eq_au, 2.5 * r_eq_au, 500)
      5 V_values = evaluate_Morse(r_values, De_au, beta_au, r_eq_au)
      7 plt.plot(r_values, V_values, label="Morse Potential")

NameError: name 'r_eq_au' is not defined

Expanding the Morse Potential as a Taylor Series#

In the following block, we will compute the analytical \(k\), \(g\), and \(h\) terms defined in the Taylor series expansion of the Morse potential. We will also compare the value of \(k\) computed analytically to the value computed numerically.

Recall that \(k\), \(g\), and \(h\) are the second, third, and fourth derivatives of the Morse potential with respect to \(r\) evaluated at \(r_{eq}\). These derivatives can be expressed in terms of the Morse parameters as:

(53)#\[\begin{align} k &= 2 D_e \beta^2 \\ g &= -6 D_e \beta^3 \\ h &= 14 D_e \beta^4 \end{align}\]

Use the code block below to assign values to the variables k_au, g_au, and h_au (all in atomic units), utilizing the variables De_au and beta_au that hold the Morse parameters in atomic units.

# TODO: Assign values to k_au, g_au, and h_au using the formulas above
# Use the variables De_au and beta_au for De and beta in atomic units.

# Example:
# k_au = 2 * De_au * beta_au**2

# Your code here:
k_au = ...
g_au = ...
h_au = ...

# Print the results to check your work
print(f"k (2nd derivative) = {k_au:.5f} au")
print(f"g (3rd derivative) = {g_au:.5f} au")
print(f"h (4th derivative) = {h_au:.5f} au")

Numerical Computation of Derivatives Using Finite Differences#

In many real-world cases, the analytical expressions for the derivatives of physical potentials are not available or are very complicated to obtain. For example, potentials obtained from quantum chemistry calculations or empirical fits often come only as discrete data points without closed-form formulas.

Therefore, numerical differentiation techniques, such as finite difference methods, are invaluable tools to estimate these derivatives directly from computed potential energy values.

In this exercise, we will use a centered finite difference approach with a 5-point stencil to numerically approximate the second, third, and fourth derivatives of the Morse potential at the equilibrium bond length, \(r_{eq}\).

The formulas for these derivatives at \(r_{eq}\) are:

(54)#\[\begin{align} k_{\text{num}} &= \frac{-f_{i-2} + 16 f_{i-1} - 30 f_i + 16 f_{i+1} - f_{i+2}}{12 h^2} \\ g_{\text{num}} &= \frac{-f_{i-2} + 2 f_{i-1} - 2 f_{i+1} + f_{i+2}}{2 h^3} \\ h_{\text{num}} &= \frac{f_{i-2} - 4 f_{i-1} + 6 f_i - 4 f_{i+1} + f_{i+2}}{h^4} \end{align}\]

Here:

  • \(h\) is the step size between bond lengths (in atomic units)

  • \(f_i\) represents the Morse potential value at \(r_{eq}\)

  • \(f_{i \pm 1}\) and \(f_{i \pm 2}\) represent Morse potential values at points displaced by \(h\) and \(2h\) from \(r_{eq}\), respectively


Step-by-step instructions:

  1. Choose a small step size \(h\) (e.g., \(h = 0.01\) au).

  2. Create a list f to hold the Morse potential values at five points:

    • f[0] = V_{Morse}(r_{eq} - 2h)

    • f[1] = V_{Morse}(r_{eq} - h)

    • f[2] = V_{Morse}(r_{eq})

    • f[3] = V_{Morse}(r_{eq} + h)

    • f[4] = V_{Morse}(r_{eq} + 2h)

  3. Using the values in f and the step size h, evaluate the finite difference expressions above to compute k_num_au, g_num_au, and h_num_au.

  4. Store the computed derivatives in variables named k_num_au, g_num_au, and h_num_au.


Once you complete these steps, you will have numerical estimates of the second, third, and fourth derivatives of the Morse potential at \(r_{eq}\) which you can compare with the analytical values.

# Define the step size h (in atomic units)
h = 0.01

# Compute the five r values centered at r_eq_au
r_values = [
    r_eq_au - 2*h,
    r_eq_au - h,
    r_eq_au,
    r_eq_au + h,
    r_eq_au + 2*h
]

# TODO: Evaluate the Morse potential at each r value in r_values
#       and store the results in a list called f
# Example:
# f = [evaluate_Morse(r, De_au, beta_au, r_eq_au) for r in r_values]

# TODO: Compute the numerical second derivative (k_num_au) using the 5-point stencil formula

# TODO: Compute the numerical third derivative (g_num_au) using the 5-point stencil formula

# TODO: Compute the numerical fourth derivative (h_num_au) using the 5-point stencil formula

# TODO: Print the numerical derivatives for inspection
# Compare numerical derivatives to analytical values with error reporting

def print_comparison(name, analytical, numerical):
    error = abs(analytical - numerical)
    print(f"{name}:")
    print(f"  Analytical value = {analytical:.6f} au")
    print(f"  Numerical value  = {numerical:.6f} au")
    print(f"  Absolute error   = {error:.6e} au\n")

print_comparison("Second derivative (k)", k_au, k_num_au)
print_comparison("Third derivative (g)", g_au, g_num_au)
print_comparison("Fourth derivative (h)", h_au, h_num_au)

print("""
Note: Numerical derivatives are approximations that depend on the chosen step size (h).
A smaller h generally reduces truncation error but may increase rounding error.
Choosing an optimal step size is important for balancing accuracy and numerical stability.
""")

Comparing Taylor Expansions of the Morse Potential#

The Morse potential provides an exact analytical form that realistically models the anharmonic vibrational behavior of diatomic molecules. However, in practice, we often approximate potentials using Taylor expansions truncated at various orders — harmonic (quadratic), cubic, quartic, etc.

Comparing these truncated potentials to the full Morse potential helps us understand:

  • How well simpler approximations capture key physical features

  • The impact of including anharmonic corrections beyond the harmonic approximation

  • The range of bond lengths over which each approximation remains accurate

Visualizing these potentials together illustrates the trade-offs between computational simplicity and physical accuracy.


Below is the plot comparing the full Morse potential with its quadratic, cubic, and quartic Taylor expansions. The vertical green dashed line marks the equilibrium bond length \(r_{eq}\), and the horizontal red dashed line shows the dissociation energy \(D_e\).

# Calculate potentials
V_H = 0.5 * k_au * (r - r_eq_au) ** 2
V_C = V_H + (1/6) * g_au * (r - r_eq_au) ** 3
V_Q = V_C + (1/24) * h_au * (r - r_eq_au) ** 4

plt.plot(r, V_Morse, color='purple', label="Morse Potential")
plt.plot(r, V_H, 'r--', label="Harmonic Potential")
plt.plot(r, V_C, 'b--', label="Cubic Potential")
plt.plot(r, V_Q, 'g--', label="Quartic Potential")

# Mark equilibrium bond length (r_eq)
plt.axvline(r_eq_au, color='green', linestyle='--', label=r'$r_{eq}$')

# Mark dissociation energy (D_e)
plt.axhline(De_au, color='red', linestyle='--', label=r'$D_e$')

plt.xlim(0.5 * r_eq_au, 2.5 * r_eq_au)
plt.ylim(0, 1)
plt.xlabel("Bond Length (Bohr radii)")
plt.ylabel("Energy (Hartrees)")
plt.title("Comparison of Morse Potential and Taylor Expansions")
plt.legend()
plt.show()

Guided Questions: Interpreting the Potential Energy Plot#

  1. Dissociation Behavior:

    • Which of the potentials shown (Morse, Harmonic, Cubic, Quartic) correctly predict the dissociation of the molecule (i.e., energy leveling off at large bond lengths rather than increasing without bound)?

    • Why is correct dissociation behavior important for modeling molecular vibrations and reactions?

  2. Anharmonicity:

    • Which potentials exhibit anharmonic behavior? How can you tell by looking at the shape of each curve?

    • How does including cubic and quartic terms improve the approximation beyond the harmonic potential?

  3. Approximation Validity:

    • Over which range of bond lengths do the harmonic and truncated Taylor expansions provide a good approximation to the Morse potential?

    • At what point do these approximations break down, and what physical consequences might that have?

  4. Practical Considerations:

    • Considering computational cost and accuracy, when might it be acceptable to use a harmonic approximation instead of a full Morse potential?

    • How might the inclusion of cubic and quartic terms in the potential affect vibrational frequency calculations?


Reflect on these questions as you examine the plot and the differences among the potentials.

Computing Vibrational Transition Energies#

Using the Morse and Harmonic oscillator models, we will compute three key vibrational transition energies for CO:

  • Fundamental transition: from \(n=0\) to \(n=1\)

  • First overtone transition: from \(n=0\) to \(n=2\)

  • First hot band: from \(n=1\) to \(n=2\)


Reminder: Energy Level Formulas#

For the Morse oscillator, the energy levels are given by:

\[ E_n = \hbar \omega \left( n + \frac{1}{2} - \chi_e \left( n + \frac{1}{2} \right)^2 \right), \]

where

\[ \omega = \sqrt{\frac{2 D_e \beta^2}{\mu}}, \quad \chi_e = \frac{\hbar \omega}{4 D_e}. \]

For the Harmonic oscillator, the energy levels simplify to:

\[ E_n = \hbar \omega \left( n + \frac{1}{2} \right). \]

Task:#

  1. Compute \(E_0\), \(E_1\), and \(E_2\) for both models.

  2. Calculate the transition energies corresponding to the three transitions listed above.

  3. Convert all energies from atomic units (Hartrees) to wavenumbers in cm\(^{-1}\).

Use the conversion factor:

\[ 1\, \text{Hartree} = 219474.63 \, \text{cm}^{-1}. \]
# Conversion factor from Hartree to cm^-1
hartree_to_cm = 219474.63

# Compute omega and chi_e using the Morse parameters
omega = np.sqrt(2 * De_au * beta_au**2 / mu_au)
chi_e = (omega) / (4 * De_au)

def E_morse(n):
    """Compute Morse oscillator energy level E_n (in atomic units)"""
    # TODO: Implement formula:
    # E_n = omega * (n + 0.5 - chi_e * (n + 0.5)**2)
    pass

def E_harmonic(n):
    """Compute Harmonic oscillator energy level E_n (in atomic units)"""
    # TODO: Implement formula:
    # E_n = omega * (n + 0.5)
    pass

# TODO: Compute energy levels for n = 0, 1, 2 using your functions and assign:
# E0_morse = ...
# E1_morse = ...
# E2_morse = ...
#
# E0_harm = ...
# E1_harm = ...
# E2_harm = ...

# TODO: Calculate transition energies (in atomic units):
# Fundamental transition (0 -> 1)
# fund_morse = ...
# fund_harm = ...
#
# First overtone (0 -> 2)
# overtone_morse = ...
# overtone_harm = ...
#
# First hot band (1 -> 2)
# hotband_morse = ...
# hotband_harm = ...

# TODO: Convert all transition energies from atomic units to cm^-1:
# fund_morse_cm = ...
# fund_harm_cm = ...
#
# overtone_morse_cm = ...
# overtone_harm_cm = ...
#
# hotband_morse_cm = ...
# hotband_harm_cm = ...

# Print the results
print(f"Transition Energies (cm^-1):")
print(f"{'Transition':<20}{'Morse':>12}{'Harmonic':>12}")
print(f"Fundamental (0->1): {fund_morse_cm:12.2f}{fund_harm_cm:12.2f}")
print(f"First overtone (0->2): {overtone_morse_cm:12.2f}{overtone_harm_cm:12.2f}")
print(f"First hot band (1->2): {hotband_morse_cm:12.2f}{hotband_harm_cm:12.2f}")

Reflection Questions: Vibrational Transition Energies#

  1. Harmonic Approximation & Hot Band:

    • Notice that in the harmonic oscillator model, the energy difference for the first hot band (transition from \(n=1\) to \(n=2\)) is identical to the fundamental transition (\(n=0\) to \(n=1\)). Why does this happen?

    • Were you expecting this result based on what you know about the harmonic oscillator? Explain your reasoning.

  2. Comparing Energy Levels:

    • Compare the fundamental transition predicted by the Morse model and the harmonic approximation. Which one is higher or lower in energy / wavenumber? Which is closer to the experimentally measured value for the fundamental in CO? What physical effects cause these differences?

    • Order the positions of the Morse fundamental, harmonic fundamental, Morse first overtone, and Morse first hot band from smallest to largest in terms of wavenumbers. Briefly explain what gives rise to this observed relative ordering.

  3. Selection Rules:

    • Recall the harmonic oscillator selection rules you learned earlier, which typically allow transitions with \(\Delta n = \pm 1\). Based on these rules, is the first overtone (\(n=0\) to \(n=2\)) allowed or forbidden?

    • How do selection rules differ in the Morse oscillator? Is the first overtone allowed there, and why?

    • Reflect on how anharmonicity affects vibrational spectroscopy and the appearance of overtones and hot bands in real molecular spectra.


Take some time to write detailed answers, using your calculations and prior knowledge of quantum vibrational transitions.