Ansys Learning Forum Forums Discuss Simulation Photonics Regarding box of monitors and far field simulations Reply To: Regarding box of monitors and far field simulations

Amrita Pati
Ansys Employee

Hi Prabha,

I have changed the “scat_ff” analysis group so that it can be used correctly with 5 monitors. I added a parameter called “include_sub” which lets you decide if you want to disable the monitor in the substrate. Also, added some if conditions in the Analysis script so that the if there is no substrate, we can use the symmerty conditions depending upon whether or not required. But if it is include_sub is false, the monitor data from “z1” is completely ignored. Before making these changes, even if you disable the monitor, it would consider symmetry conditions and manipulate the values of z1, to get the values of z2. I can not share the files with you directly as ALF doesn’t permit it. But here are the screenshots and code snippets:

 

  1. First add “scat_ff” from the Object Library (Far field from a closed box).
  2. Change it’s span and position (make it same as the previous farfield group).
  3. Edit it, go to “Setup–>Variables“, add a property called "include_sub" of type Number:

  4. Go to Setup–>Script, replace the existing code by the following:
##############################################
# Far field from closed box
# This script sets up the monitor box
#
# Input properties
# x,y,z span: span of the box of monitors
#
# Tags: far field projection closed box
#
# Copyright 2012 Lumerical Solutions Inc
##############################################
# simplify variable names by removing spaces
x_span = %x span%;
y_span = %y span%;
z_span = %z span%;

select(“z1”);
set(“x”,0);
set(“x span”,x_span);
set(“y”,0);
set(“y span”,y_span);
set(“z”,-z_span/2);
set(“enabled”,include_sub);

select(“z2”);
set(“x”,0);
set(“x span”,x_span);
set(“y”,0);
set(“y span”,y_span);
set(“z”,z_span/2);

select(“x1”);
set(“x”,-x_span/2);
set(“y”,0);
set(“y span”,y_span);
set(“z”,0);
set(“z span”,z_span);

select(“x2”);
set(“x”,x_span/2);
set(“y”,0);
set(“y span”,y_span);
set(“z”,0);
set(“z span”,z_span);

select(“y1”);
set(“x”,0);
set(“x span”,x_span);
set(“y”,-y_span/2);
set(“z”,0);
set(“z span”,z_span);

select(“y2”);
set(“x”,0);
set(“x span”,x_span);
set(“y”,y_span/2);
set(“z”,0);
set(“z span”,z_span);

select(“index”);
set(“x”,x_span/2);
set(“y”,y_span/2);
set(“z”,0);
set(“x span”,0);
set(“y span”,0);
set(“z span”,0);

5. Go to Analysis–>Script, replace the existing code by the following:

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

# Far field from closed box

# This script calculates scattering cross-section and far field projection in half space

#

# Note: The far field projection calculation assumes that all of the monitors

# are in a single homogeneous material (i.e. there is no substrate)

# If a substrate is present, results from this object will be invalid.

# If multiple frequency points are collected, the projection can be slow!! One could reduce the halfspace resolution for faster analysis.

# For more information, see http://docs.lumerical.com/en/layout_analysis_projections_from_monitor.html

#

# symm x,y,z: symmetry boundary conditions

# 0 for no symmetry, 1 for symmetric, -1 for antisymmetric

# Autodetection is managed by examining fields at the symmetry boundary

# For more information, see http://docs.lumerical.com/en/index.html?ref_sim_obj_symmetric_anti-symmetric.html

#

# do halfspace: Calculate the far field in the full half space for all frequencies. This takes longer than the 1D radar line cross sections. 1 for yes, 0 for no

# do polar plot: Calculate the far field scattering angular distribution for a specified target wavelength. 1 for yes, 0 for no

# target wavelength: Desired wavelength for polar plot. The closest wavelength recorded by the monitors will be found and used for the plot.

# halfspace res: Define the resolution of the half space projection. This will significantly affect the time to run the analysis.

# polar plot res: Define the resolution of the polat plots.

#

# Output properties

# XY, YZ, XZ: E, |E|^2, |H|^2 far field profile of scattered field in plane, as a function of frequency

# XY_halfspace: E, |E|^2, |H|^2 in full upper/lower half space,, as a function of frequency. Similar to standard projection from a single monitor

#

# Tags: far field projection closed box

#

# Copyright 2015 Lumerical Solutions Inc

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



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

# automatically unfold field data if symmetry BC is applied

if (havedata(“x1”, “f”)) {

symm_x = 0;

} else {

xtemp = getdata(“y2”, “x”);

ztemp = getdata(“y2”, “z”);

Eztemp = pinch(getdata(“y2”, “Ez”));



Ez2mid = sum(Eztemp(round(length(xtemp)/2), 1:length(ztemp))^2);

if (Ez2mid != 0) {

symm_x = 1;

} else {

symm_x = -1;

}

}



if (havedata(“y1”, “f”)) {

symm_y = 0;

} else {

ytemp = getdata(“x2”, “y”);

ztemp = getdata(“x2”, “z”);

Eztemp = pinch(getdata(“x2”, “Ez”));



Ez2mid = sum(Eztemp(round(length(ytemp)/2), 1:length(ztemp))^2);

if (Ez2mid != 0) {

symm_y = 1;

} else {

symm_y = -1;

}

}

if(include_sub){

if (havedata(“z1”, “f”)) {

symm_z = 0;

} else {

xtemp = getdata(“y2”, “x”);

ztemp = getdata(“y2”, “z”);

Eytemp = pinch(getdata(“y2”, “Ey”));



Ey2mid = sum(Eytemp(1:length(xtemp), round(length(ztemp)/2))^2);

if (Ey2mid != 0) {

symm_z = 1;

} else {

symm_z = -1;

}

}

}

f = getdata(“x2″,”f”); # get freqency data



if (havedata(“index”,”index_x”)) { # get refractive index. Required to calcualte H2 from E2

n_index = getdata(“index”,”index_x”);

} else {

n_index = getdata(“index”,”index_z”);

}

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





# define the angular resolution

phi = linspace(0,360,%polar plot res%); # user-modifiable in the Variables tab

npts = length(phi);



# define the field data matrices for angular distribution

E_xy = matrix(npts, 3, length(f)); # 3 for x, y, z component

E_yz = matrix(npts, 3, length(f)); # 3 for x, y, z component

E_xz = matrix(npts, 3, length(f)); # 3 for x, y, z component

E2_xy = matrix(npts,length(f));

E2_yz = matrix(npts,length(f));

E2_xz = matrix(npts,length(f));

H2_xy = matrix(npts,length(f));

H2_yz = matrix(npts,length(f));

H2_xz = matrix(npts,length(f));





# Identify the closest wavelength to target:

target_wavelength = %target wavelength%;

i_target = find(f,c/target_wavelength);

?”Target wavelength = ” + num2str(target_wavelength);

?”Wavelength used = ” + num2str(c/f(i_target));





if (havedata(“z2″,”Ex”)) { # have z data, 3D simulation



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

# Angular distribution calculation for a 3D simulation begins



for (i = 1:length(f)){ # loop for all frequencies



# print the frequency point number running in the loop

?”Angular distribution i=”+num2str(i)+”, “+num2str(c/f(i)*1e6)+”um”;



n = n_index(i); # select the frequency point for the index



######## x-y plane (phi=0 corresponds to the direction (1,0,0))

?” Projecting in x-y plane”;

x = cos(phi*pi/180); y = sin(phi*pi/180); z = 0;



# Calculate far field by summing contribution from each monitor

temp = farfieldexact(“x2”,x,y,z,i) + farfieldexact(“y2”,x,y,z,i) + farfieldexact(“z2″,x,y,z,i);

if(havedata(“x1″)){

temp = temp – farfieldexact(“x1″,x,y,z,i);

}else{

temp2 = farfieldexact(“x2″,-x,y,z,i);

s = symm_x*[1,-1,-1];

temp2(1:npts,1) = s(1)*temp2(1:npts,1);

temp2(1:npts,2) = s(2)*temp2(1:npts,2);

temp2(1:npts,3) = s(3)*temp2(1:npts,3);

temp = temp – temp2;

}

if(havedata(“y1″)){

temp = temp – farfieldexact(“y1″,x,y,z,i);

}else{

temp2 = farfieldexact(“y2″,x,-y,z,i);

s = symm_y*[-1,1,-1];

temp2(1:npts,1) = s(1)*temp2(1:npts,1);

temp2(1:npts,2) = s(2)*temp2(1:npts,2);

temp2(1:npts,3) = s(3)*temp2(1:npts,3);

temp = temp – temp2;

}

if(include_sub){

if(havedata(“z1″)){

temp = temp – farfieldexact(“z1″,x,y,z,i);

}else{

temp2 = farfieldexact(“z2″,x,y,-z,i);

s = symm_z*[-1,-1,1];

temp2(1:npts,1) = s(1)*temp2(1:npts,1);

temp2(1:npts,2) = s(2)*temp2(1:npts,2);

temp2(1:npts,3) = s(3)*temp2(1:npts,3);

temp = temp – temp2;

}

}

E_xy (1:length(phi), 1:3, i) = temp;

E2_xy (1:length(phi), i) = sum(abs(temp)^2,2); # E2 = |Ex|^2 + |Ey|^2 + |Ez|^2

H2_xy (1:length(phi), i) = E2_xy (1:length(phi), i) * n^2 * eps0/mu0; # for a plane wave, E^2 and H^2 only differ by a factor of n^2*eps0/mu0







######## y-z plane (phi=0 corresponds to the direction (0,1,0))

?” Projecting in y-z plane”;

x = 0; y = cos(phi*pi/180); z = sin(phi*pi/180);



# Calculate far field by summing contribution from each monitor

temp = farfieldexact(“x2”,x,y,z,i) + farfieldexact(“y2”,x,y,z,i) + farfieldexact(“z2″,x,y,z,i);

if(havedata(“x1″)){

temp = temp – farfieldexact(“x1″,x,y,z,i);

}else{

temp2 = farfieldexact(“x2″,-x,y,z,i);

s = symm_x*[1,-1,-1];

temp2(1:npts,1) = s(1)*temp2(1:npts,1);

temp2(1:npts,2) = s(2)*temp2(1:npts,2);

temp2(1:npts,3) = s(3)*temp2(1:npts,3);

temp = temp – temp2;

}

if(havedata(“y1″)){

temp = temp – farfieldexact(“y1″,x,y,z,i);

}else{

temp2 = farfieldexact(“y2″,x,-y,z,i);

s = symm_y*[-1,1,-1];

temp2(1:npts,1) = s(1)*temp2(1:npts,1);

temp2(1:npts,2) = s(2)*temp2(1:npts,2);

temp2(1:npts,3) = s(3)*temp2(1:npts,3);

temp = temp – temp2;

}

if(include_sub){

if(havedata(“z1″)){

temp = temp – farfieldexact(“z1″,x,y,z,i);

}else{

temp2 = farfieldexact(“z2″,x,y,-z,i);

s = symm_z*[-1,-1,1];

temp2(1:npts,1) = s(1)*temp2(1:npts,1);

temp2(1:npts,2) = s(2)*temp2(1:npts,2);

temp2(1:npts,3) = s(3)*temp2(1:npts,3);

temp = temp – temp2;

}

}

E_yz (1:length(phi), 1:3, i) = temp;

E2_yz (1:length(phi), i) = sum(abs(temp)^2,2); # E2 = |Ex|^2 + |Ey|^2 + |Ez|^2

H2_yz (1:length(phi), i) = E2_yz (1:length(phi), i) * n^2 * eps0/mu0; # for a plane wave, E^2 and H^2 only differ by a factor of n^2*eps0/mu0







######### x-z plane (phi=0 corresponds to the direction (1,0,0))

?” Projecting in x-z plane”;

x = cos(phi*pi/180); y = 0; z = sin(phi*pi/180);



# Calculate far field by summing contribution from each monitor

temp = farfieldexact(“x2”,x,y,z,i) + farfieldexact(“y2”,x,y,z,i) + farfieldexact(“z2″,x,y,z,i);

if(havedata(“x1″)){

temp = temp – farfieldexact(“x1″,x,y,z,i);

}else{

temp2 = farfieldexact(“x2″,-x,y,z,i);

s = symm_x*[1,-1,-1];

temp2(1:npts,1) = s(1)*temp2(1:npts,1);

temp2(1:npts,2) = s(2)*temp2(1:npts,2);

temp2(1:npts,3) = s(3)*temp2(1:npts,3);

temp = temp – temp2;

}

if(havedata(“y1″)){

temp = temp – farfieldexact(“y1″,x,y,z,i);

}else{

temp2 = farfieldexact(“y2″,x,-y,z,i);

s = symm_y*[-1,1,-1];

temp2(1:npts,1) = s(1)*temp2(1:npts,1);

temp2(1:npts,2) = s(2)*temp2(1:npts,2);

temp2(1:npts,3) = s(3)*temp2(1:npts,3);

temp = temp – temp2;

}

if(include_sub){

if(havedata(“z1″)){

temp = temp – farfieldexact(“z1″,x,y,z,i);

}else{

temp2 = farfieldexact(“z2″,x,y,-z,i);

s = symm_z*[-1,-1,1];

temp2(1:npts,1) = s(1)*temp2(1:npts,1);

temp2(1:npts,2) = s(2)*temp2(1:npts,2);

temp2(1:npts,3) = s(3)*temp2(1:npts,3);

temp = temp – temp2;

}

}

E_xz (1:length(phi), 1:3, i) = temp;

E2_xz (1:length(phi), i) = sum(abs(temp)^2,2); # E2 = |Ex|^2 + |Ey|^2 + |Ez|^2

H2_xz (1:length(phi), i) = E2_xz (1:length(phi), i) * n^2 * eps0/mu0; # for a plane wave, E^2 and H^2 only differ by a factor of n^2*eps0/mu0



} # end of the angular distribution for loop



if (%do polar plot%) { # polar plot for target wavelength

polar(phi*pi/180, E2_xy(1:length(phi), i_target), E2_yz(1:length(phi), i_target), E2_xz(1:length(phi), i_target),

”angle (degrees)”, “|E|^2”, “|E|^2 vs angle @ “+num2str(c/f(i_target)*1e6)+”um”);

legend(“xy plane”,”yz plane”,”xz plane”);

} # end of if polar plot



# create datasets for XY, YZ, XZ for angular distribution

XY = matrixdataset(“XY”);

XY.addparameter(“phi”,phi*pi/180.); #phi angle in radians

XY.addparameter(“lambda”,c/f,”f”,f);

XY.addattribute(“E”,pinch(E_xy,2,1),pinch(E_xy,2,2),pinch(E_xy,2,3)); # Ex, Ey, Ez

XY.addattribute(“E2″,E2_xy);

XY.addattribute(“H2″,H2_xy);



YZ = matrixdataset(“YZ”);

YZ.addparameter(“phi”,phi*pi/180.); #phi angle in radians

YZ.addparameter(“lambda”,c/f,”f”,f);

YZ.addattribute(“E”,pinch(E_yz,2,1),pinch(E_yz,2,2),pinch(E_yz,2,3)); # Ex, Ey, Ez

YZ.addattribute(“E2″,E2_yz);

YZ.addattribute(“H2″,H2_yz);



XZ = matrixdataset(“XZ”);

XZ.addparameter(“phi”,phi*pi/180.); #phi angle in radians

XZ.addparameter(“lambda”,c/f,”f”,f);

XZ.addattribute(“E”,pinch(E_xz,2,1),pinch(E_xz,2,2),pinch(E_xz,2,3)); # Ex, Ey, Ez

XZ.addattribute(“E2″,E2_xz);

XZ.addattribute(“H2″,H2_xz);

# end of the angular distribution for a 3D simulation

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



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

# Halfspace calculation for a 3D simulation begins



# calculate the far field in XY upper/lower half space

if (%do halfspace%) {



res = %halfspace res%; # projection resolution, user-modifiable in the Variables tab

u1 = linspace(-1,1,res);

u2 = u1;

X = meshgridx(u1,u2); # These three lines define the orientation of the hemisphere (ie. XY based halfspace)

Y = meshgridy(u1,u2);

Z = sqrt(1-X^2-Y^2);

filter = abs(imag(Z))<=0; # filter out any values outside of hemisphere

filter2=matrix(res,res,length(f)); # same as filter, just for all frequencies

filter3=matrix(res,res,3,length(f)); # same as filter2, just for all frequencies, Ex, Ey, Ez

for (j=1:length(f)){ # just for filter2 and fitler3 for all frequencies

filter2(1:res,1:res,j)=filter;

filter3(1:res,1:res,1,j)=filter; filter3(1:res,1:res,2,j)=filter; filter3(1:res,1:res,3,j)=filter;

}

x = reshape(X,[res^2,1]); # reshape coordinate matrix into a vector. This is the required form for farfieldexact.

y = reshape(Y,[res^2,1]);

z = reshape(Z,[res^2,1]);

x = [x,x]; # Concatenate a 2nd copy of the vector, for the lower half space

y = [y,y];

z = [z,-z];

npts = length(z); # size of position vector



# define halfspace dataset

E_XY_halfspace = matrix (2*res^2,3,length(f));

E2_XY_halfspace = matrix (2*res^2,length(f));

H2_XY_halfspace = matrix (2*res^2,length(f));





for (i = 1 : length(f)) { # loop for all frequency points



?”Projecting in XY upper half space, i=” + num2str(i)+”, “+num2str(c/f(i)*1e6)+”um”;

# Calculate far field by summing contribution from each monitor

temp = farfieldexact(“x2”,x,y,z,i) + farfieldexact(“y2”,x,y,z,i) + farfieldexact(“z2″,x,y,z,i);

if(havedata(“x1″)){

temp = temp – farfieldexact(“x1″,x,y,z,i);

}else{

temp2 = farfieldexact(“x2″,-x,y,z,i);

s = symm_x*[1,-1,-1];

temp2(1:npts,1) = s(1)*temp2(1:npts,1);

temp2(1:npts,2) = s(2)*temp2(1:npts,2);

temp2(1:npts,3) = s(3)*temp2(1:npts,3);

temp = temp – temp2;

}

if(havedata(“y1″)){

temp = temp – farfieldexact(“y1″,x,y,z,i);

}else{

temp2 = farfieldexact(“y2″,x,-y,z,i);

s = symm_y*[-1,1,-1];

temp2(1:npts,1) = s(1)*temp2(1:npts,1);

temp2(1:npts,2) = s(2)*temp2(1:npts,2);

temp2(1:npts,3) = s(3)*temp2(1:npts,3);

temp = temp – temp2;

}

if(include_sub){

if(havedata(“z1″)){

temp = temp – farfieldexact(“z1″,x,y,z,i);

}else{

temp2 = farfieldexact(“z2″,x,y,-z,i);

s = symm_z*[-1,-1,1];

temp2(1:npts,1) = s(1)*temp2(1:npts,1);

temp2(1:npts,2) = s(2)*temp2(1:npts,2);

temp2(1:npts,3) = s(3)*temp2(1:npts,3);

temp = temp – temp2;

}

}



E_XY_halfspace (1:2*res^2,1:3,i) = temp;

E2_XY_halfspace (1:2*res^2,i)= sum(abs(temp)^2,2); # E2 = |Ex|^2 + |Ey|^2 + |Ez|^2

} # end of halfspace for loop



E_XY_upper_halfspace = E_XY_halfspace(1:res^2,1:3,1:length(f)); # separate the upper/lower data

E_XY_lower_halfspace = E_XY_halfspace((res^2+1):(2*res^2),1:3,1:length(f));

E_XY_upper_halfspace = reshape(E_XY_upper_halfspace,[res,res,3,length(f)]); # reshape the data back into a 2D matrix

E_XY_lower_halfspace = reshape(E_XY_lower_halfspace,[res,res,3,length(f)]);

E_XY_upper_halfspace = E_XY_upper_halfspace*filter3; # set all values outside of hemisphere (ie. the corners of the matrices) to zero

E_XY_lower_halfspace = E_XY_lower_halfspace*filter3;



E2_XY_upper_halfspace = E2_XY_halfspace(1:res^2,1:length(f)); # separate the upper/lower data

E2_XY_lower_halfspace = E2_XY_halfspace((res^2+1):(2*res^2),1:length(f));

E2_XY_upper_halfspace = reshape(E2_XY_upper_halfspace,[res,res,length(f)]); # reshape the data back into a 2D matrix

E2_XY_lower_halfspace = reshape(E2_XY_lower_halfspace,[res,res,length(f)]);

E2_XY_upper_halfspace = E2_XY_upper_halfspace*filter2; # set all values outside of hemisphere (ie. the corners of the matrices) to zero

E2_XY_lower_halfspace = E2_XY_lower_halfspace*filter2;



# create halfspace dataset

XY_halfspace = matrixdataset(“XY_halfspace”);

XY_halfspace.addparameter(“ux”,u1);

XY_halfspace.addparameter(“uy”,u2);

XY_halfspace.addparameter(“lambda”,c/f,”f”,f);

XY_halfspace.addattribute(“E_upper”,pinch(E_XY_upper_halfspace,3,1),pinch(E_XY_upper_halfspace,3,2),pinch(E_XY_upper_halfspace,3,3));

XY_halfspace.addattribute(“E_lower”,pinch(E_XY_lower_halfspace,3,1),pinch(E_XY_lower_halfspace,3,2),pinch(E_XY_lower_halfspace,3,3));

XY_halfspace.addattribute(“E2_upper”,E2_XY_upper_halfspace);

XY_halfspace.addattribute(“E2_lower”,E2_XY_lower_halfspace);

XY_halfspace.addattribute(“H2_upper”,E2_XY_upper_halfspace * n^2*eps0/mu0);

XY_halfspace.addattribute(“H2_lower”,E2_XY_lower_halfspace * n^2*eps0/mu0);

}

# end of the halfspace calculation for a 3D simulation

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



# end of 3D



} else {

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

# Angular distribution for a 2D simulation, only for the XY plane
for (i = 1 : length(f)) { # for all frequency points
n = n_index(i); # select the frequency point for the index

# x-y plane (phi=0 corresponds to the direction (0,1,0))
?” Projecting in x-y plane. 2D simulation.”;

x = -sin(phi*pi/180);
y = cos(phi*pi/180);
z = 0;

temp = farfieldexact(“x2”,x,y,i) + farfieldexact(“y2″,x,y,i);
if(havedata(“x1″)){
temp = temp – farfieldexact(“x1″,x,y,i);
}else{
temp2 = farfieldexact(“x2″,-x,y,i);
s = symm_x*[1,-1,-1];
temp2(1:length(phi),1) = s(1)*temp2(1:length(phi),1);
temp2(1:length(phi),2) = s(2)*temp2(1:length(phi),2);
temp2(1:length(phi),3) = s(3)*temp2(1:length(phi),3);
temp = temp – temp2;
}
if(havedata(“y1″)){
temp = temp – farfieldexact(“y1″,x,y,i);
}else{
temp2 = farfieldexact(“y2″,x,-y,i);
s = symm_y*[-1,1,-1];
temp2(1:length(phi),1) = s(1)*temp2(1:length(phi),1);
temp2(1:length(phi),2) = s(2)*temp2(1:length(phi),2);
temp2(1:length(phi),3) = s(3)*temp2(1:length(phi),3);
temp = temp – temp2;
}

E_xy (1:length(phi), 1:3, i) = temp;
E2_xy (1:length(phi), i) = sum(abs(temp)^2,2); # E2 = |Ex|^2 + |Ey|^2 + |Ez|^2
H2_xy (1:length(phi), i) = E2_xy (1:length(phi), i) * n^2 * eps0/mu0; # for a plane wave, E^2 and H^2 only differ by a factor of n^2*eps0/mu0

} # end of for loop 2D

if (%do polar plot%) { # polar plot for target wavelength
polar(phi*pi/180, E2_xy(1:length(phi), i_target), “angle (degrees)”, “|E|^2”, “|E|^2 vs angle @ “+num2str(c/f(i_target)*1e6)+”um”);
legend(“xy plane”);
} # end of if polar plot

# create dataset for XY
XY = matrixdataset(“XY”);
XY.addparameter(“phi”,phi*pi/180.); #phi angle in radians
XY.addparameter(“lambda”,c/f,”f”,f);
XY.addattribute(“E”,pinch(E_xy,2,1),pinch(E_xy,2,2),pinch(E_xy,2,3)); # Ex, Ey, Ez
XY.addattribute(“E2″,E2_xy);
XY.addattribute(“H2″,H2_xy);
} # end of angular distribution for 2D simulation
########################################

6. Contrary to one of the points I previously made, you can perform a broadband simulation and perform the farfield projection over a single target wavelength:

Feel free to let me know if you have any questions.

Regards,
Amrita