Coupled Dipole Approximation in Python
Posted on Wed 20 July 2016 in Plasmonics
Coupled dipole approximation (CDA) method is a numerical method to calculate the optical properties (scattering and absorption) of interacting dipoles. This method is used in discrete dipole approximation method (like in DDSCAT software), where a big particle (also known as target) is broken into lot of interacting dipoles arranged in cubic lattice. CDA can also be used to calculate the optical properties (scattering and absorption) of random particle distributions (like in L. Zhao et al. J. Phys. Chem. B, 107, 30, 7343, 2003) and assuming each particle to be small enough that it behaves like a dipole.
I have implemented CDA in python and used it to calculate the optical properties of nanoparticles that are arranged randomly in cuboid or on a rectangular grid. Once the incident electric field direction (\(k\) vector), polarization, positions and radii of particles are given, the code calculates the extinction, scattering and absorption cross-sections. It is important to note that the nano particles should be small enough so that they can act as dipole with quasi-static polarizability.
If you are interested in the numerical part of the code, see below:
The goal of CDA method is to calculate the self-consistent dipole moments of the dipoles that are interacting with each other. Once dipole moments are calculated, scattering and absorption cross-sections can be calculated. Most of the write up below is from Bruce T. Draine and Piotr J. Flatau, "Discrete-Dipole Approximation For Scattering Calculations," J. Opt. Soc. Am. A 11, 1491-1499 (1994).
Let start for simplicity by assuming two dipoles, dipole \(1\) positioned at \(\vec{r}_1\) and dipole \(2\) positioned at \(\vec{r}_2\).
The dipole moment of dipole \(1\) is given by \(\vec{p}_1 = p_{1x}\vec{i}+p_{1y}\vec{j}+p_{1z}\vec{k} = \alpha \vec{E}_1\), where \(\vec{E}_1 = E_{1x}\vec{i}+E_{1y}\vec{j}+E_{1z}\vec{k}\) is the local electric field at dipole \(i\).
Here,
is the isotropic polarizability tensor of the \(i\)-th dipole.
The polarizability of the dipole is generally known (generally assumed to follow Clausius-Mossotti relation), but we do not know the local electric field at the dipole \(i\), because there are complex contributions from other dipoles (like dipole \(2\)).
Lets write down the local electric field at dipole \(2\): there will be an incident electric field which is given by \(\vec{E}_{2inc} = \vec{E}_o e^{i\vec{k}\vec{r}_2}\) and an electric field emanating from dipole \(1\):
Here \(r_{21} = |\vec{r}_2 - \vec{r}_1|\), \(\vec{n}_{21} = \frac{\vec{r}_2 - \vec{r}_1}{r_{21}}\), and \(k = |\vec{k}|\) is the wavevector of the incident wave.
For a constant \(k\), at the distances near the dipole \(1\), the second term dominates (near field); the first term dominates at farther distances (far field).
The above equation can be reduced to a matrix form:
where, \(A_{12} = \frac{k^2}{4\pi\epsilon_o}\frac{e^{ikr_{21}}}{r_{21}}\) and \(B_{12} = \left[\frac{1}{r_{21}^3}-\frac{ik}{r_{21}^2}\right]\frac{e^{ikr_{21}}}{4\pi\epsilon_o}\)
Similarly, we write the electric field near dipole 1 as:
These two equations can be combined in the form of \(AP = E\) matrix equation:
We calculate \(A\) from positions and polarizability, and \(E\) from the incident fields. We solve for \(P\) using numerical iterative methods. For solving \(AP=E\), I use Scipy's BiConjugate Gradient Stabilized method.