Phase jumps within polarization monitor


so I am performing parameter sweeps (rough radius & periodicity sweep, see attached project) to correlate the Phase-difference between s- and p-component of transmitted light in dependence of the variation of x/y-Radius of an elliptical Si-posts on SiO2. I thereby get the Phase-difference via the Lumerical Object “Polarization Ellipse” (result “pol”) and Transmission via a regular FD & power monitor.Ellipse at 2.5THz_work-in-progress_phase-discontinuities_support.fsp (3.6 MB)

My issue is, that the results for the phase-difference appear to have “phase jumps” of +/-180deg, see image below, left (x is radius of short post-axis, y is wavelength). The right side shows the Transmission(x is wavelength, y is radius of short post axis).

Looking on the raw data, I found that these “jump-lines” would fit perfectly in the overall trend if they were not shifted by 180deg, and the transmission monitor gives reasonable results.
Furthermore, the “phase-jumps” overlap perfectly with the different handedness, see below.Lumerical%20Phase-discondinuities%20upon%20parameter%20sweeps_handedness_2

Could you please advise how to solve this problem or whether/what I am doing wrong within these simulations?

Thank you very much in advance!
With best regards,

Hey @2425060N,

I will take a look at your sim file, but without completely understanding your analysis it occurs to me that that you might want to use the unwrap command. The phase is returned in the domain of $ [-\pi, \pi] $. Likely you will want to use unwrap on the raw data and then calculate the phase difference. Since you have 2D data I would suggest you look at the final example on the page linked above that describes how to apply unwrap to the columns of a matrix.

I hope this helps let me know if you have any other questions.


Good Morning @trobertson,

thanks a lot for the quick help! So I am trying to implement this unwrap command into the polarization ellipse code, specifically onto the phase_diff parameter in the meantime, but so far without success (I’m quite unexperienced with this). In any case, I suspect the “flickering” of phase/handedness to appear in this portion of code (excerted from polarization ellipse) as I will elaborate below.

# convert spherical coordinates polarization into s,p polarization and select the grating order
# calculate the polarization ellipse. kappa is the resolution
Gs = Gphi(ni,mi);
Gp = Gtheta(ni,mi);	
Gs = real( Gs*exp(1i*kappa) );
Gp = real( Gp*exp(1i*kappa) );

# measure parameters(ratio,major_angle) from the ellipse. normalize Gs and Gp	
diameter   = sqrt( (Gs)^2+(Gp)^2 );
major_axis = max( diameter );		    # for some grating numbers, the major_axis can be 0 
minor_axis = min( diameter );		    # for some grating numbers, the minor_axis can be 0
ratio      = major_axis / minor_axis;       # for some grating numbers, the ratio can be a NAM (0/0)
if (almostequal(ratio,1,0.0001,0.0001)){major_axis_i = find( Gp, max( Gp )); # if ratio ~ 1, then it will have no major axis
}else{ major_axis_i = find( diameter, max(diameter) );}
major_angle  = atan2( Gs( major_axis_i ), Gp( major_axis_i ) )*180/pi;
if (major_angle < -90) { major_angle = major_angle+180; }
if (major_angle > 90)  { major_angle = major_angle-180; }
Gs = Gs/major_axis;
Gp = Gp/major_axis; # normalization

# measure phase difference from the s and p component
phase_diff = (angle(Gtheta(ni,mi))-angle(Gphi(ni,mi)))*180/pi; # phase difference of s and p pol. in degree 
if (Gphi(ni,mi)==0+1i*0) { phase_diff = 0; }    # define linearly pol light
if (Gtheta(ni,mi)==0+1i*0) { phase_diff = 0; }    # define linearly pol light
if (phase_diff > 180) { phase_diff = phase_diff - 180; } # -180< phase_diff <180
if (phase_diff < -180) { phase_diff = phase_diff + 180; }  # -180< phase_diff <180

# measure polarization handedness based on phase_diff
pol_handed = 0; # initiallise an entry
if (phase_diff < 0)   { pol_handed = -1; } # define left-handed
if (phase_diff > 0)   { pol_handed = 1; }  # define right-handed
    ####changed unwrap code
# unwrap over both dimensions 
for (i=1:nx) {
     phase_diff(i,1:ny) = unwrap( pinch(phase_diff,1,i) );
     for (j=1:ny) {
          phase_diff(1:nx,j) = unwrap( pinch(phase_diff,2,j) );
         image(x,y,phase_diff,"x","y","unwrapped phase (rad)"); 
     ####changed unwrap code end

    #end of changed code
# stitch data into the central columns of the final result matrices
# to have all data from different grating orders packaged in a single matrix dataset (as a function of n, m, f)
Gs_all(1:ellipse_res,n1+ni-1,m1+mi-1,fi) = Gs;
Gp_all(1:ellipse_res,n1+ni-1,m1+mi-1,fi) = Gp;
phase_diff_all(n1+ni-1,m1+mi-1,fi) = phase_diff;
pol_handed_all(n1+ni-1,m1+mi-1,fi) = pol_handed;
ratio_all(n1+ni-1,m1+mi-1,fi)	 = ratio;
major_angle_all(n1+ni-1,m1+mi-1,fi)= major_angle;


I feel like pointing out that I do NOT think that the majority of the 180deg phase jumps are “true” results but rather an artifact of the script which flickers between left- and right circular polarized light for different wavelength. The phase jumps seen in the previous message appear to be arbitraty and I can identify (and I also physically expect to see) a “larger” and more continuous 2pi-period when subtracting 180deg from those phase jumps, which is more apparent in the pictures below.Lumerical%20Phase-discondinuities%20sweep

I can even observe this “phase flickering” between LCP and RCP in a single simulation, see below.

And even if I analyse -45deg polarized light in reflection, where the phase-difference is constant at 0.

Any Idea what might be causing this? Maybe because my source is angled at 45 deg, so as soon as I have a Phase-shift, small alterations in x- and y- instensity make the difference between major and minor axis, hence RCP and LCP? What do you think and how would you solve this problem?
Would you advise swithching to a completely switch to a different script, e.g. Phase retardation
the phase.lsf file there?


Hey @2425060N,

Sorry for the delay in getting back to you. I had to dig into the code a little bit to figure out what was going on, but I believe I found a simple fix.

Please do not use unwrap inside the loop of this analysis group. The relevant section, so that you understand what is happening is the code block.

> # measure phase difference from the s and p component
> phase_diff = (angle(Gtheta(ni,mi))-angle(Gphi(ni,mi)))*180/pi; # phase difference of s and p pol. in degree 
> if (Gphi(ni,mi)==0+1i*0) { phase_diff = 0; }    # define linearly pol light
> if (Gtheta(ni,mi)==0+1i*0) { phase_diff = 0; }    # define linearly pol light
> if (phase_diff > 180) { phase_diff = phase_diff - 180; } # -180< phase_diff <180
> if (phase_diff < -180) { phase_diff = phase_diff + 180; }  # -180< phase_diff <180

The variable phase_diff is the difference in degrees of the S, and P polarization. The bottom two lines serve to ensure that the domain of phase diff is limited to [-180,180] and it is responsible for the discontinuities. The unwrap command looks for jumps of $ 2 \pi $, so simply by converting to radians and calling unwrap you should get the results you are looking for. Try the following script commands, and let me know if you have any more issues.


> #Get the results from polarization ellipse analysis group
> POL=getresult("output_polarztn_ellipse","pol");
> #Convert to radian and unwrap
> pd = pinch(POL.phase_diff)*(pi/180);
> pd = unwrap(pd);
> f = POL.f;
> select("- xypol. plane wave");
> theta=get("polarization angle");
> plot(f*1e-12,pd,"frequency [THz]","phase diff [rad]","Phase unwrap pol. angle = " + num2str(theta) + ", freq. reso. = " + num2str(length(f))) ;

I think that you should make sure you have enough frequency points sampled by changing the number of frequency points in the global monitor setting.

Hello Taylor,

thanks a lot, the Script seems to work nicely for the central/main Simulation in Analysis mode.

However, is there also a way to implement it for Parameter/optimization sweeps in the respective Tab? Unfortunately, I am not yet familiar with lumerical scripting and I doubt I can write a whole parameter-sweep_script by myself.


Hey @2425060N,

If you are curious to learn more I would suggest our Scripting 100 course as it would save you time setting-up sweeps and parametrizing your simulation in the future. Also the KB page on the Polarization Ellipse analysis group is short, but helps explain how to set-up the simulation with these monitors.

The simplest way to extract the phase result in a sweep is by changing the model (i.e. root element) analysis script.

  1. Take the script I posted before.
pd = pinch(POL.phase_diffU);
f = POL.f;
phase_diffU = unwrap(pd);
  1. Create result variables that match the name in the script.


  1. These will now be available in sweep results.


The analysis script in model will initialize all analysis groups below, so you may want to disable those groups you are not using to speed up the sweep.


I did some more testing of the polarization_ellipse analysis group, and I found some anomalous behavior of phase_diff. The bottom two lines, I referenced above, which remap phase_diff into the [-180,180] domain seem to cause artifacts in the results when using broadband linearly polarized light. I made some changes in the analysis group, that simply bypass this mapping. It is stored as a new variable I called phase_diffU, in the output monitor only. Take a look at the lines you cited in the output analysis group of the attached file.

PolEllipse_Broadband_PD_unwrapOut.fsp (3.6 MB)