Home Examples Screenshots User manual Bluesky logo YouTube
OghmaNano Multiphysics simulation platform for optoelectronic devices and photonic systems DOWNLOAD Quick Start guide

2D FDTD Simulation of Perovskite Solar Cells Coupled to a Drift-Diffusion Model

1. Introduction

In this tutorial we simulate a perovskite solar cell using a single, integrated simulation that couples a 2D Finite-Difference Time-Domain (FDTD) optical model to a drift-diffusion electrical model. The FDTD solver calculates how light propagates and is absorbed inside the device, and the drift-diffusion solver then uses this information to calculate the flow of charge and the final current density–voltage (JV) curve. Everything happens in one run: you press Run once, and OghmaNano performs the optics and the electronics for you.

Why use FDTD here at all? Many perovskite cells include light-trapping structures, such as textured or pyramidal layers, that are designed to scatter light and increase absorption. In a device like this the optical field is genuinely two-dimensional: light bends, scatters, and concentrates in ways that a simple 1D optical model (such as the transfer matrix method) cannot capture. FDTD solves Maxwell’s equations directly on a grid, so it resolves the full spatial structure of the field and tells us exactly where light is absorbed inside the cell.

The coupling between the two models is what makes this simulation powerful. FDTD gives us the electric field \(\mathbf{E}\) everywhere in the device. From this we obtain the absorbed optical power density, which is proportional to \(\sigma |\mathbf{E}|^2\), where \(\sigma\) describes the optical loss of each material. Dividing by the photon energy converts this absorbed power into an optical generation rate \(G(x,y)\)—the number of electron–hole pairs created per unit volume per second at every point in the cell. This spatial generation rate is then handed directly to the drift-diffusion solver, which calculates how those photogenerated carriers move, recombine, and are collected at the contacts, producing the JV curve.

By the end of this tutorial you will have opened the example, run the coupled simulation, and inspected the three most important outputs: the triangular device mesh that describes the geometry, the optical generation profile produced by FDTD, and the JV curve that summarises how well the cell performs.

2. Making a new simulation

Open the New simulation window and select the FDTD examples category (??). Then choose the Perovskite FDTD example (??). Save the simulation to a suitable folder; this loads the main interface shown in ??.

OghmaNano New simulation window showing device categories including an FDTD examples option.
The New simulation window. Open FDTD examples.
FDTD example list including the Perovskite FDTD example.
FDTD examples list. Select Perovskite FDTD.

3. Orienting yourself in the main window

After loading the simulation, the main window will appear as shown in ??. The structure is displayed in the 3D view in the Device structure tab. The black background represents the world—the simulation domain in which the device sits.

Several important elements are visible. At the top of the device, the block of green arrows represents the FDTD light source. Light is injected from above and travels downwards into the cell, just as sunlight would illuminate a real solar cell. Below the source you can see a detector plane: this measures the electromagnetic field as light passes through it, and its readings are essential for later reconstructing the optical generation profile inside the device.

Running vertically through the structure is a purple grid. This is the FDTD mesh, and it shows the plane through which the simulation is solved—in effect we are taking a 2D slice through the device. Near the top of the cell you can also see a triangular light-trapping structure, which is designed to scatter incoming light and increase absorption. Beneath it lie the functional perovskite device layers (for example the transparent contact, electron and hole transport layers, the perovskite absorber, and the metal back contact) stacked to form the working solar cell.

It should be noted that the detectors do not interfere with the light itself; they simply measure the electromagnetic fields.

Main OghmaNano window showing a perovskite solar cell with a top light source, an FDTD mesh slice, a detector plane, a triangular light-trapping structure, and the stacked device layers.
The main OghmaNano interface after loading the Perovskite FDTD example.

In a moment we will run the simulation and watch how light travels down into the structure, is scattered by the light-trapping layer, and is absorbed in the perovskite. This absorption is what generates the charge carriers that the electrical model subsequently collects.

4. Running the simulation

Once you have saved the simulation and had a look around the structure, click the Run simulation (▶) button to start the calculation. The window will switch to the Terminal tab, where you can follow the progress of the run. The simulation proceeds through several stages, shown in ????, and produces the outputs shown in ??.

Calibration run. As the FDTD module starts (??), the very first thing it does is a calibration simulation. In this step OghmaNano temporarily removes the device from the domain and propagates the source pulse through empty space. This records a clean reference measurement of the incident field at the detectors—how much light would arrive if the device were not there at all. Later, the code compares the real run (with the device present) against this reference. That comparison is what allows OghmaNano to separate the light that is reflected, transmitted, and genuinely absorbed, and therefore to calculate the optical generation profile inside the cell accurately. While calibration is running, each printed line is tagged with the word calibration.

Main optical run. Once calibration is complete (??), the word calibration disappears from the output and the real FDTD simulation of the device begins, stepping the electromagnetic field forward in time. Notice that the progress text is printed in green. This is deliberate: this particular example is solved at a single wavelength of roughly 550 nm, which lies in the green part of the visible spectrum, and OghmaNano colours the timestep text to match the wavelength currently being simulated.

Electrical run. When the FDTD stage finishes, the terminal reports the elapsed time—here the optical run took around 30 seconds (??). It is worth noting that FDTD is inherently slow, because it explicitly simulates the propagation of light through the structure timestep by timestep. Once the optics are done, OghmaNano automatically moves on to the electrical simulation and sweeps out a JV curve using the generation profile that FDTD has just calculated. In the terminal you will see the applied voltage stepped from 0 V upwards, together with the resulting current density. A negative current density indicates that the cell is generating current—i.e. it is behaving as a working solar cell under illumination.

When the run has completed, switch to the Output tab (??) to find the data generated during the simulation. We will look at the most important outputs in the next section.

Terminal tab showing the FDTD module starting and the calibration run, where each timestep line is tagged with the word calibration.
The FDTD module starts with a calibration run through empty space.
Terminal tab showing calibration finished and the main FDTD run beginning, with green timestep text corresponding to a single wavelength near 550 nm.
Calibration finishes and the main optical run begins; green text denotes a ~550 nm wavelength.
Terminal tab showing the FDTD run completing in about 30 seconds, then the electrical drift-diffusion JV sweep running with negative current density values.
The optical run completes (~30 s), then the JV sweep runs; negative current means generation.
Output tab listing the files produced by the coupled perovskite FDTD and drift-diffusion simulation.
The Output tab after the run, listing the generated data files.

5. Viewing the results

With the run complete, we can inspect the outputs from the Output tab (??). We will focus on the three most informative results: the device mesh, the optical generation profile, and the JV curve.

Device mesh. First, open device to view the geometry, shown in ??. This reveals how OghmaNano actually represents the structure internally: the entire device is discretised into a large number of triangles. This triangular mesh is what the solver really “sees”, and you can rotate and zoom around it freely to inspect how the layers and the light-trapping structure are built up.

Optical generation profile. Next, open G to view the optical generation rate, shown in ??. This is the spatial map of where electron–hole pairs are created inside the device, calculated directly from the FDTD field. It is plotted in units of \(\mathrm{m^{-3}\,s^{-1}}\), i.e. the number of carriers generated per unit volume per second. You can clearly see the generation concentrated within the active region, with brighter regions where the light-trapping structure has enhanced absorption. This profile is precisely the quantity that is passed to the electrical model.

JV curve. Finally, and most importantly for a quick assessment of device performance, open jv to view the current density–voltage curve, shown in ??. For this example the cell reaches an open-circuit voltage (\(V_{oc}\)) of just over 1 V and a short-circuit current density (\(J_{sc}\)) of roughly −150 A m−2. The negative sign simply reflects the sign convention that photogenerated current flows in the opposite direction to an applied forward bias. Note that, as everywhere in OghmaNano, all quantities are expressed in SI units.

3D triangular mesh of the perovskite solar cell, showing how the entire device is discretised into triangles.
The device is built from triangles: this is how the solver represents the geometry internally.
Optical generation rate map of the perovskite cell in units of per cubic metre per second, calculated from the FDTD field, showing carrier generation concentrated in the active region.
The optical generation profile \(G(x,y)\), computed from the FDTD field and passed to the electrical model.
Current density versus applied voltage curve for the perovskite cell, showing an open-circuit voltage just above 1 V and a short-circuit current density of about minus 150 amps per square metre.
The JV curve: \(V_{oc}\) just above 1 V and \(J_{sc}\approx-150\;\mathrm{A\,m^{-2}}\) (SI units throughout).

6. Examining the results in detail

The simulation we have just run really has two parts: an FDTD optical calculation and a drift-diffusion electrical calculation. OghmaNano saves detailed snapshots from both stages, and we can step through them to understand exactly what is happening inside the device. We will look at the optical results first and then the electrical results.

The FDTD (optical) snapshots. From the Output tab, double-click on fdtd_snapshots. This opens the snapshot viewer shown in ??, which is essentially a complete dump of the FDTD field as it evolved during the run. The viewer lets you inspect the results as a function of simulation step. Click the blue + button and select power_density.csv, then drag the scroll bar to move through the timesteps and watch how the field propagates down into the device and is scattered by the structure. If you would rather look at the raw field components, you can add Ex, Ey, or Ez instead of the power density.

The electrical snapshots. The electrical results are stored separately. From the Output tab, double-click on the snapshots directory (as opposed to fdtd_snapshots). Using the + button, add Ec.csv, Ev.csv, Fn.csv, and Fp.csv to plot the conduction band edge, the valence band edge, and the electron and hole quasi-Fermi levels, as shown in ??. Note that this time the slider steps through applied voltage rather than time (the window title reports the current bias, e.g. 0.1 V), so you can watch the band structure respond as the cell is swept from short circuit towards open circuit.

Carrier densities. A closely related view is obtained by adding Q_nfree.csv and Q_pfree.csv, which give the free electron and free hole densities (in \(\mathrm{m^{-3}}\)). The result is shown in ??. Again, stepping the slider through voltage lets you see how the electron and hole populations redistribute across the device as the applied bias changes.

FDTD snapshot viewer showing the optical power density inside the perovskite device as a coloured field on a slice through the structure.
FDTD snapshots: the optical power density (W m−2) stepped through simulation time.
Electrical snapshot viewer showing the conduction band, valence band, and electron and hole quasi-Fermi levels across the device as wireframe surfaces.
Electrical snapshots: band edges (Ec, Ev) and quasi-Fermi levels (Fn, Fp), stepped through voltage.
Electrical snapshot viewer showing the free electron and free hole carrier densities across the device as wireframe surfaces.
Carrier densities: free electrons (Q_nfree) and free holes (Q_pfree) as a function of voltage.

7. The effect of the light-trapping structure

The triangular layer on top of the cell is a textured light-trapping structure (it also acts as an anti-reflection layer). We can use the simulation to measure exactly what it does by switching it off and comparing the result against the original device.

Save a reference JV curve. Before changing anything, make a copy of the results file jv.csv and rename the copy jv_backup.csv using your operating system’s file manager. This preserves the JV curve of the full device so that we can compare against it later.

Disable the structure. Right-click on the triangular structure on top of the device and select Edit object, as shown in ??. This opens the object editor, shown in ??. Click the enable/disable button in the toolbar so that it reads Object disabled. The triangular structure will now disappear from the device, leaving the flat stack shown in ??.

What have we actually removed? A textured layer like this does two useful things for a solar cell. First, by replacing the abrupt flat interface with a graded, angled surface, it reduces front-surface reflection, so more light enters the device instead of bouncing straight back off the top. Second, it scatters and redirects the transmitted light so that it travels at an angle and follows a longer path through the absorber, increasing the chance of absorption. Together these effects raise the total absorbed light and therefore the short-circuit current. In real devices—silicon cells are the classic example, where micron-scale pyramids are routinely etched into the surface—this benefit is well established but can be difficult to isolate and quantify experimentally. A simulation lets us switch the structure on and off and read off its effect directly.

Rerun and compare. With the triangular structure now disabled, rerun the simulation. This produces a fresh jv.csv for the device without the light-trapping layer. Plot this new jv.csv together with the saved jv_backup.csv (the full device) on the same axes; you should obtain something like ??. The difference is modest but clearly visible: with the light-trapping structure in place, the magnitude of the short-circuit current is larger (around −162 A m−2) than without it (around −155 A m−2). This confirms that the texture increases the amount of light absorbed and hence the current the cell can deliver.

Right-click menu on the triangular light-trapping structure showing the Edit object option.
Right-click the triangular structure and select Edit object.
Object editor window with the enable/disable button in the toolbar set to Object disabled.
In the object editor, toggle the toolbar button to Object disabled.
Device view showing the flat stack after the triangular light-trapping structure has been disabled.
The device with the light-trapping structure removed.
JV curves compared with and without the triangular light-trapping structure, showing a larger short-circuit current magnitude when the structure is present.
JV curves with and without the structure: enabling the texture increases the short-circuit current.

8. Reducing the dimensionality of the electrical problem

The cell we are simulating is arguably a genuinely two-dimensional structure: the light-trapping texture on top breaks the flat, layered symmetry of a simple planar device, so light scatters sideways and the optical field varies in the plane of the cell as well as through its thickness. For that reason it makes good physical sense to simulate it in 2D. The price you pay, however, is simulation time and complexity. We are running an FDTD optical simulation—which is inherently slow because it explicitly time-steps the propagation of light—coupled to a full 2D electrical drift-diffusion simulation. It is therefore worth exploring how far we can reduce the dimensionality of the problem without losing the physics we care about. We will begin with the electrical problem.

Go to the Electrical ribbon, shown in ??, and click on Electrical mesh. This opens the electrical mesh editor, shown in ??, which defines how the device is discretised for the electrical calculation. Here you can see that the problem is being solved quite finely in the y direction (through the thickness of the device), with 40 mesh points, and much more coarsely across the device in the x direction, with only 10 mesh points. The y direction is where the important band bending and carrier transport happen, so it deserves the fine mesh; the x direction carries far less of the physics.

To collapse the electrical problem to one dimension, click the large X Dimension button at the top of the mesh editor. This removes the x discretisation entirely, leaving only the y mesh, as shown in ??. The electrical simulation is now a 1D problem, solving only through the thickness of the device.

The Electrical ribbon in OghmaNano, showing the Electrical mesh button used to open the electrical mesh editor.
The Electrical ribbon. Click Electrical mesh.
Electrical mesh editor showing 40 mesh points in the y direction and 10 mesh points in the x direction, i.e. a 2D electrical mesh.
The 2D electrical mesh: fine in y (40 points), coarse in x (10 points).
Electrical mesh editor after disabling the x dimension, leaving only the y mesh, i.e. a 1D electrical mesh.
After clicking X Dimension: only the y mesh remains—a 1D electrical problem.

Now rerun the simulation. What we have built is a 2D optical simulation coupled to a 1D electrical simulation: the optics still capture the full 2D behaviour of the light-trapping structure, while the electrical solve is reduced to a fast 1D transport problem through the device thickness. You can inspect the JV curve exactly as before. If you double-click on the snapshots directory and plot the carrier densities, you will now see something like ??. Rather than the 2D wireframe surfaces we saw earlier, the free electron and hole densities are now plotted as simple 1D line profiles through the device—confirming that the electrical problem really is one-dimensional.

This is a genuinely useful modelling strategy. It lets you keep the dimensionality high where it matters—in the optics, where the light-trapping structure demands a 2D treatment—while reducing the electrical problem to 1D, where a through-thickness description is often perfectly adequate and runs far more quickly. (The implicit assumption is that lateral carrier transport across the device is not critical, which is reasonable for many thin-film cells.)

Carrier density snapshot showing free electron and hole densities as 1D line profiles through the device thickness after reducing the electrical problem to 1D.
With the electrical problem reduced to 1D, the carrier densities become simple line profiles through the device.

9. Reducing the dimensionality of the optical problem

Having reduced the electrical problem, we can now do the same for the optical problem and see just how compact we can make the whole simulation. Go to the Optical ribbon, shown in ??, and click on Optical mesh. This opens the optical mesh editor, shown in ??. As with the electrical mesh, click the X Dimension button to remove the x discretisation. The optical problem is now solved in one dimension, as shown in ??, which shrinks the optical calculation dramatically.

While you are in the optical mesh editor, it is worth looking at the wavelength mesh on the right. You will see that the simulation is currently solving at only a single point in wavelength, placed roughly in the middle of the 300–800 nm range at around 550 nm (the same green wavelength we used for the FDTD run earlier). In other words, this example does not simulate the full solar spectrum—it evaluates the device at just one colour of light. If you wanted the complete solar-spectrum response, you would need to add many more wavelength points (at least around 20 to resolve the spectrum sensibly). That is perfectly possible and entirely valid, but the computational time would increase significantly, so we keep to a single wavelength here to keep the demo fast.

Now run the simulation again. At this point we have a 1D optical simulation coupled to a 1D electrical simulation—the most lightweight version of the model. You can inspect the 1D FDTD result from the snapshot viewer, as shown in ??. The optical power density is now a single 1D line profile as the pulse travels through the device, rather than the 2D field map we saw at the start of the tutorial.

The Optical ribbon in OghmaNano, showing the Optical mesh button used to open the optical mesh editor.
The Optical ribbon. Click Optical mesh.
Optical mesh editor showing x, y, and wavelength meshes, i.e. a 2D optical simulation with a single wavelength point.
The 2D optical mesh, with x, y, and a single-point wavelength mesh.
Optical mesh editor after disabling the x dimension, leaving only the y and wavelength meshes, i.e. a 1D optical simulation.
After clicking X Dimension: only the y mesh remains—a 1D optical problem.
FDTD snapshot showing the optical power density as a 1D line profile through the device after reducing the optical problem to 1D.
The 1D FDTD result: the optical power density is now a single line profile through the device.

10. A faster alternative: the transfer matrix method

To finish the tutorial, we will switch from FDTD—which, as we have seen, is very computationally intensive—to the much cheaper transfer matrix method (TMM). In most solar-cell tools the transfer matrix method is thought of as a strictly one-dimensional model, only really suited to flat, planar stacks. However, because of the way OghmaNano is organised, you can apply the transfer matrix model in any direction and in any dimensionality, which makes it a flexible drop-in replacement for FDTD in many situations.

Go to the Optical ribbon and click on the Transfer matrix button. This opens the optical simulation editor shown in ??. Click Run optical simulation, and you will obtain a photon distribution much like the one shown there. What OghmaNano has done here is apply the transfer matrix method across the 2D device, solving it as a series of independent vertical slices down the structure. Crucially, unlike FDTD there is no cross-coupling between neighbouring slices: the transfer matrix method is a much simpler approximation of Maxwell’s equations, so light cannot scatter sideways from one slice into the next. In exchange for that approximation, it runs much, much faster than FDTD, because there is no time-stepping of the field.

Optical simulation editor showing the photon distribution across the 2D device calculated with the transfer matrix method as a set of independent vertical slices.
The transfer matrix method applied across the 2D device: independent vertical slices, with no lateral cross-coupling.

Because the transfer matrix method is so cheap, we can now afford to solve over many wavelengths rather than a single one. Go back to the Optical mesh editor and set the wavelength mesh to around 20 points, then rerun the optical simulation. While it is running you will see the terminal work through each wavelength in turn, as shown in ??. Each optical slice is solved at its own wavelength (here stepping from roughly 312.5 nm to 787.5 nm), and the text is colour-coded to indicate the wavelength currently being solved.

Once the run has finished, return to the transfer matrix window, ??, and select the Photon distribution absorbed tab. You can now use the slider along the bottom of the window to step through wavelength and see where in the device each colour of light is absorbed. In the example shown the slider is at 587.5 nm, and you can see the corresponding absorption profile inside the perovskite device. This is a quick and intuitive way to understand how different parts of the solar spectrum are absorbed at different depths in the cell.

Terminal showing the transfer matrix method solving each optical slice at a series of wavelengths from about 312.5 nm to 787.5 nm, with colour-coded output.
The multi-wavelength transfer matrix run, solving each optical slice wavelength by wavelength.
Transfer matrix window on the Photon distribution absorbed tab, with a slider at 587.5 nm showing where that wavelength is absorbed within the perovskite device.
The Photon distribution absorbed tab: slide through wavelength to see where each colour is absorbed (here 587.5 nm).

11. Choosing the optical generation model

By default, this simulation uses the FDTD solver as its optical generation model—this is what feeds the generation profile into the electrical calculation. If you would rather use the faster transfer matrix method to drive the electrical simulation, you can change the generation model directly. Open the ribbon shown in ?? and click on the JV editor. In the JV editor, under Charge carrier generation, change the Charge carrier generation model from FDTD to transfer matrix, as shown in ??. From then on the optical generation profile will be calculated with the transfer matrix method rather than with FDTD.

The Editors ribbon in OghmaNano, showing the JV editor button used to open the JV experiment window.
Open the JV editor from the ribbon.
JV experiment window showing the Charge carrier generation model setting, which can be switched between FDTD and transfer matrix.
In the JV editor, switch Charge carrier generation model from FDTD to transfer matrix.

Summary. Over the course of this tutorial we have taken a single device through a whole range of modelling choices. We started with a full 2D FDTD optical simulation coupled to a 2D drift-diffusion electrical model of a perovskite cell with a complex, light-trapping top surface. We then reduced the dimensionality of both the optical and the electrical problems from 2D down to 1D, watched the runtime and the results change, and brought them back up to 2D again. Finally, we simplified the optical problem in a completely different way, by replacing FDTD with the much faster transfer matrix method.