Files
mxpic_simu/simulation/Lumerical/mx_analysis_lib.lsf
T
2026-06-08 15:46:41 +08:00

213 lines
6.1 KiB
Plaintext

function mx_sweep(sweeps,run_on){
#addsweep(0);
## NOTICE : this can only be used in one-dimentional result calculation
## NOTICE : such as [T .vs. lambda]
#### @ sweeps: struct ####
#### @ sweeps: [var_names={'width','radius','wavelength'...}]
#### @ sweeps: width = [w1:dw:w2]
#### @ radius = [r1:dr:r2]
addsweep(0);
sweep_name = 'mx_sweep';
deletesweep(sweep_name);
setsweep("sweep", "name", sweep_name);
setsweep(sweep_name,"type","Ranges");
ins_temp = 'var_temp = sweeps.' + sweeps.var_names{1} + ';';
eval(ins_temp);
setsweep(sweep_name,"number of points",length(var_temp));
result_data = zeros(length(var_temp),length(sweeps.result_names));
for (idx_vars=1;idx_vars<=length(sweeps.var_names);idx_vars=idx_vars+1){
para = struct;
para.Name = sweeps.var_names{idx_vars};
para.Type = sweeps.var_types{idx_vars};
para.Parameter = sweeps.var_select{idx_vars};
ins_temp = 'var_temp = sweeps.' + sweeps.var_names{idx_vars} + ';';
eval(ins_temp);
para.Start = var_temp(1);
para.Stop = var_temp(end);
addsweepparameter(sweep_name, para);
}
for (idx_rsult=1;idx_rsult<=length(sweeps.result_names);idx_rsult=idx_rsult+1){
result = struct;
result.Name = sweeps.result_names{idx_rsult};
result.Result = sweeps.result_select{idx_rsult};
addsweepresult(sweep_name, result);
}
if (run_on) {
runsweep;
for (idx_result=1;idx_result<=length(sweeps.result_names);idx_result=idx_result+1){
result_data(:,idx_result) = getsweepdata(sweep_name,sweeps.result_names{idx_result});
}
}
################################### RESULT ##################################################
sweep_cur = sweeps;
sweep_cur.result = result_data;
return sweep_cur;
}
##### FWM analysis lib #####
##### FWM calculation pack #####
##### @ freq_pump : pumping frequency, vector of 1*2
##### @ freq_signal: signal frequency, single scalar
##### @ mode_idx : vector of 1*4, [p,p,l,s] denoted
##### @ mode_pol : vector of 1*4, [p,p,l,s] denoted
##### @ wg: struct of {width, bend radius}
##### @ ONLY operates in FDE !!!! #####
function mx_FWM_analysis(freq_pump,freq_signal,mode_idx,mode_pol,wg_bend){
##### Select the target modes #####
freq_idler = freq_pump(1) + freq_pump(2) - freq_signal;
freq_range = [freq_pump,freq_signal,freq_idler];
mode_neff = zeros(1,4);
for (idx_mode=1;idx_mode<=4;idx_mode=idx_mode+1){
temp = mx_get_mode_data(c/freq_range(idx_mode),mode_pol{idx_mode},mode_idx(idx_mode),wg_bend,{'neff'});
mode_neff(idx_mode) = temp.neff;
}
wavelengths = c/freq_range;
wl_neff = wavelengths/mode_neff;
k_vector = 2*pi/wl_neff;
phase_mismatch = sum(k_vector*[1,1,-1,-1]);
return phase_mismatch;
}
##### Phase Matched Coupler calculation pack #####
##### NOTICE : this is coupled by TE0/TM0 by default #####
function mx_DC_analysis(wafer,width_seed,wl,gap,neff,bend,outer_side,mode_idx,mode_pol){
cur_file_name = currentfilename;
#load('Temp_workspace.lms');
switchtolayout;
#deleteall;
cladding = wafer.cladding;
max_itn = 5;
mesh_grids = [20,20,20]*1e-9;
##### Adding two waveguides to the strcuture #####
#mx_FDE_strip(wafer,width_seed);
#mx_simu_area('FDE_y',[0,0,0],[7e-6,10e-6,3e-6],2,mesh_grids,'Metal',10000);
width_cur = width_seed;
neff_sweep = mx_get_mode_data(wl,mode_pol,0,bend,{'neff'});
run;
setanalysis('use max index',0);
setanalysis('n',neff_sweep.neff);
findmodes;
width_step = 0.002e-6;
for (itn=1;itn<=max_itn;itn=itn+1){
width_delta = [-0.01:0.002:0.01]*1e-6;
width_sweep = width_cur+width_delta;
radius_sweep = width_sweep/2 + gap + outer_side;
#### Adding single sweep ####
if (bend>0){
sweeps = struct;
sweeps.var_names = {'width','radius'};
sweeps.radius = radius_sweep;
sweeps.width = width_sweep;
sweeps.var_select = {'::model::waveguide::x span','::model::FDE::bend radius'};
sweeps.var_types = {'Length','Length'};
sweeps.result_names = {'TE0_neff'};
sweeps.result_select = {'::model::FDE::data::mode'+num2str(mode_idx)+'::neff'};
sweeps.bound_para_idx = [1,2];
neff_data = mx_sweep(sweeps,1);
neff_data = abs(neff_data.result);
mismatch = neff*bend - neff_data*radius_sweep;
}
else {
sweeps = struct;
sweeps.var_names = {'width'};
sweeps.width = width_sweep;
sweeps.var_select = {'::model::WG::x span'};
sweeps.var_types = {'Length'};
sweeps.result_names = {'TE0_neff'};
sweeps.result_select = {'::model::FDE::data::mode'+num2str(mode_idx)+'::neff'};
sweeps.bound_para_idx = [1];
neff_data = mx_sweep(sweeps,1);
neff_data = abs(neff_data.result);
mismatch = neff - neff_data;
}
if ((mismatch(1)*mismatch(end)) <=0) {
idx_match = find(abs(mismatch) == min(abs(mismatch)));
itn = max_itn + 1;
}
else {
delta_match = mismatch(1) - mismatch(end);
cent_match = (mismatch(1) + mismatch(end))/2;
delta_width = (width_delta(1)-width_delta(end))/delta_match*cent_match;
width_cur = width_cur - delta_width;
width_cur = round(width_cur/width_step)*width_step;
print(width_cur);
}
}
#matched_width = width_sweep(idx_match);
return width_sweep(idx_match);
load(cur_file_name);
}