About Issues Tutorials Documentation
</span>
This notebook uses basic quantum chemical calculations to calculate the absorption spectra of a small molecule.
In [ ]:
%matplotlib inline
import numpy as np
from matplotlib.pylab import *
try: import seaborn #optional, makes plots look nicer
except ImportError: pass
import moldesign as mdt
from moldesign import units as u
In [ ]:
qmmol = mdt.from_name('benzene')
qmmol.set_energy_model(mdt.models.CASSCF, active_electrons=6,
active_orbitals=6, state_average=6, basis='sto-3g')
In [ ]:
properties = qmmol.calculate()
This cell print a summary of the possible transitions.
Note: you can convert excitation energies directly to nanometers using Pint by calling energy.to('nm', 'spectroscopy')
.
In [ ]:
for fstate in range(1, len(qmmol.properties.state_energies)):
excitation_energy = properties.state_energies[fstate] - properties.state_energies[0]
print('--- Transition from S0 to S%d ---' % fstate )
print('Excitation wavelength: %s' % excitation_energy.to('nm', 'spectroscopy'))
print('Oscillator strength: %s' % qmmol.properties.oscillator_strengths[0,fstate])
Of course, molecular spectra aren't just a set of discrete lines - they're broadened by several mechanisms. We'll treat vibrations here by sampling the molecule's motion on the ground state at 300 Kelvin.
To do this, we'll sample its geometries as it moves on the ground state by:
In [ ]:
mdmol = mdt.Molecule(qmmol)
mdmol.set_energy_model(mdt.models.GaffSmallMolecule)
mdmol.minimize()
In [ ]:
mdmol.set_integrator(mdt.integrators.OpenMMLangevin, frame_interval=250*u.fs,
timestep=0.5*u.fs, constrain_hbonds=False, remove_rotation=True,
remove_translation=True, constrain_water=False)
mdtraj = mdmol.run(5.0 * u.ps)
In [ ]:
post_traj = mdt.Trajectory(qmmol)
for frame in mdtraj:
qmmol.positions = frame.positions
qmmol.calculate()
post_traj.new_frame()
This cell plots the results - wavelength vs. oscillator strength at each geometry for each transition:
In [ ]:
wavelengths_to_state = []
oscillators_to_state = []
for i in range(1, len(qmmol.properties.state_energies)):
wavelengths_to_state.append(
(post_traj.state_energies[:,i] - post_traj.potential_energy).to('nm', 'spectroscopy'))
oscillators_to_state.append([o[0,i] for o in post_traj.oscillator_strengths])
for istate, (w,o) in enumerate(zip(wavelengths_to_state, oscillators_to_state)):
plot(w,o, label='S0 -> S%d'%(istate+1),
marker='o', linestyle='none')
xlabel('wavelength / nm'); ylabel('oscillator strength'); legend()
In [ ]:
from itertools import chain
all_wavelengths = u.array(list(chain(*wavelengths_to_state)))
all_oscs = u.array(list(chain(*oscillators_to_state)))
hist(all_wavelengths, weights=all_oscs, bins=50)
xlabel('wavelength / nm')
In [ ]: