Welcome to pyGDM

pyGDM is an open source python toolkit for electro-dynamical simulations, based on the Green dyadic method (GDM). In contrast to most other coupled-dipole codes, pyGDM uses a generalized propagator, which allows to cost-efficiently treat large monochromatic problems such us polarization-resolved calculations or raster-scan simulations.

pyGDM includes tools to easily derive several physical quantities such as far-field patterns, extinction and scattering cross-sections, the electric and magnetic near-field in the vicinity of the structure, the surface-LDOS or the heat deposited inside the nanoparticle. pyGDM furthermore offers a toolkit for evolutionary optimization of nanoparticle geometries: The EO module allows to automatically design nanostructures which optimize optical properties such as a certain resonance wavelength, strong field enhancement or the direction of scattering.

You can download the code from the pypi repository or clone it from gitlab (see also the Overview section)

Please send comments, suggestions and report bugs by mail or via the gitlab issue tracker


If you use pyGDM for your work, please cite the paper (bibtex):

P. R. Wiecha
pyGDM - A python toolkit for full-field electro-dynamical simulations and evolutionary optimization of nanostructures
arXiv:1802.04071 [cond-mat, physics:physics] (2018)

Key features

  • Easy to install and easy to use: Fully relying on freely available open-source python libraries (numpy, scipy, matplotlib)

  • Fast: Performance-critical parts are implemented in fortran and are parallelized with openmp, efficient and parallelized scipy libraries are used when possible. Spectra can be calculated very rapidly via an MPI-parallelized routine

  • Electro-dynamical simulations including a substrate

  • Different illumination sources such as plane wave, focused beam or dipolar emitter. Easy to implement own light sources in python

  • Efficient calculation of large monochromatic problems such as raster-scan simulations (example)

  • Provide tools to rapidly post-process the simulations and derive physical quantities such as

    • near-field inside and around nanostructures (example)
    • extinction, absorption and scattering cross-sections (example)
    • polarization- and spatially resolved far-field scattering (example)
    • heat generation, temperature rise around nano-objects (example)
    • efficient and rapid raster-scan simulations (example)
    • surface photonic local density of states (SP-LDOS) (example)
    • modification of the decay-rate of dipolar emitters (example)
  • Many easy to use visualization tools, including animations of the electro-magnetic fields

  • Evolutionary optimization of the nano-particle geometry with regards to specific optical properties (example)

About the above animation

The animation at the top of this page was generated from the image


with the below script.

In the script the pyGDM function structures.image_to_struct is used to convert the bitmap pixel by pixel into a planar nano-structure: Every pixel darker than a specific threshold will be considered material (gold in the below example), all brighter pixels are part of the environment. The planar structure is then discretized on a cubic mesh using a pre-defined scaling and structure height. The time-harmonic electric field inside the gold-letter structure resulting from plane wave illumination is then calculated using pyGDM’s core.scatter and finally converted into a movie with visu.animate_vectorfield.

The structure is approximately 1100nm long, 300nm wide and 8nm high (one layer of meshpoints). It is made of gold, placed in vacuum and illuminated from your position towards the computer screen by a plane wave of 700nm wavelength, linearly polarized along 45°.

All other videos in this documentation are showing planar aluminum structures using a discretization of 5nm under 700nm wavelength plane wave illumination with -45° linear polarization. Aluminum has a far higher imaginary part of the dielectric function, which causes high losses due to absorption inside the metal. Due to these losses, the fields decay very quickly which looks “smoother”, which is why we use it in the here shown videos.

## --- load pyGDM
from pyGDM2 import structures
from pyGDM2 import materials
from pyGDM2 import fields

from pyGDM2 import core
from pyGDM2 import tools
from pyGDM2 import visu

import matplotlib.pyplot as plt

# Setup the simulation
## --- structure / environment
n1, n2 = 1.0, 1.0  # vacuum env.
step = 8.0
geometry = structures.image_to_struct("pyGDM_logo_static.png",
                      useDarkPixel=1, threshold=100, H=1,
                      nm_per_pixel=1.*step, stepsize=step)
material = materials.gold()
struct = structures.struct(step, geometry, material, n1,n2,

## --- incident field
field_generator = fields.planewave
kwargs = dict(theta = [45.0])
wavelengths = [700]
efield = fields.efield(field_generator, wavelengths=wavelengths,

## --- simulation object
sim = core.simulation(struct, efield)

# Run the simulation
E = core.scatter(sim)
NF = tools.get_field_as_list_by_fieldindex(sim, 0)

# create the field-animation
## setup figure / axes
ax = plt.subplot(aspect='equal')
plt.subplots_adjust(left=0, right=1, bottom=0,top=1)

## geometry
s = visu.structure(sim, scale=0.1, color='.75', show=0)

## field-animation
config_vectorfield = dict(cmin=0.5, cmap=plt.cm.Blues,
                        borders=50, vecwidth=0.8)
ani = visu.animate_vectorfield(NF, Nframes=100, scale=12,
                            ax=ax, show=False)
## save video to file
ani.save('pyGDM_logo.mp4', writer="ffmpeg",
         codec='h264', bitrate=1500)


Similarly, 3D represantations of the fields can be animated using:

from pyGDM2 import visu3d
from mayavi import mlab

fig = mlab.figure( size=(600, 300), bgcolor=(1.0, 1.0, 1.0), fgcolor=(0.,0.,0.) )

## structure
visu3d.structure(sim, axis_labels=False, draw_substrate=False,
                opacity=0.1, show=False)

## 3D field-animation
ani2 = visu3d.animate_vectorfield(NF, Nframes=100, scale=8,
                        draw_substrate=False, substrate_size=1.1,
                        colormap='Blues', clim=[0.0, 0.5],
                        fig=fig, view=(85, -45, 350, (0,0,-15)),
                        ffmpeg_args="-b:v 1.5M -c:v libx264", mov_file="3D.mp4",

which (depending on the model of course) will result in something like:

Indices and tables