Ansys Assistant will be unavailable on the Learning Forum starting January 30. An upgraded version is coming soon. We apologize for any inconvenience and appreciate your patience. Stay tuned for updates.
Photonics

Photonics

Topics related to Lumerical and more.

Negative Reflectance and Transmittance in 2D FDTD simulation of Ag Nanoparticle

TAGGED: 

    • raano1
      Subscriber

      Hello,

      I am simulating the effect of Ag nanoparticles (NPs) on light absorption in a Si solar cell structure using 2D FDTD in Lumerical. I am running two simulations — one reference (no NPs) and one with 12 Ag NPs of mixed diameters (100–400 nm) sitting on top of a SiO2/Si stack — and comparing the results.

      My structure (bottom to top):

      • Si layer: 8 µm
      • SiO2 layer: 300 nm
      • Ag NPs sitting on SiO2 surface (diameters: 100, 200, 300, 400 nm mixed)
      • Air: 4 µm

      My simulation settings:

      • 2D FDTD
      • Plane wave source, injection axis: y, direction: Backward (downward)
      • Source position: Air_y_max - 200e-9 (near top of Air)
      • Reflection monitor: Air_y_max - 300e-9 (just below source)
      • Transmission monitor: Si_y_max - 1e-6 (1 µm inside Si from top)
      • Boundary conditions: PML on all 4 sides
      • Wavelength: 200–1000 nm
      • Simulation time: 10000e-15 s
      • Auto shutoff min: 1e-5
      • Mesh accuracy: 2
      • Material: Ag (Johnson and Christy), Si (Palik), SiO2 (Palik)

      Post-processing:

       
       
      `T = transmission("transmission");
      R = transmission("reflection");
      A = 1 - T - R;`

      Problem I am getting:

      • Transmittance is negative (down to -0.55)
      • Reflectance is negative (down to -0.9)
      • Absorption (1-T-R) is greater than 1 (up to 2.5)
      • T+R+A is not equal to 1 — it oscillates wildly

      My questions:

      1. What is the correct sign convention for transmission() function when using a Backward directed plane wave source? Should I use -transmission("transmission") or transmission("transmission")?
      2. Is my reflection monitor placement correct — just below the source? Or should it be above the source?
      3. Is my transmission monitor placement correct — 1 µm inside Si from the top? Or should it be near the bottom of Si?
      4. Should I use Periodic boundary conditions on x instead of PML for a plane wave source?
      5. Is auto shutoff min = 1e-5 sufficient for plasmonic Ag NP simulations or should it be tighter (1e-7)?

      Any guidance would be very helpful. Thank you

    • raano1
      Subscriber

      Hello,

      I am simulating the effect of Ag nanoparticles (NPs) on light absorption in a Si solar cell structure using 2D FDTD in Lumerical. I am running two simulations — one reference (no NPs) and one with 12 Ag NPs of mixed diameters (100–400 nm) sitting on top of a SiO2/Si stack — and comparing the results.

      My structure (bottom to top):

      • Si layer: 8 µm
      • SiO2 layer: 300 nm
      • Ag NPs sitting on SiO2 surface (diameters: 100, 200, 300, 400 nm mixed)
      • Air: 4 µm

      My simulation settings:

      • 2D FDTD
      • Plane wave source, injection axis: y, direction: Backward (downward)
      • Source position: Air_y_max - 200e-9 (near top of Air)
      • Reflection monitor: Air_y_max - 300e-9 (just below source)
      • Transmission monitor: Si_y_max - 1e-6 (1 µm inside Si from top)
      • Boundary conditions: PML on all 4 sides
      • Wavelength: 200–1000 nm
      • Simulation time: 10000e-15 s
      • Auto shutoff min: 1e-5
      • Mesh accuracy: 2
      • Material: Ag (Johnson and Christy), Si (Palik), SiO2 (Palik)

      Post-processing:

       
       
      `T = transmission("transmission");
      R = transmission("reflection");
      A = 1 - T - R;`

      Problem I am getting:

      • Transmittance is negative (down to -0.55)
      • Reflectance is negative (down to -0.9)
      • Absorption (1-T-R) is greater than 1 (up to 2.5)
      • T+R+A is not equal to 1 — it oscillates wildly

      My questions:

      1. What is the correct sign convention for transmission() function when using a Backward directed plane wave source? Should I use -transmission("transmission") or transmission("transmission")?
      2. Is my reflection monitor placement correct — just below the source? Or should it be above the source?
      3. Is my transmission monitor placement correct — 1 µm inside Si from the top? Or should it be near the bottom of Si?
      4. Should I use Periodic boundary conditions on x instead of PML for a plane wave source?
      5. Is auto shutoff min = 1e-5 sufficient for plasmonic Ag NP simulations or should it be tighter (1e-7)?

      Any guidance would be very helpful. Thank you

      And here is my code 

      clear;

      ####################################################
      # COMBINED SCRIPT: Reference + AgNP in ONE code
      # Run 1: Air + SiO2 + Si (no NPs)
      # Run 2: Air + Ag NPs + SiO2 + Si
      ####################################################

      # Layer thicknesses
      Si_thickness = 8e-6;
      SiO2_thickness = 300e-9;
      Air_thickness = 4e-6;

      # Wavelength
      lambda_min = 200e-9;
      lambda_max = 1000e-9;

      # Mesh
      mesh_accuracy = 2;
      sim_time = 10000e-15;

      # Cell size
      cell_x = 6e-6;

      # NP parameters
      edge_gap = 100e-9;

      # NP radii in random order (12 NPs)
      np_r1  = 50e-9;
      np_r2  = 100e-9;
      np_r3  = 200e-9;
      np_r4  = 50e-9;
      np_r5  = 150e-9;
      np_r6  = 100e-9;
      np_r7  = 50e-9;
      np_r8  = 200e-9;
      np_r9  = 150e-9;
      np_r10 = 100e-9;
      np_r11 = 50e-9;
      np_r12 = 150e-9;

      # NP x positions
      x1 = 0;
      x2  = x1  + np_r1  + edge_gap + np_r2;
      x3  = x2  + np_r2  + edge_gap + np_r3;
      x4  = x3  + np_r3  + edge_gap + np_r4;
      x5  = x4  + np_r4  + edge_gap + np_r5;
      x6  = x5  + np_r5  + edge_gap + np_r6;
      x7  = x6  + np_r6  + edge_gap + np_r7;
      x8  = x7  + np_r7  + edge_gap + np_r8;
      x9  = x8  + np_r8  + edge_gap + np_r9;
      x10 = x9  + np_r9  + edge_gap + np_r10;
      x11 = x10 + np_r10 + edge_gap + np_r11;
      x12 = x11 + np_r11 + edge_gap + np_r12;

      x_cen = (x1 + x12) / 2;
      x1=x1-x_cen;  x2=x2-x_cen;  x3=x3-x_cen;  x4=x4-x_cen;
      x5=x5-x_cen;  x6=x6-x_cen;  x7=x7-x_cen;  x8=x8-x_cen;
      x9=x9-x_cen;  x10=x10-x_cen; x11=x11-x_cen; x12=x12-x_cen;

      # Y positions
      Si_y_min = 0;
      Si_y_max = Si_thickness;
      SiO2_y_min = Si_y_max;
      SiO2_y_max = SiO2_y_min + SiO2_thickness;
      Air_y_min = SiO2_y_max;
      Air_y_max = SiO2_y_max + Air_thickness;

      r_max = 200e-9;
      margin_y = 500e-9;
      sim_y_min = Si_y_min – margin_y;
      sim_y_max = Air_y_max + margin_y;
      sim_y_center = (sim_y_min + sim_y_max) / 2;
      sim_y_span = sim_y_max – sim_y_min;

      source_y = Air_y_max – 200e-9;
      refl_y   = Air_y_max – 300e-9;
      trans_y  = Si_y_max  – 1e-6;

      ####################################################
      # LOOP: sim=1 (reference), sim=2 (with NPs)
      ####################################################

      for (sim = 1:2) {

          newproject;

          ############################################
          # STRUCTURES (common)
          ############################################

          addrect;
          set(“name”, “Si_film”);
          set(“material”, “Si (Silicon) – Palik”);
          set(“x”, 0);
          set(“x span”, cell_x);
          set(“y min”, Si_y_min);
          set(“y max”, Si_y_max);

          addrect;
          set(“name”, “SiO2_layer”);
          set(“material”, “SiO2 (Glass) – Palik”);
          set(“x”, 0);
          set(“x span”, cell_x);
          set(“y min”, SiO2_y_min);
          set(“y max”, SiO2_y_max);

          ############################################
          # ADD NPs ONLY FOR sim=2
          ############################################

          if (sim == 2) {
              addcircle;
              set(“name”, “Ag_NP_01_d100”); set(“material”, “Ag (Silver) – Johnson and Christy”);
              set(“x”, x1); set(“y”, SiO2_y_max + np_r1); set(“radius”, np_r1);

              addcircle;
              set(“name”, “Ag_NP_02_d200”); set(“material”, “Ag (Silver) – Johnson and Christy”);
              set(“x”, x2); set(“y”, SiO2_y_max + np_r2); set(“radius”, np_r2);

              addcircle;
              set(“name”, “Ag_NP_03_d400”); set(“material”, “Ag (Silver) – Johnson and Christy”);
              set(“x”, x3); set(“y”, SiO2_y_max + np_r3); set(“radius”, np_r3);

              addcircle;
              set(“name”, “Ag_NP_04_d100”); set(“material”, “Ag (Silver) – Johnson and Christy”);
              set(“x”, x4); set(“y”, SiO2_y_max + np_r4); set(“radius”, np_r4);

              addcircle;
              set(“name”, “Ag_NP_05_d300”); set(“material”, “Ag (Silver) – Johnson and Christy”);
              set(“x”, x5); set(“y”, SiO2_y_max + np_r5); set(“radius”, np_r5);

              addcircle;
              set(“name”, “Ag_NP_06_d200”); set(“material”, “Ag (Silver) – Johnson and Christy”);
              set(“x”, x6); set(“y”, SiO2_y_max + np_r6); set(“radius”, np_r6);

              addcircle;
              set(“name”, “Ag_NP_07_d100”); set(“material”, “Ag (Silver) – Johnson and Christy”);
              set(“x”, x7); set(“y”, SiO2_y_max + np_r7); set(“radius”, np_r7);

              addcircle;
              set(“name”, “Ag_NP_08_d400”); set(“material”, “Ag (Silver) – Johnson and Christy”);
              set(“x”, x8); set(“y”, SiO2_y_max + np_r8); set(“radius”, np_r8);

              addcircle;
              set(“name”, “Ag_NP_09_d300”); set(“material”, “Ag (Silver) – Johnson and Christy”);
              set(“x”, x9); set(“y”, SiO2_y_max + np_r9); set(“radius”, np_r9);

              addcircle;
              set(“name”, “Ag_NP_10_d200”); set(“material”, “Ag (Silver) – Johnson and Christy”);
              set(“x”, x10); set(“y”, SiO2_y_max + np_r10); set(“radius”, np_r10);

              addcircle;
              set(“name”, “Ag_NP_11_d100”); set(“material”, “Ag (Silver) – Johnson and Christy”);
              set(“x”, x11); set(“y”, SiO2_y_max + np_r11); set(“radius”, np_r11);

              addcircle;
              set(“name”, “Ag_NP_12_d300”); set(“material”, “Ag (Silver) – Johnson and Christy”);
              set(“x”, x12); set(“y”, SiO2_y_max + np_r12); set(“radius”, np_r12);
          }

          ############################################
          # FDTD (2D)
          ############################################

          addfdtd;
          set(“dimension”, “2D”);
          set(“x”, 0);
          set(“x span”, cell_x);
          set(“y”, sim_y_center);
          set(“y span”, sim_y_span);
          set(“x min bc”, “PML”);
          set(“x max bc”, “PML”);
          set(“y min bc”, “PML”);
          set(“y max bc”, “PML”);
          set(“mesh accuracy”, mesh_accuracy);
          set(“simulation time”, sim_time);
          set(“auto shutoff min”, 1e-5);

          ############################################
          # SOURCE
          ############################################

          addplane;
          set(“name”, “source”);
          set(“injection axis”, “y-axis”);
          set(“direction”, “Backward”);
          set(“x”, 0);
          set(“x span”, cell_x);
          set(“y”, source_y);
          set(“wavelength start”, lambda_min);
          set(“wavelength stop”, lambda_max);

          ############################################
          # MONITORS
          ############################################

          addpower;
          set(“name”, “reflection”);
          set(“monitor type”, “Linear X”);
          set(“override global monitor settings”, 1);
          set(“use source limits”, 1);
          set(“frequency points”, 100);
          set(“x”, 0);
          set(“x span”, cell_x);
          set(“y”, refl_y);

          addpower;
          set(“name”, “transmission”);
          set(“monitor type”, “Linear X”);
          set(“override global monitor settings”, 1);
          set(“use source limits”, 1);
          set(“frequency points”, 100);
          set(“x”, 0);
          set(“x span”, cell_x);
          set(“y”, trans_y);

          addprofile;
          set(“name”, “field_xy”);
          set(“override global monitor settings”, 1);
          set(“use source limits”, 1);
          set(“frequency points”, 10);
          set(“x”, 0);
          set(“x span”, cell_x);
          set(“y”, sim_y_center);
          set(“y span”, sim_y_span – 100e-9);

          ############################################
          # MESH OVERRIDE
          ############################################

          if (sim == 2) {
              addmesh;
              set(“name”, “mesh_NPs”);
              set(“x”, 0);
              set(“x span”, cell_x);
              set(“y”, SiO2_y_max + r_max);
              set(“y span”, 2*r_max + 40e-9);
              set(“dx”, 10e-9);
              set(“dy”, 10e-9);
          }

          addmesh;
          set(“name”, “mesh_SiO2”);
          set(“x”, 0);
          set(“x span”, cell_x);
          set(“y”, SiO2_y_min + SiO2_thickness/2);
          set(“y span”, SiO2_thickness + 40e-9);
          set(“dy”, 10e-9);

          ############################################
          # SAVE AND RUN
          ############################################

          if (sim == 1) {
              save(“Combined_Reference.fsp”);
              ?””;
              ?”=== RUNNING SIMULATION 1: REFERENCE (no NPs) ===”;
          } else {
              save(“Combined_WithAgNP.fsp”);
              ?””;
              ?”=== RUNNING SIMULATION 2: WITH 12 Ag NPs ===”;
          }

          run;

      }

      ?””;
      ?”=== BOTH SIMULATIONS COMPLETE ===”;
      ?”Open Combined_Reference.fsp and Combined_WithAgNP.fsp to view results.”;


      also result post processing code 

      clear;

      ####################################################
      # POST-PROCESSING SCRIPT
      # Load Reference and AgNP simulation results
      # Compute T, R, A and plot comparisons
      ####################################################

      ?”=== LOADING REFERENCE SIMULATION ===”;
      load(“Combined_Reference.fsp”);
      run;

      f     = getdata(“transmission”, “f”);
      lam   = c / f;

      T_ref = transmission(“transmission”);
      R_ref = transmission(“reflection”);
      A_ref = 1 – T_ref – R_ref;

      ?”Reference loaded. T, R, A extracted.”;

      ####################################################

      ?”=== LOADING AgNP SIMULATION ===”;
      load(“Combined_WithAgNP.fsp”);
      run;

      T_np  = transmission(“transmission”);
      R_np  = transmission(“reflection”);
      A_np  = 1 – T_np – R_np;

      ?”AgNP loaded. T, R, A extracted.”;

      ####################################################
      # COMPARISON PLOTS
      ####################################################

      ?””;
      ?”=== GENERATING COMPARISON PLOTS ===”;

      # — Transmittance Comparison —
      plot(lam*1e9, T_ref, T_np, “Wavelength (nm)”, “Transmittance”, “Transmittance Comparison”);
      legend(“Reference (no NPs)”, “With Ag NPs”);
      exportfigure(“Compare_Transmittance.png”, 800, 600);

      # — Reflectance Comparison —
      plot(lam*1e9, R_ref, R_np, “Wavelength (nm)”, “Reflectance”, “Reflectance Comparison”);
      legend(“Reference (no NPs)”, “With Ag NPs”);
      exportfigure(“Compare_Reflectance.png”, 800, 600);

      # — Absorption Comparison —
      plot(lam*1e9, A_ref, A_np, “Wavelength (nm)”, “Absorption (1-T-R)”, “Absorption Comparison”);
      legend(“Reference (no NPs)”, “With Ag NPs”);
      exportfigure(“Compare_Absorption.png”, 800, 600);

      # — T+R+A = 1 Check (should be flat line at 1) —
      plot(lam*1e9, T_ref+R_ref+A_ref, T_np+R_np+A_np, “Wavelength (nm)”, “T+R+A”, “Energy Conservation Check”);
      legend(“Reference”, “With Ag NPs”);
      exportfigure(“EnergyConservation_Check.png”, 800, 600);

      # — Transmittance Enhancement (T_NP / T_ref) —
      T_Enhancement = T_np / T_ref;
      plot(lam*1e9, T_Enhancement, “Wavelength (nm)”, “T_NP / T_ref”, “Transmittance Enhancement”);
      exportfigure(“Transmittance_Enhancement.png”, 800, 600);

      # — Absorption Enhancement (A_NP / A_ref) —
      A_Enhancement = A_np / A_ref;
      plot(lam*1e9, A_Enhancement, “Wavelength (nm)”, “A_NP / A_ref”, “Absorption Enhancement”);
      exportfigure(“Absorption_Enhancement.png”, 800, 600);

      # — Absorption Difference (Delta A) —
      Delta_A = A_np – A_ref;
      plot(lam*1e9, Delta_A, “Wavelength (nm)”, “Delta A = A_NP – A_ref”, “Absorption Increase due to Ag NPs”);
      exportfigure(“Absorption_Difference.png”, 800, 600);

      # — Complete Comparison (T, R, A together) —
      plot(lam*1e9, T_ref, T_np, R_ref, R_np, A_ref, A_np, “Wavelength (nm)”, “Value”, “Complete T R A Comparison”);
      legend(“T (ref)”, “T (NP)”, “R (ref)”, “R (NP)”, “A (ref)”, “A (NP)”);
      exportfigure(“Complete_Comparison.png”, 800, 600);

      ####################################################
      # RESULTS SUMMARY
      ####################################################

      ?””;
      ?”=== RESULTS SUMMARY ===”;
      ?””;
      ?”— Transmittance —“;
      ?”Avg T (ref)        : ” + num2str(mean(T_ref));
      ?”Avg T (NP)         : ” + num2str(mean(T_np));
      ?”Avg T Enhancement  : ” + num2str(mean(T_Enhancement));
      ?”Max T Enhancement  : ” + num2str(max(T_Enhancement));
      ?”Min T Enhancement  : ” + num2str(min(T_Enhancement));
      ?””;
      ?”— Reflectance —“;
      ?”Avg R (ref)        : ” + num2str(mean(R_ref));
      ?”Avg R (NP)         : ” + num2str(mean(R_np));
      ?””;
      ?”— Absorption (1-T-R) —“;
      ?”Avg A (ref)        : ” + num2str(mean(A_ref));
      ?”Avg A (NP)         : ” + num2str(mean(A_np));
      ?”Avg A Enhancement  : ” + num2str(mean(A_Enhancement));
      ?”Max A Enhancement  : ” + num2str(max(A_Enhancement));
      ?”Avg Delta A        : ” + num2str(mean(Delta_A));
      ?”Max Delta A        : ” + num2str(max(Delta_A));
      ?””;
      ?”=== ALL DONE! 8 plots saved ===”;




       

    • Kirill
      Forum Moderator

      Hello @raano1,

      Thank for the detailed explanation.

      1. Negative values indicate that the power is flowing in the negative direction of the axis (see the transmission - Script command). Please adjust the sign based on the expected direction of the flux.

      2. The DFT monitor captures all fields, and when placed below the source, it will also record the source field. There are ways to address this, but placing the monitor above the source is often a simpler and cleaner approach. Please also keep in mind that the PML boundaries will absorb energy.

      3. There is no single correct answer here; it depends on where you want to measure the transmission. As the field propagates deeper into the film, it may be absorbed by the material itself as well as by the PML boundaries.

      4. Again, this depends on what you want to achieve. If your structure assumes periodicity, consider using Periodic or Bloch Boundary Conditions. See, for example, Periodic boundary conditions in FDTD and MODE.

      5. 1e-05 is the default autoshutoff value and may provide sufficient accuracy without requiring the simulation to run for the full simulation time, if it converges early. The key point is whether the simulation converges.

      Please check the FDTD simulation status:
      0 – simulation in layout mode
      1 – ran to full simulation time
      2 – ran to autoshutoff
      3 – diverged

      see FDTD solver - Simulation Object.

      Ideally, you want to see a status of 2. For resonant or layered structures, convergence may require longer simulation times, improved material fits, finer mesh, etc., see Convergence testing process for FDTD simulations. You can also use a time monitor or movie monitor to verify that the fields have completely decayed by the end of the simulation; otherwise, the frequency-domain results may not be reliable.

      Best regards,
      Kirill

Viewing 2 reply threads
  • You must be logged in to reply to this topic.
[bingo_chatbox]