├── SimMolFil ├── Ultility │ ├── xcorr_normal.m │ ├── fwhm.m │ ├── fwzm.m │ ├── rand_sech.m │ ├── plot_model.m │ └── Plot_ML_result.m ├── unittests │ ├── run_all_tests.m │ ├── DFGTest.m │ └── EvaluationTest.m ├── +simulation │ ├── Feedback.m │ ├── Const.m │ ├── Filter.m │ ├── Join.m │ ├── Constants.m │ ├── Input.m │ ├── Fiber.m │ ├── Coupler.m │ ├── Show.m │ ├── Recurrence.m │ ├── +builder │ │ ├── Builder.m │ │ └── Evaluation.m │ ├── Configuration.m │ ├── Operation.m │ └── Model.m ├── Amplifier │ ├── Spectra │ │ ├── GetGuassianSpectrum_w.m │ │ ├── GetYbSpecturm_w.m │ │ └── GetYbSpectrum.m │ ├── AmpSimp │ │ ├── testcodes │ │ │ ├── test_fzero.m │ │ │ ├── test_gain_saturated.m │ │ │ ├── test_Pin_Pout.m │ │ │ └── test_onetrip_gain.m │ │ ├── gain_saturated3.m │ │ ├── gain_saturated2.m │ │ ├── AmpSimpNonoise.m │ │ ├── filter_lorentz_tf.m │ │ └── AmpSimpNoise.m │ └── AmpStable │ │ ├── AmpGainWCal.m │ │ ├── EqualAmpSimpPara.m │ │ ├── AmpTBV.m │ │ ├── AmpParaCal.m │ │ ├── AmpGain.m │ │ ├── TEST │ │ ├── AmpStableTest.m │ │ ├── AmpReaborption.m │ │ └── AmpStableMain.m │ │ └── cal_AmpSimpPara.m ├── Coupler │ └── coupler.m ├── GNLSE │ └── Solver │ │ ├── Linearoperator_w.m │ │ ├── Raman_response_w.m │ │ ├── NonLinearoperator_w.m │ │ └── IP_CQEM_FD.m ├── Filter │ ├── filter_BPF.m │ └── filter_gauss.m └── +component │ ├── Coupler.m │ ├── Filter.m │ ├── Fiber.m │ └── ActiveFiber.m ├── .gitignore ├── LICENSE ├── README.md └── Examples └── mainP1.m /SimMolFil/Ultility/xcorr_normal.m: -------------------------------------------------------------------------------- 1 | function [ out ] = xcorr_normal( x,y,lag ) 2 | 3 | nt = size(x,1); 4 | out = xcorr(x,y,lag); 5 | out = out/((sqrt(sum(x.^2)*sum(y.^2)))/nt^2); 6 | 7 | end 8 | 9 | -------------------------------------------------------------------------------- /SimMolFil/unittests/run_all_tests.m: -------------------------------------------------------------------------------- 1 | clear; 2 | clc; 3 | 4 | resDFGTest = run(DFGTest); 5 | 6 | resEvaluationTest = run(EvaluationTest); 7 | 8 | disp(resDFGTest); 9 | disp(resEvaluationTest); 10 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Feedback.m: -------------------------------------------------------------------------------- 1 | function [op] = Feedback() 2 | %FEEDBACK Create a Operation for Feedback 3 | % Usage: 4 | % uout = Feedback(u_reccurence,u_in); 5 | 6 | import simulation.* 7 | 8 | op = Operation("","Feedback",2,... 9 | struct()); 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Const.m: -------------------------------------------------------------------------------- 1 | function [m] = Const(value) 2 | %COUPLER Create a model for Const signal 3 | % Const Models need no name 4 | % value: value hold by the model 5 | 6 | import simulation.* 7 | 8 | m = Model(Operation("", "Const", 0,... 9 | struct("value",value)),[]); 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Filter.m: -------------------------------------------------------------------------------- 1 | function [op] = Filter(name, filter) 2 | %FILTER Create a Filter Operation 3 | % Usage: 4 | % filter = Filter(name, filter); 5 | % uout = uin + filter; 6 | 7 | import simulation.* 8 | 9 | op = Operation(name,"Filter",1,... 10 | struct("filter",filter)); 11 | 12 | end 13 | 14 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Join.m: -------------------------------------------------------------------------------- 1 | function [op] = Join() 2 | %JOIN Create a Operation for Feedback 3 | % Usage: 4 | % u_main = Join(u_main+u_side); 5 | % Extende to u_main = Join(u_main+u_side1+...) in the future 6 | 7 | import simulation.* 8 | 9 | op = Operation("","Join",2,... 10 | struct()); 11 | 12 | end 13 | 14 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/Spectra/GetGuassianSpectrum_w.m: -------------------------------------------------------------------------------- 1 | function [ sigE_w ] = GetGuassianSpectrum_w( nt,fo,df,c ) 2 | 3 | f = (-(nt/2)*df:df:(nt/2-1)*df) + fo; % frequencies vector (THz) 4 | lam = c./f; % nm 5 | 6 | sigE_w = 1e-27* (340*exp(-(((lam-1030)/100).^2))); 7 | 8 | 9 | end 10 | 11 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Constants.m: -------------------------------------------------------------------------------- 1 | classdef Constants 2 | %CONSTANTS Summary of this class goes here 3 | % Detailed explanation goes here 4 | 5 | properties (Constant = true) 6 | speed_of_light = 299792.458; % nm/ps 7 | c = 299792.458; % nm/ps 8 | end 9 | 10 | end 11 | 12 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpSimp/testcodes/test_fzero.m: -------------------------------------------------------------------------------- 1 | Pin =1; 2 | 3 | GssdB = 20; % (dB) 4 | PoutsatdB = 40; % (dBm) 5 | 6 | Gss = 10^(GssdB/10); 7 | Poutsat = (10^(PoutsatdB/10))/1000; 8 | 9 | G0 = Gss/100; 10 | G = fzero(@(G)(G-Gss*exp(-G+1)),G0); 11 | 12 | Psat = Poutsat/G; 13 | 14 | G = fzero(@(G)(G-Gss*exp(-(G-1)*Pin/Psat)),Gss); 15 | 16 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Input.m: -------------------------------------------------------------------------------- 1 | function [m] = Input(name) 2 | %INPUT Create a Model object that asks for input 3 | % name: name of the input operation 4 | % some input will eventually be put into a variable called name 5 | % Usage: 6 | % in = Input(name); 7 | 8 | import simulation.* 9 | 10 | m = Model(Operation(name, "Input", 0, struct()),[]); 11 | 12 | end 13 | 14 | -------------------------------------------------------------------------------- /SimMolFil/Coupler/coupler.m: -------------------------------------------------------------------------------- 1 | function [ u1o,u2o ] = coupler( u1i,u2i,rho ) 2 | %COUPLER simulate an four-end optical coupler 3 | % 4 | % rho: couple ratio, u1o = sqrt(rho)*u1i, u1i and u1o are at the same side 5 | 6 | if rho>1 7 | rho = 1; 8 | elseif rho <0 9 | rho = 0; 10 | end 11 | 12 | u1o = sqrt(rho)*u1i + 1i*sqrt(1-rho)*u2i; 13 | u2o = 1i*sqrt(1-rho)*u1i + sqrt(rho)*u2i; 14 | 15 | end 16 | 17 | -------------------------------------------------------------------------------- /SimMolFil/GNLSE/Solver/Linearoperator_w.m: -------------------------------------------------------------------------------- 1 | function [ LOP ] = Linearoperator_w( alpha,betaw,w ) 2 | %Linearoperator_w 3 | 4 | LOP = -fftshift(alpha/2); 5 | if (length(betaw) == length(w)) % If the user manually specifies beta(w) 6 | LOP = LOP - 1i*betaw; 7 | LOP = fftshift(LOP); 8 | else 9 | for ii = 0:length(betaw)-1 10 | LOP = LOP - 1i*betaw(ii+1)*(w).^ii/factorial(ii); 11 | end 12 | end 13 | 14 | end 15 | 16 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Fiber.m: -------------------------------------------------------------------------------- 1 | function [op] = Fiber(name,fiber) 2 | %FIBER Create a Operation for Fiber component 3 | % name: name of the Fiber Operation 4 | % fiber: a fiber component object, which will eventually be used to 5 | % calculation pulse propagation 6 | % Usage: 7 | % fiber = Fiber(name,fiber); 8 | % uout = uin + fiber; 9 | 10 | import simulation.* 11 | 12 | op = Operation(name,"Fiber",1,... 13 | struct("fiber",fiber)); 14 | 15 | end 16 | 17 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpSimp/testcodes/test_gain_saturated.m: -------------------------------------------------------------------------------- 1 | % Amplifier parameters: 2 | GssdB = 10; % (dB) 3 | PsatdB = 40; % (dBm) 4 | NF = 7; % (dB) 5 | 6 | Pin = linspace(0,20,100); 7 | 8 | gain2 = []; 9 | for ii = 1:100 10 | gain2 = [gain2,gain_saturated2(Pin(ii),GssdB,PsatdB)]; 11 | end 12 | figure(2);plot(Pin,gain2); 13 | 14 | gain3 = []; 15 | for ii = 1:100 16 | gain3 = [gain3,gain_saturated3(Pin(ii),GssdB,PsatdB)]; 17 | end 18 | figure(3);plot(Pin,gain3); 19 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Coupler.m: -------------------------------------------------------------------------------- 1 | function [ops] = Coupler(name,coupler) 2 | %COUPLER Create two Operation objects in an array for Coupler component 3 | % name: name of the Coupler Operation 4 | % coupler: a coupler component 5 | % A optical coupler usually has 2 input ends and 2 output ends 6 | 7 | import simulation.* 8 | 9 | ops = [Operation(name,"CouplerOut1",2,... 10 | struct("coupler",coupler)),... 11 | Operation(name,"CouplerOut2",2,... 12 | struct("coupler",coupler))]; 13 | 14 | end 15 | 16 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Show.m: -------------------------------------------------------------------------------- 1 | function [op] = Show(options) 2 | %SHOW create a show operation to display a model output 3 | % options: struct that contain show parameters 4 | % After creation, Show operator s can be called by m = s(m) 5 | % Show operator should return same model as its input 6 | if ~isa(options,"struct") 7 | error("Show: options should be struct but got %s", class(options)); 8 | end 9 | 10 | import simulation.* 11 | 12 | op = Operation("", "Show", 1,... 13 | options); 14 | 15 | end 16 | 17 | -------------------------------------------------------------------------------- /SimMolFil/Filter/filter_BPF.m: -------------------------------------------------------------------------------- 1 | function uo = filter_BPF( ui,mod,fo,df ) 2 | %FILTER_BPF filter the pulse by a band-pass filter 3 | 4 | Ui = fft(ui); 5 | N = size(Ui,2); 6 | 7 | c = 299792.458; % speed of light nm/ps 8 | 9 | f = fftshift((-(N/2)*df:df:(N/2-1)*df) + fo); % frequencies vector (THz) 10 | lambda = c./(f + fo); % lambdas vector (nm) 11 | 12 | delta_phi = (2*pi./lambda*1e9)*mod.L*mod.bf; 13 | Tf = cos(delta_phi/2).^2; 14 | 15 | uo = ifft(Ui.*Tf); % apply BP filter 16 | 17 | end 18 | 19 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/Spectra/GetYbSpecturm_w.m: -------------------------------------------------------------------------------- 1 | function [ sigA_w,sigE_w,alpha_w ] = GetYbSpecturm_w( nt,fo,df,c ) 2 | %GETYBSPECTURM_W_ return the emission and absoption spectra of Yb 3 | 4 | % Input parameters 5 | % nt: 6 | % fo: central pulse frequency (THz) 7 | % df: frequencies separation (THz) 8 | % c: 9 | % Output parameters 10 | % 11 | 12 | f = (-(nt/2)*df:df:(nt/2-1)*df) + fo; % frequencies vector (THz) 13 | lam = c./f; % nm 14 | [sigA_w,sigE_w,alpha_w] = GetYbSpectrum(lam); 15 | % plot(lam,[sigA_w;sigE_w;]) 16 | 17 | end 18 | 19 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpStable/AmpGainWCal.m: -------------------------------------------------------------------------------- 1 | function [ gain_w ] = AmpGainWCal( mod, gain,dz) 2 | % 3 | % gain (km-1) 4 | 5 | % c = 299792458; % speed of light (m/s) 6 | % h = 6.626e-34; % Planck Constant (J/s) 7 | 8 | % N2 = gain*1e-3/mod.sigE_s/mod.dopN; 9 | % if N2<0.1 10 | % N2 = 0.1; 11 | % end 12 | % N0 = 0.8*(1- N2); 13 | % N0 = 1- N2; 14 | % gain_w = mod.sigE_w*N2 - mod.sigA_w*N0; 15 | 16 | n2 = gain*1e-3/(mod.k0*mod.Gamma_s*mod.dopN)/(mod.sigE_s+mod.sigA_s)+... 17 | mod.sigA_s/(mod.sigE_s+mod.sigA_s); 18 | n0 = 1 - n2; 19 | gain_w = mod.sigE_w*n2 - mod.sigA_w*n0; 20 | 21 | end -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpSimp/gain_saturated3.m: -------------------------------------------------------------------------------- 1 | function gain = gain_saturated3(Pin,GssdB,PsatdBm) 2 | % calculate the gain of the amplifier given the input power, the small 3 | % signal gain and saturation power 4 | % 5 | % Pin: input power 6 | % GssdB: small signal gain(dB) 7 | % PsatdBm : saturation input power(dBm) 8 | % 9 | % source code by CJH 10 | 11 | % where: G is the saturated gain 12 | % G = Gss*exp(-(G-1)Pin/Psat) (eq1) 13 | 14 | Gss = 10^(GssdB/10); 15 | Psat = (10^(PsatdBm/10))/1000; 16 | 17 | % numerical calculation of G 18 | G = fzero(@(G)(G-Gss*exp(-(G-1)*Pin/Psat)),Gss/10); 19 | 20 | gain = G; -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpSimp/testcodes/test_Pin_Pout.m: -------------------------------------------------------------------------------- 1 | clear 2 | % Active fiber parameters: 3 | gssdB = 10; % (dB/m) 4 | PsatdBm = 40; % (dBm) 5 | LossdB = 0; % (dB) 6 | loss = 10^(LossdB/10); 7 | Length =0.5; % (m) 8 | d_z = 0.001; % (m) 9 | N_z = Length/d_z; 10 | 11 | Pmax = 10; 12 | N_P = 100; 13 | 14 | Pin = linspace(0,Pmax,N_P); 15 | Pout = Pin; 16 | tic 17 | for jj = 1:N_P; 18 | for ii = 1:N_z 19 | gain2 = gain_saturated2(Pout(jj),gssdB,PsatdBm); 20 | Pout(jj) = exp((gain2-loss)*d_z)*Pout(jj); 21 | end 22 | end 23 | toc 24 | 25 | figure(1);plot(Pin,Pout); -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpSimp/gain_saturated2.m: -------------------------------------------------------------------------------- 1 | function gain = gain_saturated2(Pin,gssdB,PsatdBm) 2 | % calculate the gain coefficient of the amplifier given the input power, the small 3 | % signal gain coefficient and saturation power 4 | % 5 | % Input parameters 6 | % Pin: input average power (W) 7 | % gssdB: small signal gain coefficient(dB/km) 8 | % PsdBm : saturation input power(dBm) 9 | % 10 | % Outputs 11 | % gain: gain saturated gain coefficient (km^-1) 12 | % 13 | % source code by CJH 14 | 15 | % where: G is the saturated gain 16 | % G = Gss/(1+Pin/Psat) 17 | 18 | gss = 10^(gssdB/10); 19 | Psat = (10^(PsatdBm/10))/1000; 20 | 21 | gain = gss./(1+Pin./Psat); %(km-1) ############ -------------------------------------------------------------------------------- /SimMolFil/Ultility/fwhm.m: -------------------------------------------------------------------------------- 1 | function [width,I_l,I_r] = fwhm(x) 2 | % return the Full Width at Half Maximum of the pulse x 3 | 4 | nsize = length(x); 5 | [peak,ind_peak] = max(x); 6 | half_peak = peak/2; 7 | % 3 dB 8 | x_l = x(1:ind_peak); 9 | x_r = x(1+ind_peak:end); 10 | I_l = find(fliplr(x_l)<=half_peak,1,'first'); 11 | I_r = find(x_r<=half_peak,1,'first'); 12 | 13 | if isempty(I_l) 14 | I_l = find(fliplr(x_r)<=half_peak,1,'first'); 15 | width = I_l+I_r+ind_peak; 16 | I_l = nsize - I_l; 17 | elseif isempty(I_r) 18 | I_r = find(x_l<=half_peak,1,'first'); 19 | width = I_l+I_r+nsize-ind_peak; 20 | else 21 | width = I_l+I_r; 22 | I_l = ind_peak - I_l; 23 | I_r = ind_peak + I_r; 24 | end -------------------------------------------------------------------------------- /SimMolFil/Ultility/fwzm.m: -------------------------------------------------------------------------------- 1 | function [width,I_l,I_r] = fwzm(x,eps) 2 | % return the Full Width at Zero Maximum of the pulse x 3 | 4 | nsize = length(x); 5 | [peak,ind_peak] = max(x); 6 | zero_peak = peak*eps; % 1e-4 7 | 8 | x_l = x(1:ind_peak); 9 | x_r = x(1+ind_peak:end); 10 | I_l = find(fliplr(x_l)<=zero_peak,1,'first'); 11 | I_r = find(x_r<=zero_peak,1,'first'); 12 | 13 | if isempty(I_l) 14 | I_l = find(fliplr(x_r)<=zero_peak,1,'first'); 15 | width = I_l+I_r+ind_peak; 16 | I_l = nsize - I_l; 17 | elseif isempty(I_r) 18 | I_r = find(x_l<=zero_peak,1,'first'); 19 | width = I_l+I_r+nsize-ind_peak; 20 | else 21 | width = I_l+I_r; 22 | I_l = ind_peak - I_l; 23 | I_r = ind_peak + I_r; 24 | end -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpSimp/AmpSimpNonoise.m: -------------------------------------------------------------------------------- 1 | function [Eout,gain] = AmpSimpNonoise(Ein,L,gssdB,PsatdBm) 2 | % simple model of optical amplifier. The model includes the gain 3 | % saturation without noise 4 | % 5 | % source code by Lam Quoc Huy 6 | % modified by CJH 7 | % 8 | % Inputs: 9 | % small signal gain: GssdB (dB) 10 | % input saturation power: PsatdBm (dBm) 11 | % active fiber length: L 12 | % The input is a column vector containing block N samples of the optical signal sampling at the 13 | % rate 1/dt 14 | % The output is calculated using 15 | % Eout = Ein*sqrt(G) 16 | % where: G is the saturated gain 17 | 18 | N = size(Ein,1); 19 | Pin = (sum(Ein.*conj(Ein))/N); 20 | gain = gain_saturated2(Pin,gssdB,PsatdBm); 21 | 22 | Eout = sqrt(exp(gain*L))*Ein; 23 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Recurrence.m: -------------------------------------------------------------------------------- 1 | function [m] = Recurrence(name, initial_value, condition) 2 | %VARIABLE Create a Model presents a Recuurence Point 3 | % name: name of the Recurence Point in this model 4 | % initial_value: the initial value of the recurrence node (Model/const) 5 | % condition: if condition is satified, feedback to Recurrence 6 | % Once created, Recuurence v can be used with feedback operatior f 7 | % and another variable s. By writting v = f(v, s), the programe will 8 | % go to the statment when v is created and update the value of the 9 | % Recurrence point v until the condition turn false 10 | 11 | import simulation.* 12 | 13 | m = Model(Operation(name, "Recurrence", 1,... 14 | struct("condition",condition)),Model(initial_value)); 15 | end 16 | 17 | -------------------------------------------------------------------------------- /SimMolFil/Filter/filter_gauss.m: -------------------------------------------------------------------------------- 1 | function uo = filter_gauss(ui,f3dB,fc,n,fo,df) 2 | % filter_gauss(ui,f3dB,n) 3 | % filter the input signal with the n order gaussian filter 4 | % 5 | % Input parameters 6 | % ui: input field amplitude (row vector) 7 | % f3dB: gaussian filter 3dB bandwith 8 | % fc: gaussian filter central frequency (THz) 9 | % n: gaussian filter order 10 | % fo: central pulse frequency (THz) 11 | % df: frequencies separation (THz) 12 | % 13 | % Outputs 14 | % uo: output field amplitude 15 | % 16 | 17 | Ui = fft(ui); 18 | N = size(Ui,2); 19 | 20 | f = fftshift((-(N/2)*df:df:(N/2-1)*df) + fo); % frequencies vector (THz) 21 | 22 | % n order gaussian filter 23 | Tf = exp(-log(sqrt(2))*(2/f3dB*(f-fc)).^(2*n)); 24 | 25 | uo = ifft(Ui.*Tf); % apply n order gaussian filter 26 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpSimp/filter_lorentz_tf.m: -------------------------------------------------------------------------------- 1 | function tf = filter_lorentz_tf(ui,fbw,fc,fo,df) 2 | % filter_lorentz_tf(fbw,fc,fo,df) 3 | % calculate the transfer function of lorentz filter 4 | % 5 | % Input parameters 6 | % ui: input field amplitude (row vector) 7 | % fbw: lorentz filter bandwith (FWHM) 8 | % fc: lorentz filter central frequency (THz) 9 | % fo: central pulse frequency (THz) 10 | % df: frequencies separation (THz) 11 | % Output parameters 12 | % tf: transfer function of lorentz filter 13 | % 14 | % 15 | % Outputs 16 | % source code by CJH 17 | 18 | N = size(ui,2); 19 | 20 | % The Ui's corresponding frequency 21 | f = (-(N/2)*df:df:(N/2-1)*df) + fo; % frequencies vector (THz) 22 | w = 2*pi*f; 23 | 24 | % lorentz filter 25 | tf = (fbw)/2/pi./((f-fc).^2+(fbw/2)^2); 26 | tf = tf/max(tf(:)); -------------------------------------------------------------------------------- /SimMolFil/Ultility/rand_sech.m: -------------------------------------------------------------------------------- 1 | function [u0] = rand_sech(nt, time_window, beta2,gamma) 2 | %RAND_SECH Generate a rand sech profile as the initial condition 3 | % Initial condtion will not affect the stable solution 4 | % Init the light field to a pulse-like shape would reduce convergence time, 5 | % compaired with plain random numbers 6 | 7 | if(nargin == 2) 8 | beta2 = 20.1814; 9 | gamma = 1.8317; 10 | end 11 | 12 | dt = time_window/nt; 13 | t = -time_window/2:dt:(time_window/2-dt); 14 | 15 | N2 = 1^2; % Soliton Order 16 | tfwhm = time_window/4; % ps 17 | P_peak = 2*N2*abs(beta2)/gamma/tfwhm^2; % Peak power of the initial pulse (W) 18 | u0 =sqrt(P_peak)*sech(t/tfwhm); %initial field shape in W^0.5 19 | rng(0); 20 | u0 = abs(wgn(nt,1,25))'.*u0; 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /SimMolFil/Ultility/plot_model.m: -------------------------------------------------------------------------------- 1 | function [] = plot_model(config,input) 2 | %PLOT_MODEL A function passed to Show operator to plot its input 3 | % config, the current configuration, TYPE. Configuration 4 | % input, anything 5 | 6 | %---------plot temporal input and output pulses 7 | figure(1); 8 | subplot(2,1,1) 9 | plot (config.t,abs(input).^2,'r.-');axis tight; 10 | grid on; 11 | xlabel ('t (ps)'); 12 | ylabel ('|u(z,t)|^2 (W)'); 13 | title ('Pulse Shape'); 14 | %---------plot output spectrum------------------ 15 | spec = fftshift(fft(input)); 16 | specnorm = spec.*conj(spec); 17 | specnorm = specnorm/max(specnorm); 18 | subplot(2,1,2) 19 | plot(simulation.Constants.c./(config.f + config.f0),specnorm,'r.-');axis tight; 20 | grid on; 21 | xlabel ('Wavelength (nm)'); 22 | ylabel ('Normalized Spectrum (a.u.)'); 23 | title ('Output Spectrum'); 24 | pause(0.1) 25 | end 26 | 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | 49 | # Matlab 50 | *.mat 51 | *.fig -------------------------------------------------------------------------------- /SimMolFil/+simulation/+builder/Builder.m: -------------------------------------------------------------------------------- 1 | classdef Builder < handle 2 | %BUILDER A builder class that convert a Model into Evaluation 3 | % append method, add a model to the program that is being built 4 | % build method, return a Evaluation based on current program 5 | 6 | properties (Access = private) 7 | program 8 | end 9 | 10 | methods 11 | function obj = Builder() 12 | %BUILDER Construct an instance of this class 13 | obj.program = []; 14 | end 15 | 16 | function append(obj, model) 17 | % APPEDND, add a model to the program that is being built 18 | obj.program = [obj.program; model]; 19 | end 20 | 21 | function eval = build(obj) 22 | % BUILD, return a Evaluation based on current program 23 | eval = simulation.builder.Evaluation(obj.program); 24 | end 25 | end 26 | end 27 | 28 | -------------------------------------------------------------------------------- /SimMolFil/+component/Coupler.m: -------------------------------------------------------------------------------- 1 | classdef Coupler 2 | %COUPLER simple four-end optical coupler 3 | % u1i u2i 4 | % | | 5 | % |-| 6 | % |-| 7 | % | | 8 | % u1o u2o 9 | 10 | properties 11 | rho % couple ratio (u1i,u2i)->(u1o,u2o), u1o = sqrt(rho)*u1i 12 | end 13 | 14 | methods 15 | function obj = Coupler(rho) 16 | %COUPLER Construct an instance of this class 17 | if rho<0 || rho>1 18 | error("Coupler: Invalid rho range"); 19 | end 20 | obj.rho = rho; 21 | end 22 | 23 | function u1o = couplerOut1(obj,u1i,u2i) 24 | u1o = sqrt(obj.rho)*u1i + 1i*sqrt(1-obj.rho)*u2i; 25 | end 26 | 27 | function u2o = couplerOut2(obj,u1i,u2i) 28 | u2o = 1i*sqrt(1-obj.rho)*u1i + sqrt(obj.rho)*u2i; 29 | end 30 | end 31 | end 32 | 33 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/Spectra/GetYbSpectrum.m: -------------------------------------------------------------------------------- 1 | function [sigA,sigE,alpha] = GetYbSpectrum(lam) 2 | % lam = lam - 3.0125; % shift the spectrum 3 | if nargin<1, lam = 1e-9 * (800:1200); end 4 | if lam(1)>1, lam = lam*1e-9; end % convert from nm to m 5 | 6 | lam = lam*1e9; 7 | 8 | % Generate Gaussians describing emission / absorption cross sections 9 | sigA = 1e-27* (180*exp(-(((lam-950)/70).^2)) + ... 10 | 360*exp(-(((lam-895)/24).^2)) + ... 11 | 510*exp(-(((lam-918)/22).^2)) + ... 12 | 160*exp(-(((lam-971)/12).^2)) + ... 13 | 2325*exp(-(((lam-975)/4).^2))); 14 | sigE = 1e-27* (2325*exp(-(((lam-975)/4).^2)) + ... 15 | 160*exp(-(((lam-978)/12).^2)) + ... 16 | 340*exp(-(((lam-1025)/20).^2)) + ... 17 | 175*exp(-(((lam-1050)/60).^2)) + ... 18 | 150*exp(-(((lam-1030)/90).^2))); 19 | 20 | % sigE = 1e-27* (340*exp(-(((lam-1030)/50).^2))); 21 | 22 | alpha = sigA./sigE; 23 | 24 | end 25 | 26 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpStable/EqualAmpSimpPara.m: -------------------------------------------------------------------------------- 1 | function [ gssdb,PsatdBm ] = EqualAmpSimpPara(mod,P_pump) 2 | % Retrive small signal gain coefficient and saturation power by numerically 3 | % solving the amplifier rate equation 4 | 5 | % gssdb :db/km 6 | 7 | % gss = pump_p*mod.absorb_p*mod.P_IS_p/mod.P_CS_s/(mod.P_IS_p+pump_p)-mod.absorb_s; % m^-1 8 | % gss = gss*1e3 9 | % gssdb = 10*log10(gss); 10 | 11 | P_signal = 0.00001; % W, small signal 12 | L = 5; % m 13 | 14 | dz = 1e-2; 15 | L = dz:dz:L; 16 | 17 | gain = zeros(1,length(L)); 18 | P_p_z = zeros(1,length(L)); 19 | P_s_z = zeros(1,length(L)); 20 | 21 | P_p_z(1) = P_pump; 22 | P_s_z(1) = P_signal; 23 | for ii = 1:length(L) 24 | [gain_t,~,P_p_z_t,P_s_z_t] = AmpGain(mod,P_p_z(ii),P_s_z(ii),dz,'forward'); 25 | gain(ii) = gain_t; 26 | P_p_z(ii+1) = P_p_z_t; 27 | P_s_z(ii+1) = P_s_z_t; 28 | end 29 | temp = abs(gain - max(gain)/2); 30 | PsatdBm = 10*log10(P_s_z(temp == min(temp))*1e3); 31 | gssdb = 10*log10(max(gain)); 32 | 33 | 34 | end 35 | 36 | -------------------------------------------------------------------------------- /SimMolFil/GNLSE/Solver/Raman_response_w.m: -------------------------------------------------------------------------------- 1 | function [ hrw,fr] = Raman_response_w( t,mod) 2 | %RAMAN_RESPONSE 3 | global Raman; 4 | if (isfield(mod,'raman') || isprop(mod,'raman')) && mod.raman==0 5 | hrw = 0; 6 | fr = 0; 7 | elseif isempty(Raman) || length(Raman.hrw)~=length(t) 8 | % Raman parameters 9 | t1 = 12.2e-3; % raman parameter t1 [ps] 10 | t2 = 32e-3; % raman parameter t2 [ps] 11 | tb = 96e-3; % ps 12 | fc = 0.04; 13 | fb = 0.21; 14 | fa = 1 - fc - fb; 15 | fr = 0.245; % fraccion de respuesta retardada Raman 16 | 17 | tres = t-t(1); % time starting in 0 18 | 19 | ha =((t1^2+t2^2)/(t1*t2^2)).*exp(-tres/t2).*sin(tres/t1); 20 | hb = ((2*tb - tres)./tb^2).*exp(-tres/tb); 21 | hr = (fa + fc)*ha + fb*hb; % hr(t) Raman responce function (ps^-1) 22 | 23 | hrw = fft(hr); 24 | 25 | Raman.hrw = hrw; 26 | Raman.fr = fr; 27 | else 28 | hrw = Raman.hrw; 29 | fr = Raman.fr; 30 | end 31 | 32 | end 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Junhao Cai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpSimp/testcodes/test_onetrip_gain.m: -------------------------------------------------------------------------------- 1 | clear 2 | % Active fiber parameters: 3 | gssdB = 30; % (dB/m) 4 | PsatdBm = 60; % (dBm) 5 | LossdB = 0; % (dB) 6 | loss = 10^(LossdB/10); 7 | Length = 0.75; % (m) 8 | 9 | d_z = 0.001; % (m) 10 | N_z = Length/d_z; 11 | Pin = 0.001; % (W) 12 | 13 | P_l2 = Pin; 14 | gain2 = []; 15 | tic 16 | for ii = 1:N_z 17 | gain2 = [gain2,gain_saturated2(P_l2(ii),gssdB,PsatdBm)]; 18 | P_l2 = [P_l2,exp((gain2(ii)-loss)*d_z)*P_l2(ii)]; 19 | end 20 | gain2 = [gain2,gain_saturated2(P_l2(ii+1),gssdB,PsatdBm)]; 21 | toc 22 | 23 | L = linspace(0,Length,N_z+1); 24 | figure(1); 25 | subplot(2,1,1),plot(L,P_l2); 26 | subplot(2,1,2),plot(L,gain2); 27 | 28 | % P_l1 = Pin; 29 | % gain1 = []; 30 | % GssdB = 10*log10(exp(10^(gssdB/10)*d_z)); 31 | % tic 32 | % for ii = 1:N_z 33 | % gain1 = [gain1,gain_saturated3(P_l1(ii),GssdB,PsatdBm)]; 34 | % P_l1 = [P_l1,gain1(ii)*exp(-loss*d_z)*P_l1(ii)]; 35 | % end 36 | % gain1 = [gain1,gain_saturated3(P_l1(ii+1),GssdB,PsatdBm)]; 37 | % toc 38 | % gain_1 = log(gain1)/d_z; 39 | % 40 | % figure(2); 41 | % subplot(2,1,1),plot(L,P_l1); 42 | % % subplot(2,1,2),plot(L,gain1); 43 | % subplot(2,1,2),plot(L,gain_1); -------------------------------------------------------------------------------- /SimMolFil/GNLSE/Solver/NonLinearoperator_w.m: -------------------------------------------------------------------------------- 1 | function [ NLOP ] = NonLinearoperator_w(u_t,gamma,w,fo,fr,hrw,dt,mod) 2 | % This function calculate the right half side of frequency domain GNLSE 3 | 4 | % Implement the right half side of equation (3) in the "Optimum 5 | % Integration Procedures for Supercontinuum Simulation", which is a 6 | % frequency domain formulation of equation (1) 7 | if ~(isfield(mod,'ssp')||isprop(mod,'ssp')) || mod.ssp == 1 8 | NLOP = -1i*gamma*(1 + w/(2*pi*fo)).*fft(((1-fr)*u_t.*u_t.*conj(u_t))... 9 | + fr*dt*u_t.*ifft(hrw.*fft(u_t.*conj(u_t)))); 10 | elseif fr ~= 0 11 | NLOP = -1i*gamma*fft(((1-fr)*u_t.*u_t.*conj(u_t))... 12 | + fr*dt*u_t.*ifft(hrw.*fft(u_t.*conj(u_t)))); 13 | else 14 | % NLOP = -1i*gamma*fft((1-fr)*u_t.*abs(u_t).^2); 15 | NLOP = -1i*gamma*fft((1-fr)*u_t.*u_t.*conj(u_t)); % faster 16 | end 17 | % The factor dt in the second term is due to the discretization of the 18 | % convolution between hr and u_t calculated in frequency domain using 19 | % 2-FFT method 20 | % Please refer to section "Nonlinear fibre optics overview"of the book 21 | % "SUPERCONTINUUM GENERATION IN OPTICAL FIBERS" 22 | 23 | end 24 | 25 | -------------------------------------------------------------------------------- /SimMolFil/+component/Filter.m: -------------------------------------------------------------------------------- 1 | classdef Filter 2 | %FILTER Summary of this class goes here 3 | % Detailed explanation goes here 4 | 5 | properties 6 | lambda_c % filter centre wavelength (nm) 7 | lambda_bw % filter bandwidth (nm) 8 | order % filter order 9 | 10 | fc % filter centre frequency (THz) 11 | f3dB % filter 3dB bandwidth(THz) 12 | end 13 | 14 | methods 15 | function obj = Filter(lambda_c, lambda_bw, order) 16 | %FILTER Construct an instance of this class 17 | % Detailed explanation goes here 18 | obj.lambda_c = lambda_c; 19 | obj.lambda_bw = lambda_bw; 20 | obj.order = order; 21 | 22 | obj.fc = simulation.Constants.c/lambda_c; 23 | obj.f3dB = simulation.Constants.c/(lambda_c)^2*lambda_bw; 24 | end 25 | 26 | function uo = filter_gauss(obj, ui, f0, df) 27 | %FILTER_GAUSS Apply gaussian filterting to light field 28 | % ui: input field amplitude (column vector) 29 | % fo: central pulse frequency (THz) 30 | % df: frequencies separation (THz) 31 | uo = filter_gauss(transpose(ui),obj.f3dB,obj.fc,obj.order,f0,df) ; 32 | end 33 | end 34 | 35 | end 36 | 37 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpStable/AmpTBV.m: -------------------------------------------------------------------------------- 1 | function [ gain,exitflag,P_p_0,P_s_z ] = AmpTBV( mod,P_p_z,P_s_0,z) 2 | % calculate the gain coefficient of the amplifier induced from Active fiber 3 | % parameter in module descripter, pump and signal optical power 4 | % USING TWO-POINT BOUNDARY VALUE CONDITION 5 | % ONLY BACKWARD PUMPING 6 | % 7 | % Input parameters 8 | % mod: amplifier parameters 9 | % P_p_z: pump power at z distance after the beginning of the active fiber 10 | % P_s_0 : signal power at the beginning of the active fiber 11 | % z: propogating distance, should be comparatively small 12 | % 13 | % Outputs 14 | % gain: gain coefficient (m^-1) 15 | % exitflag: output of fsolve 16 | % P_p_0 : pump power at the beginning of the active fiber 17 | % P_s_z: signal power at z distance after the beginning of the active fiber 18 | % 19 | 20 | AmpEquation = @(P_pump,S)([P_p_z-P_pump*exp(10^(-mod.absorb_p/10)*z+(P_pump-P_p_z)... 21 | /mod.P_IS_p-(P_s_0-S)/mod.P_CS_p);... 22 | S-P_s_0*exp(-10^(-mod.absorb_s/10)*z+(P_s_0-S)... 23 | /mod.P_IS_s-(P_pump-P_p_z)/mod.P_CS_s)]); 24 | AmpEquation = @(X)(AmpEquation(X(1),X(2))); 25 | 26 | Options = optimoptions('fsolve'); 27 | Options.Display = 'none'; 28 | if z<1e-4 29 | Options.TolFun = 1e-6*z/1e-4; 30 | Options.TolX = Options.TolFun; 31 | end 32 | [P,~,exitflag] = fsolve(AmpEquation,[P_p_z,P_s_0],Options); 33 | 34 | P_p_0 = P(1); 35 | P_s_z = P(2); 36 | 37 | gain = log(P_s_z/P_s_0)/z; % m^-1 38 | % 'gain' is averaged over z. Only if z <<1, 'gain' can be regarded 39 | % as gain coefficient at this point. 40 | 41 | end 42 | 43 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpSimp/AmpSimpNoise.m: -------------------------------------------------------------------------------- 1 | function [Eout,gain] = AmpSimpNoise(Ein,GssdB,PoutsatdB,NF) 2 | % simple model of optical amplifier. The model includes the gain 3 | % saturation with noise 4 | % 5 | % source code by Lam Quoc Huy 6 | % modified by CJH 7 | 8 | % Amplifier parameters: 9 | % small signal gain: GssdB (dB) 10 | % output saturation power: PoutsatdB (dBm) 11 | % 12 | % The input is a column vector containing block N samples of the optical signal sampling at the 13 | % rate 1/Ts 14 | % The output is calculated using 15 | % Eout = Ein*sqrt(G) 16 | % where: G is the saturated gain 17 | % G = Gss*exp(-(G-1)Pin/Psat) (eq1) 18 | global Ts 19 | f = 193.1e12; 20 | hplank = 6.6261*1e-34; 21 | Gss = 10^(GssdB/10); 22 | Poutsat = (10^(PoutsatdB/10))*1e-3; 23 | Psat = Poutsat*(Gss-2)/Gss/log(2); 24 | % Pinsat = 2* Poutsat/Gss; 25 | N = size(Ein,1); 26 | % Pin = (sum(Ein.*conj(Ein))/N); 27 | Pin = mean( (Ein.*conj(Ein)) ); 28 | % numerical calculation of G from the equation G = (Gss - lnG)*Psat/Pin + 1 29 | tol = 0.05; % tolerance for G calculation 30 | step = Gss/2; 31 | G = Gss; 32 | err = 10; 33 | while (err > tol) 34 | G1 = Gss*exp(-(G-1)*Pin/Psat); 35 | err = G1 - G; 36 | if err>0 37 | if step <0 38 | step = -step/2; 39 | end 40 | else 41 | if step >0 42 | step = -step/2; 43 | end 44 | err = -err; 45 | end 46 | G = G + step; 47 | end 48 | G = G - step; 49 | % Eout = sqrt(G)*Ein; 50 | gain = G; 51 | Egain = sqrt(G)*Ein; 52 | dt = Ts; 53 | Bsim = 1/dt; 54 | FigNoise = 10^(NF/10); 55 | nsp = (FigNoise*G-1)/(2*(G-1)); 56 | % Pase = hplank.*opfreq.*nsp*(OGain-1)*Bsim 57 | Pase = hplank.*f.*nsp*(G-1)*Bsim/1000; 58 | PasedB = 10*log10(Pase); 59 | % afout = fft(Egain) + (randn(size(Egain))+i*randn(size (Egain)) )*sqrt(Pase)./sqrt(2); 60 | % Eout = ifft(afout); 61 | % Eout = Egain + (randn(size(Egain))+i*randn(size (Egain)) )*sqrt(Pase)./sqrt(2)./1; 62 | Eout = Egain + wgn(N,1,PasedB,'complex'); 63 | % Eout = Egain; -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpStable/AmpParaCal.m: -------------------------------------------------------------------------------- 1 | function [ mod_cal ] = AmpParaCal( mod,nt,fo,df,c ) 2 | %AMPPARACAL calculate active fiber parameters according to Manufacturer Data 3 | 4 | % c = 299792458; % speed of light (m/s) 5 | h = 6.626e-34; % Planck Constant (J/s) 6 | 7 | % Calculation 8 | mod.Aeff = pi*mod.a^2/4; % Effective Area (doped) (um^2) 9 | mod.Gamma_s = mod.Aeff/mod.Amod; % Confinement Factor for signal 10 | mod.Gamma_p = (mod.a/mod.b)^2; % Confinement Factor for pump 11 | 12 | % Get Emission and Absorbtion Cross Section of Pump and Signal Light 13 | [sigA,sigE,~] = GetYbSpectrum([mod.lambda_p,mod.lambda_s]); 14 | mod.sigE_p = sigE(1); 15 | mod.sigA_p = sigA(1); 16 | mod.sigE_s = sigE(2); 17 | mod.sigA_s = sigA(2); 18 | 19 | % Calculate Absorption Coefficient @lambda_p 20 | % Dopant Concentration (m^-3) 21 | mod.k0 = 4.343; % Constant, See 10.1364/OE.24.009237 22 | mod.dopN = mod.absorb_p_0/mod.k0/GetYbSpectrum(mod.lambda_p_0)/mod.Gamma_p; % dopant concentration m-3 23 | mod.absorb_p = mod.k0*mod.dopN*mod.Gamma_p*mod.sigA_p; 24 | % Fit Well with the Manufacturer Data 1.6 dB/m @915 nm 25 | 26 | mod.absorb_s = mod.k0*mod.dopN*mod.Gamma_s*mod.sigA_s; 27 | 28 | % Calculate Intrinsic and Cross Saturation Power 29 | mod.P_IS_p = mod.Aeff*1e-12/mod.Gamma_p/mod.tf/... 30 | (mod.sigA_p+mod.sigE_p)*h*c/(mod.lambda_p*1e-9); 31 | mod.P_CS_p = mod.P_IS_p; 32 | mod.P_IS_s = mod.Aeff*1e-12/mod.Gamma_s/mod.tf/... 33 | (mod.sigA_s+mod.sigE_s)*h*c/(mod.lambda_s*1e-9); 34 | mod.P_CS_s = mod.P_IS_s; 35 | 36 | [sigA_w,sigE_w,~] = GetYbSpecturm_w(nt,fo,df,c*1e-3); 37 | [sigA_m,sigE_m,~] = GetYbSpectrum(975); 38 | mod.sigA_w = sigA_w/sigA_m; 39 | mod.sigE_w = sigE_w/sigE_m; 40 | mod.sigA_w = sigA_w; 41 | mod.sigE_w = sigE_w; 42 | mod.gain_w = 0; % to indicate gain spectrum evelotion 43 | mod.gssdB = 0; % to indicate an active fiber 44 | 45 | mod.freq_s = c*1e-3/mod.lambda_s; 46 | 47 | 48 | mod_cal = mod; 49 | 50 | end 51 | 52 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Configuration.m: -------------------------------------------------------------------------------- 1 | classdef Configuration 2 | %CONFIGURATION Summary of this class goes here 3 | % Detailed explanation goes here 4 | 5 | properties 6 | nt = 2^12 % number of points 7 | time = 120 % width of time window (ps) 8 | lambda0 = 1030 % pulse central wavelength (nm) 9 | tol = 1e-7 % tolerance 10 | N_trip = 300 % number of total runtrips 11 | 12 | f0 % pulse central frequency (THz) 13 | 14 | dz = 0.00001 % Initial longitudinal step (km) 15 | dt % time step (ps) 16 | df % frequencies separation (THz) 17 | 18 | t % time vector (ps) 19 | f % frequencies vector (THz) 20 | w % angular frequencies vector (THz) 21 | lambda % lambdas vector (nm) 22 | 23 | end 24 | 25 | methods 26 | function obj = Configuration(varargin) 27 | %CONFIGURATION Construct an instance of Configuration 28 | for ii = 1:length(varargin) 29 | switch(ii) 30 | case 1 31 | obj.nt = varargin{ii}; 32 | case 2 33 | obj.time = varargin{ii}; 34 | case 3 35 | obj.lambda0 = varargin{ii}; 36 | case 4 37 | obj.tol = varargin{ii}; 38 | case 5 39 | obj.N_trip = varargin{ii}; 40 | end 41 | end 42 | obj.dt = obj.time/obj.nt; 43 | obj.df = 1/obj.time; 44 | obj.f0 = simulation.Constants.c/obj.lambda0; 45 | 46 | c = simulation.Constants.c; 47 | obj.t = -obj.time/2:obj.dt:(obj.time/2-obj.dt); 48 | obj.f=-(obj.nt/2)*obj.df:obj.df:(obj.nt/2-1)*obj.df; 49 | obj.lambda = c./(obj.f + c/obj.lambda0); 50 | obj.w = 2*pi*obj.f; 51 | end 52 | end 53 | end 54 | 55 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpStable/AmpGain.m: -------------------------------------------------------------------------------- 1 | function [ gain,exitflag,P_p_z,P_s_z ] = AmpGain( mod,P_p_0,P_s_0,z,dir) 2 | % calculate the gain coefficient of the amplifier induced from Active fiber 3 | % parameter in module descripter, pump and signal optical power 4 | % 5 | % Input parameters 6 | % mod: amplifier parameters 7 | % P_p_0 : pump power at the beginning of the active fiber 8 | % P_s_0 : signal power at the beginning of the active fiber 9 | % dir: pump direction,'forward'/'backward' 10 | % z: propogating distance, should be comparatively small (m) 11 | % 12 | % Outputs 13 | % gain: gain coefficient (km^-1) 14 | % exitflag: output of fsolve 15 | % P_p_z: pump power at z distance after the beginning of the active fiber 16 | % P_s_z: signal power at z distance after the beginning of the active fiber 17 | % 18 | 19 | u_p = 1; 20 | if strcmp(dir,'backward') 21 | u_p = -1; 22 | end 23 | 24 | AmpEquation = @(P,S)([P-P_p_0*exp(u_p*(-10^(-mod.absorb_p/10)*z+u_p*(P_p_0-P)... 25 | /mod.P_IS_p+(P_s_0-S)/mod.P_CS_p));... 26 | S-P_s_0*exp(-10^(-mod.absorb_s/10)*z+(P_s_0-S)... 27 | /mod.P_IS_s+u_p*(P_p_0-P)/mod.P_CS_s)]); 28 | AmpEquation = @(X)(AmpEquation(X(1),X(2))); 29 | 30 | Options = optimoptions('fsolve'); 31 | Options.Display = 'none'; 32 | % if z<1e-4 33 | % Options.TolFun = 1e-6*z/1e-4; 34 | % Options.TolX = Options.TolFun; 35 | % end 36 | Options.TolFun = 1e-12; 37 | Options.TolX = Options.TolFun; 38 | 39 | % Using bordinary condition as the initial value for the solution, 40 | % for the Distance Z tends to be small, 41 | % though a better way is to forecast the solution 42 | [P,~,exitflag] = fsolve(AmpEquation,[P_p_0,P_s_0],Options); 43 | 44 | % Forecasting coarse solution 45 | % maximum gain 46 | % Gmax = exp(z*(10^(-mod.absorb_p/10)/mod.P_CS_s*mod.P_IS_p-10^(-mod.absorb_s/10))); 47 | % P_s_z_coarse = Gmax*P_s_0; 48 | % if u_p == 1 49 | % P_p_z_coarse = P_p_0-(P_s_z_coarse - P_s_0)*mod.lambda_p/mod.lambda_s; 50 | % elseif u_p == -1 51 | % P_p_z_coarse = P_p_0+(P_s_z_coarse - P_s_0)*mod.lambda_p/mod.lambda_s; 52 | % end 53 | % 54 | % [P,~,exitflag] = fsolve(AmpEquation,[P_p_z_coarse,P_s_z_coarse],Options); 55 | 56 | P_p_z = P(1); 57 | P_s_z = P(2); 58 | 59 | if u_p == 1 && (P_p_z<0 || P_p_z>P_p_0 || P_s_z<0 || (P_s_z+P_p_z)>(P_s_0+P_p_0)) 60 | fprintf('\nAmpGain Calculation failed\n'); 61 | elseif u_p == -1 && (P_p_z<0 || P_p_z(P_s_0+P_p_z)) 62 | fprintf('\nAmpGain Calculation failed\n'); 63 | end 64 | 65 | if exitflag == -2 66 | fprintf('Algorithm appears to be converging to a point that is not a root.'); 67 | end 68 | 69 | gain = log(P_s_z/P_s_0)/z*1e3; % ;km^-1 70 | % 'gain' is averaged over z. Only if z <<1, 'gain' can be regarded 71 | % as gain coefficient at this point. 72 | 73 | end 74 | 75 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpStable/TEST/AmpStableTest.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | 4 | %% General Parameters 5 | c = 299792458; % speed of light (m/s) 6 | h = 6.626e-34; % Planck Constant (J/s) 7 | 8 | lamda_pulse = 1030; % pulse central lambda (nm) 9 | fo=c/lamda_pulse; % central pulse frequency (THz) 10 | 11 | nt = 2^11; % number of spectral points 12 | time = 60; % ps 13 | dt = time/nt; % ps 14 | t = -time/2:dt:(time/2-dt); % ps 15 | 16 | df=1/(nt*dt); % frequencies separation (Thz) 17 | 18 | %% Active Fiber Parameters 19 | % Predefine of fiber parameter 20 | PM980.Amod = pi*3.47^2; % Mode Field Area (um^2) (um^2) 21 | PM980.n2 = 2.6; % Kerr coefficient (10^-16*cm^2/W) 22 | PM980.gamma = 2*pi*PM980.n2/lamda_pulse/PM980.Amod*1e4; % W^-1 * km^-1 23 | PM980.alpha = 0; % atenuation coef. (km^-1) 24 | PM980.betaw = [0 0 24.5864 26.1949e-3]; % beta coefficients (ps^n/nm) 25 | 26 | PM980.raman = 0; % 0 = exclude raman effect 27 | PM980.ssp = 0; % 0 = disable self sharpen effect 28 | 29 | % From Manufacturer DataSheet 30 | YDF10125 = PM980; 31 | YDF10125.a = 10; % Core Diameter(um) 32 | YDF10125.b = 125; % Cladding Diameter(um) 33 | YDF10125.Amod = pi*5.69^2; % Mode Field Area (um^2) 34 | YDF10125.absorb_p_0 = 4.8; % Cladding Absorption(dB/m) @lambda_p_0 35 | YDF10125.lambda_p_0 = 976; % Pump lambda of Cladding Absorption(dB/m) 36 | % YDF10125.absorb_s = 0.02; % Core Attenuation(dB/m) 37 | YDF10125.betaw = [0 0 20.1814 36.8057e-3]; 38 | 39 | YDF10125.tf = 0.8e-3; % Upper level life time(s) 40 | 41 | YDF10125.lambda_p = 976; % Pump lambda (nm) 42 | YDF10125.lambda_s = lamda_pulse; % Signal lambda (nm) 43 | 44 | YDF10125 = AmpParaCal(YDF10125,nt,fo,df,c); % Calculation of other parameters 45 | 46 | P_pump = 10; % W 47 | P_signal = 1e-7; % W 48 | L = 5; % m 49 | 50 | dz = 1e-2; 51 | L = dz:dz:L; 52 | 53 | gain = zeros(1,length(L)); 54 | P_p_z = zeros(1,length(L)); 55 | P_s_z = zeros(1,length(L)); 56 | 57 | P_p_z(1) = P_pump; 58 | P_s_z(1) = P_signal; 59 | for ii = 1:length(L) 60 | [gain_t,~,P_p_z_t,P_s_z_t] = AmpGain(YDF10125,P_p_z(ii),P_s_z(ii),dz,'forward'); 61 | gain(ii) = gain_t; 62 | P_p_z(ii+1) = P_p_z_t; 63 | P_s_z(ii+1) = P_s_z_t; 64 | end 65 | temp = abs(gain - max(gain)/2); 66 | PsatdBm = 10*log10(P_s_z(temp == min(temp))*1e3) 67 | gssdb = 10*log10(max(gain)) 68 | 69 | gain2 = gain_saturated2(P_s_z(1:end-1),gssdb,PsatdBm); 70 | 71 | gain_s1 = diff(P_s_z)./P_s_z(1:end-1)/dz; 72 | gain_s2 = diff(P_s_z)./P_s_z(2:end)/dz; 73 | gain_s = (gain_s1+gain_s2)/2; 74 | 75 | plot(L,gain);hold on; 76 | plot(L,gain2);hold off 77 | -------------------------------------------------------------------------------- /SimMolFil/+component/Fiber.m: -------------------------------------------------------------------------------- 1 | classdef Fiber 2 | %FIBER Summary of this class goes here 3 | % Detailed explanation goes here 4 | 5 | properties 6 | core_radius % um 7 | Amod % Mode Field Area (um^2) 8 | n2 % Kerr coefficient (10^-16*cm^2/W) 9 | gamma % W^-1 * km^-1 10 | alpha = 0 % Atenuation coefficient (km^-1) 11 | betaw % beta coefficients (ps^n/nm) 12 | L = 0 % fiber length (km) 13 | raman = 0 % 0 = exclude raman effect 14 | ssp = 0 % 0 = disable self sharpen effect 15 | type % fiber type, to load predefined fiber specs 16 | end 17 | 18 | methods 19 | function obj = Fiber(varargin) 20 | %FIBER Construct an instance of this class 21 | import component.* 22 | switch(nargin) 23 | case 0 24 | core_radius = 3.3; 25 | n2 = 2.6; 26 | betaw = [0 0 24.5864 26.1949e-3]; 27 | obj.type = "PM980"; 28 | case 1 29 | % Fiber(type) 30 | if isa(varargin{1},"string") 31 | switch (varargin{1}) 32 | case "PM980" 33 | core_radius = 3.3; 34 | n2 = 2.6; 35 | betaw = [0 0 24.5864 26.1949e-3]; 36 | obj.type = "PM980"; 37 | case "PM1025" 38 | core_radius = 5; 39 | n2 = 2.6; 40 | betaw = [0 0 20.8634 34.9621e-3]; 41 | obj.type = "PM1025"; 42 | case "F10125" 43 | core_radius = 5.25; 44 | n2 = 2.6; 45 | betaw = [0 0 20.1814 36.8057e-3]; 46 | obj.type = "F10125"; 47 | otherwise 48 | error("Fiber: not implemented fiber type %s\n",varargin{1}); 49 | end 50 | else 51 | error("Fiber: not implemented argument types\n"); 52 | end 53 | case 3 54 | % Fiber(core_radius, n2, betaw) 55 | core_radius = varargin{1}; 56 | n2 = varargin{2}; 57 | betaw = varargin{3}; 58 | otherwise 59 | error("Fiber: not implemented argument types\n"); 60 | end 61 | obj.core_radius = core_radius; 62 | obj.Amod = pi*obj.core_radius^2; 63 | obj.n2 = n2; 64 | obj.betaw = betaw; 65 | end 66 | 67 | function obj = cal_gamma(obj,lambda0) 68 | obj.gamma = 2*pi*obj.n2/lambda0/obj.Amod*1e4; 69 | end 70 | 71 | function obj = set_L(obj,L) 72 | obj.L = L; 73 | end 74 | end 75 | end 76 | 77 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpStable/TEST/AmpReaborption.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | %% Simulation Parameter 4 | c = 299792.458; % speed of light nm/ps 5 | 6 | % Input Field Paramenters 7 | N2 = 1^2; % Soliton Order 8 | tfwhm = 30; % ps 9 | lamda_pulse = 1030; % pulse central lambda (nm) 10 | fo=c/lamda_pulse; % central pulse frequency (THz) 11 | 12 | % Numerical Parameters 13 | nt = 2^12; % number of spectral points 14 | time = 100; % ps 15 | dt = time/nt; % ps 16 | t = -time/2:dt:(time/2-dt); % ps 17 | 18 | df=1/(nt*dt); % frequencies separation (Thz) 19 | f=-(nt/2)*df:df:(nt/2-1)*df; % frequencies vector (en THz) 20 | lambda = c./(f + c/lamda_pulse); % lambdas vector (nm) 21 | w = 2*pi*f; % angular frequencies vector (in THz) 22 | dz = 0.00001; % longitudinal step (km) 23 | tol = 1e-6; % photon error number, or local error, depending on the used method. 24 | N_trip = 300; 25 | % if set to 1, all figures will be plotted after simulation hence the 26 | % computation time of the last trip would be considerable 27 | plot_all_fig = 1; 28 | 29 | %% Component Parameter 30 | % Predefine of fiber parameter 31 | PM980.Amod = pi*3.3^2; % Mode Field Area (um^2) (um^2) 32 | PM980.n2 = 2.6; % Kerr coefficient (10^-16*cm^2/W) 33 | PM980.gamma = 2*pi*PM980.n2/lamda_pulse/PM980.Amod*1e4; % W^-1 * km^-1 34 | PM980.alpha = 0; % atenuation coef. (km^-1) 35 | PM980.betaw = [0 0 28.9311 25.4837e-3]; % beta coefficients (ps^n/nm) 36 | 37 | PM980.raman = 0; % 0 = exclude raman effect 38 | PM980.ssp = 0; % 0 = disable self sharpen effect 39 | 40 | YDF10125 = PM980; 41 | YDF10125.a = 5.5; % Core Diameter(um) 42 | YDF10125.b = 125; % Cladding Diameter(um) 43 | YDF10125.absorb_p_0 = 4.8; % Cladding Absorption(dB/m) @lambda_p_0 44 | YDF10125.lambda_p_0 = 976; % Pump lambda of Cladding Absorption(dB/m) 45 | YDF10125.absorb_s = 0.02; % Core Attenuation(dB/m) 46 | 47 | YDF10125.tf = 0.8e-3; % Upper level life time(s) 48 | 49 | YDF10125.lambda_p = 976; % Pump lambda (nm) 50 | YDF10125.lambda_s = 1030; % Signal lambda (nm) 51 | 52 | YDF10125 = AmpParaCal(YDF10125,nt,fo,df,c*1e3); % Calculation of other parameters 53 | 54 | % YDF10125.pump_power = 20; % pump power (W) 55 | 56 | P_pump = 50; % W 57 | P_signal = 0.001; % W 58 | L = 4; % m 59 | 60 | dz = 1e-1; 61 | L = dz:dz:L; 62 | 63 | gain = zeros(1,length(L)); 64 | P_p_z = zeros(1,length(L)); 65 | P_s_z = zeros(1,length(L)); 66 | 67 | P_p_z(1) = P_pump; 68 | P_s_z(1) = P_signal; 69 | for ii = 1:length(L) 70 | [gain_t,~,P_p_z_t,P_s_z_t] = AmpGain(YDF10125,P_p_z(ii),P_s_z(ii),dz,'forward'); 71 | gain(ii) = gain_t; 72 | P_p_z(ii+1) = P_p_z_t; 73 | P_s_z(ii+1) = P_s_z_t; 74 | 75 | end 76 | % N2 = gain*1e-3/YDF10125.sigE_s/YDF10125.dopN; 77 | N2 = gain*1e-3/YDF10125.sigE_s; 78 | 79 | % N2 = 0.1:0.1:1; 80 | % N0 = 1- N2; 81 | % for ii = 1:length(N2) 82 | % gain_w(ii,:) = YDF10125.sigE_w*N2(ii) - YDF10125.sigA_w*N0(ii); 83 | % % figure(1),plot(c./(f+fo),gain_w(ii,:)/max(gain_w(ii,:)));hold on;axis tight 84 | % figure(1),plot(c./(f+fo),gain_w(ii,:));hold on;axis tight 85 | % end -------------------------------------------------------------------------------- /SimMolFil/+component/ActiveFiber.m: -------------------------------------------------------------------------------- 1 | classdef ActiveFiber < component.Fiber 2 | %ACTIVEFIBER Summary of this class goes here 3 | % Detailed explanation goes here 4 | 5 | properties 6 | gssdB 7 | PsatdBm 8 | 9 | lambda_c 10 | lambda_bw 11 | fbw 12 | fc 13 | 14 | RepeatFre 15 | end 16 | 17 | methods 18 | function obj = ActiveFiber(varargin) 19 | %ACTIVEFIBER Construct an instance of this class 20 | % Detailed explanation goes here 21 | import component.* 22 | import simulation.* 23 | switch(nargin) 24 | case 0 25 | sup_varargin = {"F10125"}; 26 | gssdB = 37.5; 27 | PsatdBm = 23.5; 28 | lambda_c = 1030; 29 | lambda_bw = 80; 30 | case 1 31 | % Fiber(type) 32 | if isa(varargin{1},"string") 33 | switch (varargin{1}) 34 | case "YDF10125" 35 | sup_varargin = {"F10125"}; 36 | gssdB = 37.5; 37 | PsatdBm = 23.5; 38 | lambda_c = 1030; 39 | lambda_bw = 80; 40 | otherwise 41 | error("Fiber: not implemented fiber type %s\n",varargin{1}); 42 | end 43 | else 44 | error("Fiber: not implemented argument types\n"); 45 | end 46 | case 5 47 | % Fiber(type, gssdB, PsatdBm, lambda_c, lambda_bw) 48 | if isa(varargin{1},"string") 49 | switch (varargin{1}) 50 | case "YDF10125" 51 | sup_varargin = {"F10125"}; 52 | gssdB = varargin{2}; 53 | PsatdBm = varargin{3}; 54 | lambda_c = varargin{4}; 55 | lambda_bw = varargin{5}; 56 | otherwise 57 | error("Fiber: not implemented fiber type %s\n",varargin{1}); 58 | end 59 | else 60 | error("Fiber: not implemented argument types\n"); 61 | end 62 | case 7 63 | % Fiber(core_radius, n2, betaw, gssdB, PsatdBm, lambda_c, lambda_bw) 64 | sup_varargin = varargin{1:3}; 65 | gssdB = varargin{4}; 66 | PsatdBm = varargin{5}; 67 | lambda_c = varargin{6}; 68 | lambda_bw = varargin{7}; 69 | otherwise 70 | error("Fiber: not implemented argument types\n"); 71 | end 72 | obj = obj@component.Fiber(sup_varargin{:}); 73 | obj.gssdB = gssdB; 74 | obj.PsatdBm = PsatdBm; 75 | obj.lambda_c = lambda_c; 76 | obj.lambda_bw = lambda_bw; 77 | 78 | obj.fbw = Constants.c/(obj.lambda_c)^2*obj.lambda_bw; 79 | obj.fc = Constants.c/obj.lambda_c; 80 | end 81 | 82 | function obj = set_RepeatFre(obj, cavity_length) 83 | obj.RepeatFre = simulation.Constants.c/2/cavity_length; 84 | end 85 | end 86 | end 87 | 88 | -------------------------------------------------------------------------------- /SimMolFil/Ultility/Plot_ML_result.m: -------------------------------------------------------------------------------- 1 | figure(4),pcolor(t,1:ii,abs(u_z(1:ii,:)).^2); 2 | colorbar;axis tight; 3 | shading flat; 4 | ylabel ('run trip'); 5 | xlabel ('t (ps)'); 6 | zlabel ('|u(z,t)|^2 (W)'); 7 | title ('Output Optical Field Evolution'); 8 | view(0,90); 9 | 10 | figure(5),pcolor(c./(f + fo),1:ii,spec_z(1:ii,:)); 11 | colorbar;axis tight; 12 | shading flat; 13 | ylabel ('run trip'); 14 | xlabel ('lambda (nm)'); 15 | zlabel ('Normalized Spectrum (a.u.)'); 16 | title ('Output Spectrum Evolution'); 17 | view(0,90); 18 | 19 | repmat_length = round(size(Plotdata_smf5.u,1)/2); 20 | ut_fft = repmat(abs(fftshift(fft(ut))),repmat_length,1); 21 | u_f_fft = repmat(abs(fftshift(fft(u_f))),repmat_length,1); 22 | uout_fft = repmat(abs(fftshift(fft(uout))),repmat_length,1); 23 | u_nolm_fft = [Plotdata_smf1.ufft;Plotdata_smf2.ufft]; 24 | Plotdata.ufft = [u_f_fft;Plotdata_smf4.ufft;Plotdata_amf1.ufft;Plotdata_smf5.ufft;u_nolm_fft;ut_fft;uout_fft]; 25 | 26 | spec = abs(Plotdata.ufft').^2; 27 | specnorm = spec/max(spec(:)); 28 | figure(7),pcolor(lambda,1:size(Plotdata.ufft,1),specnorm'); 29 | colorbar;axis tight; 30 | shading flat; 31 | xlabel ('lambda (nm)'); 32 | zlabel ('Normalized Spectrum (a.u.)'); 33 | title ('Last Trip Spectrum Evolution'); 34 | view(0,90); 35 | ufft_length = [size(u_f_fft);size(Plotdata_smf4.ufft);size(Plotdata_amf1.ufft);... 36 | size(Plotdata_smf5.ufft);size(u_nolm_fft);size(ut_fft);size(uout_fft)]; 37 | text_all = {'Filter';'SMF1';'AF';'SMF2';'NOLM-SMF';'NOLM-out';'OC'}; 38 | current_height = 0; 39 | for ii = 1:length(text_all) 40 | current_height = current_height+ufft_length(ii)/2; 41 | text(min(lambda),current_height,0,text_all(ii),'color','yellow','FontSize',10); 42 | current_height = current_height+ufft_length(ii)/2; 43 | line([min(lambda),max(lambda)],[current_height,current_height]+1,[0,0],... 44 | 'LineWidth',0.5,'color','white'); 45 | end 46 | 47 | ut_t = repmat(ut,repmat_length,1); 48 | u_f_t = repmat(u_f,repmat_length,1); 49 | uout_t = repmat(uout,repmat_length,1); 50 | u_nolm_t = [Plotdata_smf1.u;Plotdata_smf2.u]; 51 | Plotdata.u = [u_f_t;Plotdata_smf4.u;Plotdata_amf1.u;Plotdata_smf5.u;u_nolm_t;ut_t;uout_t]; 52 | Plotdata.u = (abs(Plotdata.u)).^2; 53 | figure(8),pcolor(t,1:size(Plotdata.u,1),Plotdata.u); 54 | colorbar;axis tight; 55 | shading flat; 56 | xlabel ('t (ps)'); 57 | zlabel ('|u(z,t)|^2 (W)'); 58 | title ('Last Trip Pulse Evolution'); 59 | view(0,90); 60 | current_height = 0; 61 | for iii = 1:length(text_all) 62 | current_height = current_height+ufft_length(iii)/2; 63 | text(min(t),current_height,0,text_all(iii),'color','yellow','FontSize',10); 64 | current_height = current_height+ufft_length(iii)/2; 65 | line([min(t),max(t)],[current_height,current_height]+1,[0,0],... 66 | 'LineWidth',0.5,'color','white'); 67 | end 68 | 69 | 70 | NOLM_ufft = [u_nolm_fft(end,:);Plotdata_smf2_f.ufft(end,:);ut_fft(end,:)]; 71 | NOLM_ufft = abs(NOLM_ufft').^2; 72 | NOLM_ufft = NOLM_ufft ./(lambda'*ones(1,size(NOLM_ufft,2))).^2; 73 | NOLM_ufft = NOLM_ufft./max(NOLM_ufft(:)); 74 | 75 | figure(9);plot(lambda,NOLM_ufft);grid on; 76 | xlabel ('lambda (nm)'); 77 | ylabel ('Normalized Spectrum (a.u.)'); 78 | title ('NLM Specturm Interference'); 79 | 80 | NOLM_u = [u_nolm_t(end,:);Plotdata_smf2_f.u(end,:);ut(end,:)]; 81 | NOLM_u = abs(NOLM_u').^2; 82 | phase_out = [diff(phase(u_nolm_t(end,:)));diff(phase(Plotdata_smf2_f.u(end,:)));diff(phase(ut(end,:)))]; 83 | 84 | figure(10);plot(t,NOLM_u);grid on; 85 | xlabel ('t (ps)'); 86 | ylabel ('|u(z,t)|^2 (W)'); 87 | title ('NLM Pulse Interference'); 88 | 89 | AC = xcorr(Eout,Eout); 90 | AC = AC/max(AC); 91 | figure(10),plot(-time+dt:dt:time-dt,AC); 92 | xlabel ('Time Delay (ps)'); 93 | ylabel ('AC Trace(a.u.)'); 94 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpStable/cal_AmpSimpPara.m: -------------------------------------------------------------------------------- 1 | % Calculate the small signal gain coefficient and saturation power 2 | % Modify pump power here 3 | pump_power = 8; % pump power (W) 4 | % Modify the active fiber parameter in the YDF10125 section 5 | 6 | %% Pump power 7 | 8 | %% Simulation Parameter 9 | c = 299792.458; % speed of light nm/ps 10 | 11 | % Input Field Paramenters 12 | N2 = 1^2; % Soliton Order 13 | tfwhm = 30; % ps 14 | lamda_pulse = 1030; % pulse central lambda (nm) 15 | fo=c/lamda_pulse; % central pulse frequency (THz) 16 | 17 | % Numerical Parameters 18 | nt = 2^12; % number of spectral points 19 | time = 100; % ps 20 | dt = time/nt; % ps 21 | t = -time/2:dt:(time/2-dt); % ps 22 | 23 | df=1/(nt*dt); % frequencies separation (Thz) 24 | f=-(nt/2)*df:df:(nt/2-1)*df; % frequencies vector (en THz) 25 | lambda = c./(f + c/lamda_pulse); % lambdas vector (nm) 26 | w = 2*pi*f; % angular frequencies vector (in THz) 27 | dz = 0.00001; % longitudinal step (km) 28 | tol = 1e-6; % photon error number, or local error, depending on the used method. 29 | N_trip = 300; 30 | % N_trip = 1; 31 | % if set to 1, all figures will be plotted after simulation hence the 32 | % computation time of the last trip would be considerable 33 | plot_all_fig = 0; 34 | reinject_flag = 0; 35 | 36 | %% Component Parameter 37 | % Predefine of fiber parameter 38 | PM980.Amod = pi*3.47^2; % Mode Field Area (um^2) (um^2) 39 | PM980.n2 = 2.6; % Kerr coefficient (10^-16*cm^2/W) 40 | PM980.gamma = 2*pi*PM980.n2/lamda_pulse/PM980.Amod*1e4; % W^-1 * km^-1 41 | PM980.alpha = 0; % atenuation coef. (km^-1) 42 | PM980.betaw = [0 0 24.5864 26.1949e-3]; % beta coefficients (ps^n/nm) 43 | 44 | PM980.raman = 0; % 0 = exclude raman effect 45 | PM980.ssp = 0; % 0 = disable self sharpen effect 46 | 47 | PM1025 = PM980; 48 | PM1025.Amod = pi*4.97^2; 49 | PM1025.gamma = 2*pi*PM1025.n2/lamda_pulse/PM1025.Amod*1e4; % W^-1 * km^-1 50 | PM1025.betaw = [0 0 20.8634 34.9621e-3]; 51 | 52 | F10125 = PM1025; 53 | F10125.Amod = pi*5.69^2; 54 | F10125.gamma = 2*pi*F10125.n2/lamda_pulse/F10125.Amod*1e4; % W^-1 * km^-1 55 | F10125.betaw = [0 0 20.1814 36.8057e-3]; 56 | % F10125.betaw = [0 0 20.1814]; 57 | 58 | %% YDF10125 59 | YDF10125 = F10125; 60 | YDF10125.Amod = pi*5.69^2; % Mode Field Area (um^2) 61 | YDF10125.gamma = 2*pi*YDF10125.n2/lamda_pulse/YDF10125.Amod*1e4; % W^-1 * km^-1 62 | YDF10125.betaw = [0 0 20.1814 36.8057e-3]; 63 | % YDF10125.betaw = [0 0 20.1814]; 64 | 65 | YDF10125.a = 10; % Core Diameter(um) 66 | YDF10125.b = 125; % Cladding Diameter(um) 67 | YDF10125.absorb_p_0 = 4.8; % Cladding Absorption(dB/m) @lambda_p_0 68 | YDF10125.lambda_p_0 = 976; % Pump lambda of Cladding Absorption(dB/m) 69 | % YDF10125.absorb_s = 0.02; % Core Attenuation(dB/m) 70 | 71 | YDF10125.tf = 0.8e-3; % Upper level life time(s) 72 | 73 | YDF10125.lambda_p = 976; % Pump lambda (nm) 74 | YDF10125.lambda_s = lamda_pulse; % Signal lambda (nm) 75 | 76 | YDF10125 = AmpParaCal(YDF10125,nt,fo,df,c*1e3); % Calculation of other parameters 77 | 78 | amf1 = YDF10125; 79 | amf1.L = 0.001; 80 | sigE_w = GetGuassianSpectrum_w(nt,fo,df,c); 81 | amf1.gain_w = sigE_w/max(sigE_w(:)); 82 | amf1.pump_power = pump_power; % pump power (W) 83 | 84 | [gssdb,PsatdBm ] = EqualAmpSimpPara(amf1,amf1.pump_power) 85 | -------------------------------------------------------------------------------- /SimMolFil/Amplifier/AmpStable/TEST/AmpStableMain.m: -------------------------------------------------------------------------------- 1 | %% General Parameters 2 | c = 299792458; % speed of light (m/s) 3 | h = 6.626e-34; % Planck Constant (J/s) 4 | 5 | %% Active Fiber Parameters 6 | % From Manufacturer DataSheet 7 | YDF10125.a = 5.5; % Core Diameter(um) 8 | YDF10125.b = 125; % Cladding Diameter(um) 9 | YDF10125.absorb_p_0 = 4.8; % Cladding Absorption(dB/m) @lambda_p_0 10 | YDF10125.lambda_p_0 = 976; % Pump lambda of Cladding Absorption(dB/m) 11 | YDF10125.absorb_s = 0.02; % Core Attenuation(dB/m) 12 | 13 | YDF10125.tf = 0.8e-3; % Upper level life time(s) 14 | 15 | YDF10125.lambda_p = 976; % Pump lambda (nm) 16 | YDF10125.lambda_s = 1030; % Signal lambda (nm) 17 | 18 | % Calculation 19 | YDF10125.Aeff = pi*YDF10125.a^2; % Effective Area (doped) (um^2) 20 | YDF10125.Amod = pi*5.25^2; % Mode Field Area (um^2) 21 | YDF10125.Gamma_s = YDF10125.Amod/YDF10125.Aeff; % Confinement Factor for signal 22 | YDF10125.Gamma_p = (YDF10125.a/YDF10125.b)^2; % Confinement Factor for pump 23 | 24 | % Get Emission and Absorbtion Cross Section of Pump and Signal Light 25 | [sigA,sigE,~] = GetYbSpectrum([YDF10125.lambda_p,YDF10125.lambda_s]); 26 | YDF10125.sigE_p = sigE(1); 27 | YDF10125.sigA_p = sigA(1); 28 | YDF10125.sigE_s = sigE(2); 29 | YDF10125.sigA_s = sigA(2); 30 | 31 | % Calculate Absorption Coefficient @lambda_p 32 | % Dopant Concentration (m^-3) 33 | k0 = 4.343; % Constant, See 10.1364/OE.24.009237 34 | YDF10125.dopN = YDF10125.absorb_p_0/k0/GetYbSpectrum(976)/YDF10125.Gamma_p; 35 | YDF10125.absorb_p = k0*YDF10125.dopN*YDF10125.Gamma_p*YDF10125.sigA_p; 36 | % Fit Well with the Manufacturer Data 1.6 dB/m @915 nm 37 | 38 | % Calculate Intrinsic and Cross Saturation Power 39 | YDF10125.P_IS_p = YDF10125.Aeff*1e-12/YDF10125.Gamma_p/YDF10125.tf/... 40 | (YDF10125.sigA_p+YDF10125.sigE_p)*h*c/(YDF10125.lambda_p*1e-9); 41 | YDF10125.P_CS_p = YDF10125.P_IS_p; 42 | YDF10125.P_IS_s = YDF10125.Aeff*1e-12/YDF10125.Gamma_s/YDF10125.tf/... 43 | (YDF10125.sigA_s+YDF10125.sigE_s)*h*c/(YDF10125.lambda_s*1e-9); 44 | YDF10125.P_CS_s = YDF10125.P_IS_s; 45 | 46 | P_pump = 10; % W 47 | P_signal = 0.001; % W 48 | Z = 4; % m 49 | 50 | % AmpEquation = @(P,S)([P-P_pump*exp(-10^(-YDF10125.absorb_p/10)*Z+(P_pump-P)... 51 | % /YDF10125.P_IS_p+(P_signal-S)/YDF10125.P_CS_p);... 52 | % S-P_signal*exp(-10^(-YDF10125.absorb_s/10)*Z+(P_signal-S)... 53 | % /YDF10125.P_IS_s+(P_pump-P)/YDF10125.P_CS_s)]); 54 | % AmpEquation = @(X)(AmpEquation(X(1),X(2))); 55 | AmpEquation = @(P,S)([P-P_pump*exp(10^(-YDF10125.absorb_p/10)*Z+(P_pump-P)... 56 | /YDF10125.P_IS_p-(P_signal-S)/YDF10125.P_CS_p);... 57 | S-P_signal*exp(-10^(-YDF10125.absorb_s/10)*Z+(P_signal-S)... 58 | /YDF10125.P_IS_s-(P_pump-P)/YDF10125.P_CS_s)]); 59 | AmpEquation = @(X)(AmpEquation(X(1),X(2))); 60 | 61 | Options = optimoptions('fsolve'); 62 | Options.Display = 'none'; 63 | if Z<1e-5 64 | Options.TolFun = 1e-6*Z/1e-5; 65 | Options.TolX = Options.TolFun; 66 | end 67 | [P,fval,exitflag] = fsolve(AmpEquation,[P_pump,P_signal],Options); 68 | P_pump_z = P(1); 69 | P_signal_z = P(2); 70 | g = log(P_signal_z/P_signal)/Z; % m^-1 71 | 72 | [gain,~,P_p_z,P_s_z] = AmpGain(YDF10125,P_pump,P_signal,Z,'forward') 73 | 74 | 75 | [gain,~,P_p_0,P_s_z] = AmpTBV(YDF10125,P_p_z,P_signal,Z); 76 | % AmpEquation = @(P_pump,S)([P_p_z-P_pump*exp(10^(-YDF10125.absorb_p/10)*Z+(P_pump-P_p_z)... 77 | % /YDF10125.P_IS_p-(P_signal-S)/YDF10125.P_CS_p);... 78 | % S-P_signal*exp(-10^(-YDF10125.absorb_s/10)*Z+(P_signal-S)... 79 | % /YDF10125.P_IS_s-(P_pump-P_p_z)/YDF10125.P_CS_s)]); 80 | % AmpEquation = @(X)(AmpEquation(X(1),X(2))); 81 | % 82 | % Options = optimoptions('fsolve'); 83 | % Options.Display = 'none'; 84 | % if Z<1e-5 85 | % Options.TolFun = 1e-6*Z/1e-5; 86 | % Options.TolX = Options.TolFun; 87 | % end 88 | % [P,fval,exitflag] = fsolve(AmpEquation,[P_p_z,P_signal],Options); 89 | % 90 | % P_pump = P(1) 91 | % P_signal_z = P(2) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SimMoLFil 2 | A **Mode-Locked Fiber Laser (MoLFil)** simulator. 3 | 4 | ## General info 5 | This project simulates pulses generation and evolution in mode-locke fiber lasers. 6 | The pulse evolution in fiber is calcuated by solving GNLSE using Interaction Picture Method Algorithm [[1](https://ieeexplore.ieee.org/abstract/document/6153336)]. 7 | The [original codes](https://github.com/SeveNOlogy7/SimMoLFil/tree/e5cd7787960a503ebab0ab7e6fc6a859b3413667) of this project were written for this paper [[2](https://www.osapublishing.org/oe/abstract.cfm?uri=oe-25-4-4414)], which contains only a minimum amount of the whole codes used. 8 | 9 | The project is currently under development. 10 | 11 | ## Technologies 12 | The project is created with: 13 | * MATLAB version: 2018b 14 | 15 | ## Examples 16 | mainP1.m: run a simulation and produce results of Point 1 of Figure 2 in [[2](https://www.osapublishing.org/oe/abstract.cfm?uri=oe-25-4-4414)]. 17 | 18 | ## Works in progress 19 | A simple data flow graph (DFG) presentation of Mode-Locked Fiber Laser Models to seperate 20 | layout and connection of optical components from their implementation. 21 | 22 | A DFG presentation can be built into some evaluatable object by a Builder. 23 | 24 | Imaging you can simply write somthing like 25 | ```MATLAB 26 | model = defind some model use DFG 27 | evaluaion = model.build(Some Builder) 28 | evaluaion(Some simulation settings) 29 | ``` 30 | 31 | In this way, it is easy to evaluate a same model with 32 | * different simulation settings (more points, fine step, etc.), 33 | * different algorithms to simulate some specific kind of optical components (better gain model, multimode pulse simulation, etc.), 34 | * and even tools written in other language. 35 | 36 | All these can be done by adding a new Builder class to generate the evaluatable. 37 | 38 | Also, it turns out to be clear that, the idea of DFG presentation is not only suitable for Mode-locked fiber laser models, but also for Cascaded Fiber Supercontinuum Generation models. 39 | 40 | ### Examples of current DFG design 41 | Following are codes that generate a Cascaded Fiber Supercontinuum model. 42 | 43 | ```MATLAB 44 | % Define a fiber component 45 | fiber = component.Fiber(); 46 | 47 | % Create some "Node"s that performs Fiber operation 48 | % SMF stands for single mode fiber 49 | SMF1 = simulation.Fiber("SMF1", fiber); 50 | SMF2 = simulation.Fiber("SMF2", fiber); 51 | SMF3 = simulation.Fiber("SMF3", fiber); 52 | 53 | % Create a input Node 54 | In = simulation.Input("In"); 55 | 56 | % Now simply put the Nodes together 57 | % Think it like: 58 | % Out = In -> SMF1 -> SMF2 -> SMF3 59 | % It is injecting a input (like a powerful laser pulse) through three cascaded fiber sections 60 | % No "->" operator in Matlab, so it end up like this 61 | Out = In + SMF1 + SMF2 + SMF3; 62 | 63 | % Generate some human-readable statement presentation of the model 64 | statements = Out.statements() 65 | ``` 66 | 67 | The statements will contain a multiline string: 68 | ```MATLAB 69 | t0 = In.Input() 70 | t1 = SMF1.Fiber[fiber=component.Fiber](t0) 71 | t2 = SMF2.Fiber[fiber=component.Fiber](t1) 72 | t3 = SMF3.Fiber[fiber=component.Fiber](t2) 73 | ``` 74 | 75 | These staments show what any builders of the DFG model should implement to make the DFG an evaluable. 76 | 77 | ### Codes Arrangement 78 | * **simulation package** contains codes that help reuse a few MATLAB syntax to present a MoLFil Model in DFG 79 | and simply build the MoLFil Model to 80 | * Human readable statements 81 | * Evaluation object, given a specific Builder implementation 82 | 83 | * **component package** contains optical components packed in classes. 84 | And some helper methods to calculate parameters for those components. 85 | 86 | ### Todos 87 | - [x] DFG generation 88 | - [x] DFG build process 89 | - [x] A pure MATLAB Builder implementation using existing codes in SimMLFL 90 | - [x] DFG Evaluation Class 91 | - [x] flow control operations 92 | - [ ] Fill component package with concrete classes 93 | - [x] components need for F8L 94 | - [ ] more components 95 | - [ ] Docs 96 | - [ ] Examples 97 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Operation.m: -------------------------------------------------------------------------------- 1 | classdef Operation 2 | %OPERATION A class to handle operations required by a simulation model 3 | % Operation is a abstraction of components/input/output/flow control 4 | % of a simulation model. Each node (which is presented by Model) 5 | % contains a specific form of Operation. 6 | 7 | properties (Access = private) 8 | name 9 | op_type 10 | num_args 11 | parameters 12 | end 13 | 14 | methods 15 | function obj = Operation(name, op_type, num_args, parameters) 16 | %OPERATION Construct an instance of this class 17 | obj.name = name; 18 | obj.op_type = op_type; 19 | obj.num_args = num_args; 20 | obj.parameters = parameters; 21 | end 22 | 23 | % overload subsref, make operation object callable 24 | % also handle 1d array sub reference 25 | function m = subsref(obj,S) 26 | import simulation.* 27 | % overload only single subsref, chained subsref uses built-in 28 | if length(S)==1 && S.type == "()" 29 | if length(S.subs) == 1 && isa(S.subs{:},"double") 30 | % Operation_obj_array(ii) 31 | % This is just a normal 1d array subsref 32 | % use builtin subsref here 33 | m = builtin('subsref',obj,S); 34 | else 35 | if length(obj) == 1 36 | % Operation_obj(cell_array of Models) 37 | % Call a single Operation object 38 | % Check arguments numbers 39 | if obj.num_args >=0 && obj.num_args ~= length(S.subs) 40 | error("%s: need %d arguments but found %d\n", obj.name, obj.num_args, length(S.subs)); 41 | end 42 | % Check argument types 43 | if ~all(cellfun(@(c) isa(c,"simulation.Model"),S.subs)) 44 | error("%s: need simulation.Model arguments\n", obj.name); 45 | end 46 | % S.subs contains only Model objects now 47 | % s = cellfun(@char,S.subs); 48 | % disp(sprintf("You called %s with argument: ", obj.name) + join(s,",")); 49 | if obj.op_type == "Feedback" 50 | % Special Type check for Feedback 51 | L_operand_type = S.subs{1}.get_op_type(); 52 | if L_operand_type ~= "Recurrence" 53 | error("Feedback need Reccurence type input\n"); 54 | end 55 | % t = Feedback(l,r) 56 | m = Model(Operation(S.subs{1}.get_op_name(),"Feedback",2,... 57 | struct()),[S.subs{:}]); 58 | else 59 | m = Model(obj,[S.subs{:}]); 60 | end 61 | end 62 | end 63 | else 64 | % Everything else just use builtin for now 65 | m = builtin('subsref',obj,S); 66 | end 67 | end 68 | 69 | function disp(obj) 70 | disp(char(obj)); 71 | end 72 | 73 | function s = char(obj) 74 | if length(obj) == 1 75 | % convert a object to string 76 | s = obj.name+"."+obj.op_type; 77 | if isempty(fieldnames(obj.parameters)) 78 | return 79 | end 80 | % put in parameters 81 | parameter_names = fieldnames(obj.parameters); 82 | params = strings(length(parameter_names),1); 83 | for ii = 1:length(parameter_names) 84 | param = obj.parameters.(parameter_names{ii}); 85 | if length(param) == 1 && isa(param,"double") || isa(param,"string") 86 | params(ii) = parameter_names{ii}+"="+param; 87 | else 88 | params(ii) = parameter_names{ii}+"="+class(param); 89 | end 90 | 91 | end 92 | params = join(params,","); 93 | s = sprintf("%s[%s]",s,params); 94 | else 95 | % convert 1d array of objects to string 96 | s = strings(length(obj),1); 97 | for ii = 1:length(obj) 98 | s(ii) = char(obj(ii)); 99 | end 100 | s = join(s,newline); 101 | end 102 | end 103 | 104 | end 105 | end 106 | 107 | -------------------------------------------------------------------------------- /SimMolFil/GNLSE/Solver/IP_CQEM_FD.m: -------------------------------------------------------------------------------- 1 | function [u1,nf,Plotdata] = IP_CQEM_FD(u0,dt,dz,mod,fo,tol,dplot,quiet) 2 | % This function solves the Generalized Nonlinear Schrodinger Equation with 3 | % the complete Raman response for pulse propagation in an optical fiber 4 | % using the Interaction Picture Method in combination with the Conserved 5 | % Quantity Error method for the step-size determination and the frequency 6 | % domain integration of the nonlinear operator 7 | % 8 | % INPUT 9 | % 10 | % u0 - starting field amplitude (vector) 11 | % dt - time step 12 | % dz - initial step size 13 | % mod - propogation module parameters field 14 | % mod.L - propagation distance 15 | % mod.alpha - power loss coefficient, ie, P=P0*exp(-alpha*z) 16 | % mod.betap - dispersion polynomial coefs, [beta_0 ... beta_m], or beta(w) 17 | % - the coefs are Tylor expansion at the central frequency fo 18 | % mod.gamma - nonlinearity coefficient 19 | % fo - central frequency of the simulation (THz) 20 | % tol - relative photon error 21 | % dplot - if set to 1, Plot data will be packed 22 | % 23 | % OUTPUT 24 | % 25 | % u1 - field at the output 26 | % nf - number of FFTs performed 27 | 28 | nt = length(u0); % number of sample points 29 | w = fftshift(2*pi*(-nt/2:nt/2-1)/(dt*nt)); % angular frequencies (fftshifted) 30 | t = (-nt/2:1:nt/2-1)*dt; % vector temporal (in ps) 31 | df = 1/(nt*dt); 32 | f=-(nt/2)*df:df:(nt/2-1)*df; % frequencies vector (in THz) 33 | 34 | % calculate the raman response fuction of frequency domain 35 | [hrw,fr] = Raman_response_w(t,mod); 36 | 37 | % preparation before the IPM 38 | ufft = fft(u0); 39 | propagedlength = 0; 40 | u1 = u0; 41 | nf = 1; 42 | 43 | if isfield(mod,'gssdB') || isprop(mod,'gssdB') 44 | if isfield(mod,'gain_w')|| isprop(mod,'gain_w') 45 | gain_w = mod.gain_w; 46 | else 47 | gain_w = filter_lorentz_tf(u1,mod.fbw,mod.fc,fo,1/dt/nt); 48 | end 49 | alpha_0 = mod.alpha; 50 | end 51 | LOP_0 = Linearoperator_w(mod.alpha,mod.betaw,w); 52 | 53 | if dplot ==1 54 | dz_all = zeros(100,1); 55 | z_all = dz_all; 56 | ufft_z = zeros(100,nt); 57 | u_z = ufft_z; 58 | end 59 | 60 | % Performig the IPM *********************************************** 61 | if ~quiet 62 | fprintf(1, '\nSimulation running... '); 63 | end 64 | 65 | count = 0; 66 | while propagedlength < mod.L 67 | 68 | if (dz + propagedlength) > mod.L 69 | dz = mod.L - propagedlength; 70 | end 71 | 72 | % (re)constructing linear operator 73 | if isfield(mod,'gssdB')|| isprop(mod,'gssdB') 74 | % modify alpha to include saturated gain and gain spectral 75 | % Pin0 = (sum(u1.*conj(u1))*nt); 76 | Pin0 = (sum(u1.*conj(u1))*dt)*mod.RepeatFre*1e-12; 77 | % Pin0 = (sum(u1.*conj(u1)))*mod.RepeatFre*1e-12; 78 | if isfield(mod,'pump_power')|| isprop(mod,'pump_power') 79 | if ~exist('pump_power_t','var') 80 | pump_power_t = mod.pump_power; 81 | end 82 | [gain,~,pump_power_t,~ ] = AmpGain( mod,pump_power_t,Pin0,dz*1e-3,'forward'); 83 | if gain_w == 0 84 | gain_w = AmpGainWCal(mod, gain,dz); % need normorlisation 85 | gain_s = interp1(f+fo,gain_w,mod.freq_s,'linear'); 86 | gain_w(gain_w>0) = gain.*gain_w(gain_w>0)/abs(gain_s); % gain section using amplifier model, with normorlisation 87 | gain_w(gain_w<=0) = -(1-10.^((mod.k0*mod.dopN*mod.Gamma_s.*gain_w(gain_w<=0))/10))*1e3; % loss section 88 | gain = gain_w; 89 | else 90 | gain = gain.*gain_w; 91 | end 92 | else 93 | gain = gain_saturated2(Pin0,mod.gssdB,mod.PsatdBm).*gain_w; 94 | end 95 | mod.alpha = alpha_0-gain; 96 | LOP = LOP_0 + fftshift(gain/2); % fftshift 97 | elseif ~exist('LOP','var') || isempty(LOP) 98 | % In passive fiber, only calculate LOP once 99 | LOP = LOP_0; 100 | end 101 | 102 | % Calculate the real phonton number before and after dz propogation 103 | % neglect the frequency dependant of S(w) of the equation (14) in 104 | % "Efficient Adaptive Step Size Method for the Simulation of 105 | % Supercontinuum Generation in Optical Fibers" 106 | % (Instead of calculating the partial differential of PN in (14), 107 | % here we derectly calculate PN(z)) 108 | % PhotonN = sum((abs(ufft).^2)./(w + 2*pi*fo)); 109 | PhotonN_z = abs(sum(exp(-dz*fftshift(mod.alpha)).* ufft.*conj(ufft)./(w + 2*pi*fo))); 110 | 111 | % Applying the Runge-Kutta method in the interaction picture 112 | % Implement equations (5) in the "Optimum Integration Procedures for Supercontinuum Simulation" 113 | halfstep = exp(dz/2*LOP); 114 | uip = halfstep.*ufft; % calculate A in interaction picture 115 | k1 = halfstep*dz.*NonLinearoperator_w(u1,mod.gamma,w,fo,fr,hrw,dt,mod); 116 | 117 | uhalf2 = ifft(uip + k1/2); 118 | k2 = dz*NonLinearoperator_w(uhalf2,mod.gamma,w,fo,fr,hrw,dt,mod); 119 | 120 | uhalf3 = ifft(uip + k2/2); 121 | k3 = dz*NonLinearoperator_w(uhalf3,mod.gamma,w,fo,fr,hrw,dt,mod); 122 | 123 | uhalf4 = ifft(halfstep.*(uip + k3)); 124 | k4 = dz*NonLinearoperator_w(uhalf4,mod.gamma,w,fo,fr,hrw,dt,mod); 125 | 126 | uaux = halfstep.*(uip + k1./6 + k2./3 + k3./3) + k4./6; 127 | 128 | propagedlength = propagedlength + dz; 129 | 130 | if ~quiet 131 | fprintf(1, '\b\b\b\b\b\b%5.2f%%', propagedlength * 100.0 /mod.L ); 132 | end 133 | 134 | % set dz for the next step 135 | error = abs(sum(uaux.*conj(uaux)./(w+2*pi*fo))-PhotonN_z)/PhotonN_z; 136 | if error > 2 * tol 137 | % error exceeds the double of tolerance, discard this calculation 138 | % and roll back 139 | propagedlength = propagedlength - dz; 140 | dz = dz/2; % reduce the step size by half 141 | else 142 | % accept this step and optimise the next step size 143 | ufft = uaux; 144 | u1 = ifft(ufft); 145 | if error > tol 146 | % error exceeds tolerance, reduce step size 147 | dz = dz/(2^0.2); 148 | else 149 | % error is too small, increase step size to accelerate 150 | % change the factor from 0.1 to 0.5 to accelerate. Now both the 151 | % speed and precision are mainly controled by tolerance 152 | if error < 0.5*tol 153 | dz = dz*(2^0.2); 154 | end 155 | end 156 | count = count +1; 157 | 158 | if dplot ==1 159 | % save the plot of this step 160 | if count>size(dz_all,1) 161 | temp = zeros(100,1); % buffered auto grow method to save time 162 | dz_all = [dz_all;temp]; %#ok 163 | z_all = [z_all;temp]; %#ok 164 | end 165 | if count>size(ufft_z,1) 166 | temp = zeros(200,nt); 167 | ufft_z = [ufft_z;temp]; %#ok 168 | u_z = [u_z;temp]; %#ok 169 | end 170 | dz_all(count) = dz; 171 | z_all(count) = propagedlength; 172 | ufft_z(count,:) = ufft; 173 | u_z(count,:) = u1; 174 | end 175 | end 176 | 177 | nf = nf + 16; 178 | end 179 | 180 | % pack the output struct 181 | if dplot ==1 182 | Plotdata.dz = dz_all(1:count); 183 | Plotdata.z = z_all(1:count); 184 | Plotdata.ufft = abs(fftshift(ufft_z(1:count,:),2)); 185 | Plotdata.u = u_z(1:count,:); 186 | else 187 | Plotdata = []; 188 | end 189 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/Model.m: -------------------------------------------------------------------------------- 1 | classdef Model 2 | %MODEL A class to handle model information as a data flow graph(DFG) 3 | % A DFG is a graph that present complex data flow as nodes and 4 | % directed edges. Each node has input and output, and performs some 5 | % operation. Use DFG to describle a simulation model. This class aims 6 | % to construct a DFG presentation of a model using some MATLAB 7 | % build-in arithmatic operators. 8 | % 9 | % Technically, a node is a smallest model unit. A full model is a 10 | % combination of model units, hence a DFG. For any node in the model, 11 | % call statements to display the generating DFG for that node, which 12 | % is basicly a sub-model. A DFG is displayed in multilines of texts 13 | % each presents a single operation. 14 | % 15 | % Here is an example: 16 | % fiber = component.Fiber(); % Define fiber component 17 | % SMF1 = simulation.Fiber("SMF1", fiber) % Operation of node SMF1 18 | % SMF2 = simulation.Fiber("SMF2", fiber) % Operation of node SMF2 19 | % SMF3 = simulation.Fiber("SMF3", fiber) % Operation of node SMF3 20 | % In = simulation.Input("In") % A node(Model) that asks for input 21 | % Out = In + SMF1 + SMF2 + SMF3; % An output defined using + 22 | % Simulation = Out.statements() % Print the DFG 23 | % This example shows how to constuct a model that cascades 3 sections 24 | % of optical fiber. 25 | % 26 | % output of the statements function. 27 | % t0 = In.Input() 28 | % t1 = SMF1.Fiber[fiber=component.Fiber](t0) 29 | % t2 = SMF2.Fiber[fiber=component.Fiber](t1) 30 | % t3 = SMF3.Fiber[fiber=component.Fiber](t2) 31 | % 32 | % See unittests for more examples 33 | 34 | properties (Access = private) 35 | operation 36 | inputs 37 | id 38 | end 39 | 40 | methods 41 | function obj = Model(operation, inputs) 42 | %MODEL Construct an instance of this class 43 | % Detailed explanation goes here 44 | if nargin == 0 45 | error("No Default Constructor in Model Class"); 46 | elseif nargin == 1 47 | obj = simulation.Model.promote(operation); 48 | if isempty(obj) 49 | error("No Compatible Convesion Constructor in Model Class"); 50 | end 51 | return 52 | elseif nargin > 2 53 | error("Too Many parameters for Constructor in Model Class") 54 | end 55 | 56 | % Check Type 57 | if ~isa(operation,'simulation.Operation') 58 | error("Type error: 'operation' need type simulation.Operation, get %s",class(operation)); 59 | end 60 | if ~isempty(inputs) && ~isa(inputs,'simulation.Model') 61 | error("Type error: 'inputs' need type simulation.Model, get %s",class(inputs)); 62 | end 63 | 64 | persistent next_id; 65 | if isempty(next_id) 66 | next_id = 0; 67 | end 68 | obj.operation = operation; 69 | obj.inputs = inputs; 70 | obj.id = next_id; 71 | next_id = next_id + 1; 72 | end 73 | 74 | function s = statements(obj) 75 | %STATEMENTS convert an model into readable statement 76 | % each statement corresponds to a node in the DFG 77 | lines = string([]); 78 | function visitor(o) 79 | lines = [lines, char(o)]; 80 | end 81 | obj.depth_first_search({},@visitor); 82 | s = join(lines,newline); 83 | end 84 | 85 | function varargout = plus(a,b) 86 | %PLUS Overload operator+ 87 | % This overloads operator+ so that a expression like 88 | % Model+Operation will perform Operation on a Model 89 | % output. Ideally an operator like -> looks better. 90 | % But no operator -> in matlab, use + instead. 91 | % Model->Operation 92 | if ~(isa(a,"simulation.Model") || isa(b,"simulation.Operation")) 93 | error("Model: plus got imcompatible input type(s)"); 94 | end 95 | for ii = 1:length(b) 96 | op = b(ii); 97 | inputs = cell(a); 98 | varargout{ii} = op(inputs{:}); 99 | end 100 | end 101 | 102 | function eval = build(obj, builder) 103 | %BUILD convert an model into evaluation 104 | function visitor(o) 105 | builder.append(o); 106 | end 107 | obj.depth_first_search({}, @visitor); 108 | eval = builder.build(); 109 | end 110 | 111 | % overload cell call 112 | function c = cell(obj) 113 | c = cell(1,length(obj)); 114 | for ii = 1:length(obj) 115 | c{ii} = obj(ii); 116 | end 117 | end 118 | 119 | function disp(obj) 120 | disp(char(obj)); 121 | end 122 | 123 | function s = char(obj) 124 | if length(obj) == 1 125 | args = strings(length(obj.inputs),1); 126 | for ii = 1:length(obj.inputs) 127 | args(ii) = sprintf("t%d", obj.inputs(ii).id); 128 | end 129 | if isempty(args) 130 | args = ""; 131 | else 132 | args = join(args,","); 133 | end 134 | s = sprintf("t%d = %s(%s)",obj.id, char(obj.operation),args); 135 | else 136 | % convert 1d array of objects to string 137 | s = strings(length(obj),1); 138 | for ii = 1:length(obj) 139 | s(ii) = char(obj(ii)); 140 | end 141 | s = join(s,newline); 142 | end 143 | end 144 | 145 | % getters 146 | function id = get_id(obj) 147 | id = obj.id; 148 | end 149 | function op = get_operation(obj) 150 | op = obj.operation; 151 | end 152 | 153 | function op_type = get_op_type(obj) 154 | op_type = obj.operation.op_type; 155 | end 156 | 157 | function op_name = get_op_name(obj) 158 | op_name = obj.operation.name; 159 | end 160 | 161 | function t = get_inputs_id(obj) 162 | t = zeros(1,length(obj.inputs)); 163 | for ii = 1:length(t) 164 | t(ii) = obj.inputs(ii).id; % (0:) not MATLAB convention 165 | end 166 | end 167 | 168 | % setters 169 | function obj = set_inputs(obj, inputs) 170 | if ~isempty(inputs) && ~isa(inputs,'simulation.Model') 171 | error("Type error: 'inputs' need type simulation.Model, get %s",class(inputs)); 172 | end 173 | obj.inputs = inputs; 174 | end 175 | end 176 | 177 | methods (Access = private) 178 | function depth_first_search(obj, ids, visitor) 179 | % ids: Map(id, visited?) 180 | % visitor: function(obj) 181 | if isempty(ids) 182 | ids = containers.Map(obj.id, false); 183 | else 184 | ids(obj.id) = true; 185 | end 186 | for ii = 1: length(obj.inputs) 187 | if isKey(ids,obj.inputs(ii).id) 188 | continue 189 | end 190 | obj.inputs(ii).depth_first_search(ids, visitor) 191 | end 192 | visitor(obj); 193 | end 194 | end 195 | 196 | methods (Static) 197 | function p = promote(r) 198 | if isa(r,"simulation.Model") 199 | p = r; 200 | elseif isa(r,"double") 201 | p = simulation.Const(r); 202 | end 203 | end 204 | end 205 | end 206 | 207 | -------------------------------------------------------------------------------- /SimMolFil/unittests/DFGTest.m: -------------------------------------------------------------------------------- 1 | classdef DFGTest < matlab.unittest.TestCase 2 | %DFGTEST Summary of this class goes here 3 | % Detailed explanation goes here 4 | methods(TestMethodSetup) 5 | function createFixture(testCase) 6 | function clearModel() 7 | clear Model 8 | end 9 | testCase.addTeardown(@clearModel); 10 | end 11 | end 12 | 13 | methods (Test) 14 | function testSingleFiber(testCase) 15 | % disp, char, + should all work in this test 16 | fiber = component.Fiber(); 17 | SMF = simulation.Fiber("SMF", fiber) 18 | In = simulation.Input("In") 19 | Out = In + SMF; 20 | statements = Out.statements() 21 | testCase.verifyEqual(statements,... 22 | join(["t0 = In.Input()",... 23 | "t1 = SMF.Fiber[fiber=component.Fiber](t0)"],newline)); 24 | end 25 | 26 | function testMultipleFiber(testCase) 27 | createFixture(testCase); 28 | fiber = component.Fiber(); 29 | SMF1 = simulation.Fiber("SMF1", fiber); 30 | SMF2 = simulation.Fiber("SMF2", fiber); 31 | SMF3 = simulation.Fiber("SMF3", fiber); 32 | In = simulation.Input("In"); 33 | Out = In + SMF1 + SMF2 + SMF3; 34 | statements = Out.statements() 35 | testCase.verifyEqual(statements,... 36 | join(["t0 = In.Input()",... 37 | "t1 = SMF1.Fiber[fiber=component.Fiber](t0)",... 38 | "t2 = SMF2.Fiber[fiber=component.Fiber](t1)",... 39 | "t3 = SMF3.Fiber[fiber=component.Fiber](t2)"],newline)); 40 | end 41 | 42 | function testCoupler(testCase) 43 | % Test Coupler model 44 | createFixture(testCase); 45 | coupler = component.Coupler(0.5); 46 | In1 = simulation.Input("In1"); 47 | In2 = simulation.Input("In2"); 48 | OC = simulation.Coupler("OC", coupler); 49 | 50 | % cell() is overloaded here, the warning here can be neglected 51 | [Out1,Out2] = [In1, In2] + OC; 52 | 53 | statements1 = Out1.statements() 54 | statements2 = Out2.statements() 55 | testCase.verifyEqual(statements1,... 56 | join(["t0 = In1.Input()",... 57 | "t1 = In2.Input()",... 58 | "t2 = OC.CouplerOut1[coupler=component.Coupler](t0,t1)"],newline)); 59 | testCase.verifyEqual(statements2,... 60 | join(["t0 = In1.Input()",... 61 | "t1 = In2.Input()",... 62 | "t3 = OC.CouplerOut2[coupler=component.Coupler](t0,t1)"],newline)); 63 | end 64 | 65 | function testNOLM(testCase) 66 | % Test Creation of a NOLM model 67 | createFixture(testCase); 68 | coupler = component.Coupler(0.5); 69 | fiber = component.Fiber(); 70 | SMF = simulation.Fiber("SMF1", fiber); 71 | In = simulation.Input("In"); 72 | OC = simulation.Coupler("OC", coupler); 73 | [u1,u2] = [In, 0] + OC; 74 | u3 = u1 + SMF; 75 | u4 = u2 + SMF; 76 | [~, Out] = [u3, u4] + OC; 77 | statements = Out.statements() 78 | testCase.verifyEqual(statements,... 79 | join(["t0 = In.Input()",... 80 | "t1 = .Const[value=0]()",... 81 | "t2 = OC.CouplerOut1[coupler=component.Coupler](t0,t1)",... 82 | "t4 = SMF1.Fiber[fiber=component.Fiber](t2)",... 83 | "t3 = OC.CouplerOut2[coupler=component.Coupler](t0,t1)",... 84 | "t5 = SMF1.Fiber[fiber=component.Fiber](t3)",... 85 | "t7 = OC.CouplerOut2[coupler=component.Coupler](t4,t5)"],newline)); 86 | end 87 | 88 | function testShow(testCase) 89 | createFixture(testCase); 90 | In = simulation.Input("In"); 91 | show = simulation.Show(struct("plotter",@plot_model)); 92 | In = show(In); % It is fine to write like this 93 | statements1 = In.statements() 94 | testCase.verifyEqual(statements1,... 95 | join(["t0 = In.Input()",... 96 | "t1 = .Show[plotter=function_handle](t0)",],newline)); 97 | 98 | In = simulation.Input("In"); 99 | Out = show(In); % It is better to write like this 100 | statements2 = Out.statements() 101 | testCase.verifyEqual(statements2,... 102 | join(["t2 = In.Input()",... 103 | "t3 = .Show[plotter=function_handle](t2)",],newline)); 104 | 105 | % In->SMF->Show->Out 106 | In = simulation.Input("In"); 107 | fiber = component.Fiber(); 108 | SMF = simulation.Fiber("SMF", fiber); 109 | SMF = simulation.Fiber("SMF", fiber); 110 | Out = show(In+SMF); 111 | statements3 = Out.statements() 112 | testCase.verifyEqual(statements3,... 113 | join(["t4 = In.Input()",... 114 | "t5 = SMF.Fiber[fiber=component.Fiber](t4)",... 115 | "t6 = .Show[plotter=function_handle](t5)"],newline)); 116 | end 117 | 118 | function testRecuurence(testCase) 119 | createFixture(testCase); 120 | 121 | coupler = component.Coupler(0.5); 122 | fiber = component.Fiber(); 123 | 124 | SMF = simulation.Fiber("SMF", fiber); 125 | OC = simulation.Coupler("OC", coupler); 126 | 127 | feedback = simulation.Feedback(); 128 | 129 | In = simulation.Input("In"); 130 | u = simulation.Recurrence("u",In,"Run_until_stop"); 131 | [u1, ~] = [u, 0] + OC; 132 | t = feedback(u,u1); 133 | 134 | % use the latest model to see the whole statements 135 | statements = t.statements() 136 | testCase.verifyEqual(statements,... 137 | join(["t0 = In.Input()",... 138 | "t1 = u.Recurrence[condition=Run_until_stop](t0)",... 139 | "t2 = .Const[value=0]()",... 140 | "t3 = OC.CouplerOut1[coupler=component.Coupler](t1,t2)",... 141 | "t5 = u.Feedback(t1,t3)"],newline)); 142 | end 143 | 144 | function testFigure8(testCase) 145 | createFixture(testCase); 146 | 147 | coupler_NOLM = component.Coupler(0.3); 148 | coupler_output = component.Coupler(0.6); 149 | passive_fiber = component.Fiber(); 150 | active_fiber = component.Fiber(); 151 | filter = component.Filter(1030, 1030, 7); 152 | 153 | SMF1 = simulation.Fiber("SMF1", passive_fiber); 154 | SMF2 = simulation.Fiber("SMF2", passive_fiber); 155 | SMF3 = simulation.Fiber("SMF3", passive_fiber); 156 | SMF4 = simulation.Fiber("SMF4", passive_fiber); 157 | SMF5 = simulation.Fiber("SMF5", passive_fiber); 158 | AF = simulation.Fiber("AF", active_fiber); 159 | BPF = simulation.Filter("BPF", filter); 160 | 161 | OC = simulation.Coupler("OC", coupler_output); 162 | Coupler_NOLM = simulation.Coupler("Coupler_NOLM", coupler_NOLM); 163 | 164 | feedback = simulation.Feedback(); 165 | 166 | In = simulation.Input("In"); 167 | u = simulation.Recurrence("u",In,"Run_until_stop"); 168 | u3 = u + SMF1 + AF + SMF2; 169 | [u4, ~] = [u3, 0] + OC; 170 | u5 = u4 + SMF3 + BPF + SMF4; 171 | [u6, u7] = [u5, 0] + Coupler_NOLM; 172 | u8 = u6 + SMF5; 173 | u9 = u7 + SMF5; 174 | [~, u10] = [u8, u9] + Coupler_NOLM; 175 | t = feedback(u,u10); 176 | 177 | % use the latest model to see the whole statements 178 | statements = t.statements() 179 | testCase.verifyEqual(true, true) 180 | end 181 | end 182 | 183 | end 184 | 185 | -------------------------------------------------------------------------------- /Examples/mainP1.m: -------------------------------------------------------------------------------- 1 | % This example reproduces Point 1 in Figure 2 of the following paper: 2 | % Cai, J.-H., Chen, H., Chen, S.-P. & Hou, J. Opt. Express 25, 4414 (2017). 3 | 4 | %% Structural Parameters to investigate 5 | lambda_bw = 11; 6 | smf5_L = 0.025; 7 | NOLM_L = 0.0015; 8 | PsatdBm = 23.5; % use cal_AmpSimpPara.m to calculate from pump power 9 | smf4_L = 0.002; 10 | 11 | %% Simulation Parameter 12 | c = 299792.458; % speed of light nm/ps 13 | lambda_pulse = 1030; % pulse central lambda (nm) 14 | fo=c/lambda_pulse; % central pulse frequency (THz) 15 | 16 | % Numerical Parameters 17 | nt = 2^12; % number of spectral points 18 | time = 120; % ps 19 | dt = time/nt; % ps 20 | t = -time/2:dt:(time/2-dt); % ps 21 | 22 | df=1/(nt*dt); % frequencies separation (Thz) 23 | f=-(nt/2)*df:df:(nt/2-1)*df; % frequencies vector (en THz) 24 | lambda = c./(f + c/lambda_pulse); % lambdas vector (nm) 25 | w = 2*pi*f; % angular frequencies vector (in THz) 26 | dz = 0.00001; % Initial longitudinal step (km) 27 | tol = 1e-7; 28 | N_trip = 300; 29 | 30 | % Some helpful settings 31 | % if set to 1, all figures will be plotted after simulation hence the 32 | % computation time of the last trip would be considerable 33 | plot_all_fig = 1; 34 | reinject_flag = 0; 35 | 36 | %% Set Component Parameters 37 | % Predefine of fiber parameters 38 | PM980.Amod = pi*3.3^2; % Mode Field Area (um^2) (um^2) 39 | PM980.n2 = 2.6; % Kerr coefficient (10^-16*cm^2/W) 40 | PM980.gamma = 2*pi*PM980.n2/lambda_pulse/PM980.Amod*1e4; % W^-1 * km^-1 41 | PM980.alpha = 0; % atenuation coef. (km^-1) 42 | PM980.betaw = [0 0 24.5864 26.1949e-3]; % beta coefficients (ps^n/nm) 43 | 44 | PM980.raman = 0; % 0 = exclude raman effect 45 | PM980.ssp = 0; % 0 = disable self sharpen effect 46 | 47 | PM1025 = PM980; 48 | PM1025.Amod = pi*5^2; 49 | PM1025.gamma = 2*pi*PM1025.n2/lambda_pulse/PM1025.Amod*1e4; % W^-1 * km^-1 50 | PM1025.betaw = [0 0 20.8634 34.9621e-3]; 51 | 52 | F10125 = PM980; 53 | F10125.Amod = pi*5.25^2; 54 | F10125.gamma = 2*pi*F10125.n2/lambda_pulse/F10125.Amod*1e4; % W^-1 * km^-1 55 | F10125.betaw = [0 0 20.1814 36.8057e-3]; 56 | 57 | % smf1 module parameters 58 | NOLM.smf1 = F10125; 59 | NOLM.smf1.L = 0.0007; % fiber length (km) 60 | 61 | % smf2 module parameters 62 | NOLM.smf2 = F10125; 63 | NOLM.smf2.L = NOLM_L-NOLM.smf1.L; 64 | 65 | % smf3 module parameters 66 | smf3 = F10125; 67 | smf3.L = 0.001; 68 | 69 | % smf4 module parameters 70 | smf4 = F10125; 71 | smf4.L = smf4_L; 72 | 73 | % smf5 module parameters 74 | smf5 = F10125; 75 | smf5.L = smf5_L; 76 | 77 | % smf5 module parameters 78 | smf6 = F10125; 79 | smf6.L = 0.001; 80 | 81 | % amf1 module parameters 82 | amf1 = F10125; 83 | amf1.L = 0.0008; 84 | amf1.gssdB = 37.5; % small signal gain coefficient(dB) 85 | amf1.PsatdBm = PsatdBm; % saturation input power(dBm) 86 | 87 | amf1.fbw = c/(1030)^2*80; 88 | amf1.fc = c/1030; 89 | 90 | % filter parameters 91 | filter.lambda_c = 1030; 92 | filter.lambda_bw = lambda_bw; 93 | filter.fc = c/filter.lambda_c; 94 | filter.f3dB = c/(filter.lambda_c)^2*filter.lambda_bw; 95 | filter.n = 7; 96 | 97 | % coupler parameters 98 | NOLM.rho = 0.30; 99 | rho_out = 0.40; % Output ratio = 1-rho_out 100 | PhaseShift = 0; % Nonreciprocal Phase Shift for NOLM 101 | 102 | Length_cavity = smf4.L+smf5.L+amf1.L+NOLM.smf1.L+NOLM.smf2.L; % km 103 | RepeatFre = c/2/Length_cavity; % Hz 104 | amf1.RepeatFre = RepeatFre; 105 | 106 | %% INPUT FIELD 107 | u0 = rand_sech(nt,time); 108 | 109 | if ~reinject_flag 110 | u = u0; 111 | end 112 | 113 | fprintf(1,'\n----------------------------------------------\n'); 114 | fprintf('Input Peak Power (W) = %5.2f\n',max(u0.*conj(u0))); 115 | fprintf('Input Pulse Energy in pJ = %5.2f\n', dt*sum(u0.*conj(u0))); 116 | 117 | %% PROPAGATE finding numerical solution 118 | fprintf('\nLaser Simulation started\n'); 119 | tic 120 | 121 | spec_z = zeros(N_trip,nt); 122 | u_z = spec_z; 123 | 124 | h1 = waitbar( 0,'The program is running...'); 125 | 126 | dplot = 0; 127 | dstop = 0; 128 | dconv = 0; 129 | 130 | for ii = 1:N_trip 131 | if plot_all_fig == 1 && ii == N_trip 132 | dplot = 1; 133 | end 134 | %u->BPF->SMF4->AMF1->SMF5->NOLM->OC->u 135 | u_f = filter_gauss(u,filter.f3dB,filter.fc,filter.n,fo,df); 136 | u = u_f; 137 | 138 | [u,~,Plotdata_smf4] = IP_CQEM_FD(u,dt,dz,smf4,fo,tol,dplot,1); 139 | [u,~,Plotdata_amf1] = IP_CQEM_FD(u,dt,dz,amf1,fo,tol,dplot,0); 140 | [u,~,Plotdata_smf5] = IP_CQEM_FD(u,dt,dz,smf5,fo,tol,dplot,0); 141 | 142 | [uf,ub] = coupler(u,0,NOLM.rho); 143 | % forward light cp1o-smf1-NRPS-smf2-cp2o 144 | [ufo,~,Plotdata_smf1_f] = IP_CQEM_FD(uf,dt,dz,NOLM.smf1,fo,tol,dplot,1); 145 | % ufo = ufo.*exp(1i*PhaseShift); 146 | [ufo,~,Plotdata_smf2_f] = IP_CQEM_FD(ufo,dt,dz,NOLM.smf2,fo,tol,dplot,1); 147 | % forward light cp1o-smf1-NRPS-smf2-cp2o 148 | [ubo,~,Plotdata_smf1] = IP_CQEM_FD(ub,dt,dz,NOLM.smf2,fo,tol,dplot,1); 149 | % ubo = ubo.*exp(-1i*PhaseShift); 150 | [ubo,~,Plotdata_smf2] = IP_CQEM_FD(ubo,dt,dz,NOLM.smf1,fo,tol,dplot,1); 151 | 152 | [ur,ut] = coupler(ubo,ufo,NOLM.rho); 153 | 154 | u = ut; 155 | [u,uout] = coupler(u,0,rho_out); 156 | 157 | %---------plot temporal input and output pulses 158 | figure(1); 159 | plot (t,abs(uout).^2,'r.-');axis tight; 160 | grid on; 161 | xlabel ('t (ps)'); 162 | ylabel ('|u(z,t)|^2 (W)'); 163 | title ('Pulse Shape'); 164 | %---------plot output spectrum------------------ 165 | spec = fftshift(fft(uout)); 166 | specnorm = spec.*conj(spec); 167 | specnorm = specnorm/max(specnorm); 168 | figure(3) 169 | plot(c./(f + fo),specnorm,'r.-');axis tight; 170 | grid on; 171 | xlabel ('lambda (nm)'); 172 | ylabel ('Normalized Spectrum (a.u.)'); 173 | title ('Output Spectrum'); 174 | 175 | spec_z(ii,:) = specnorm; 176 | u_z(ii,:) = uout; 177 | 178 | if dstop 179 | break; 180 | end 181 | 182 | % Close the waitbar manually, the simulation will end 183 | try 184 | waitbar( ii/N_trip,h1,sprintf('The program is running...%d/%d',ii,N_trip)); 185 | catch err 186 | if strcmp(err.identifier,'MATLAB:waitbar:InvalidSecondInput') 187 | fprintf('\nSimulation is going to be terminated\n'); 188 | else 189 | fprintf(err.message); 190 | end 191 | if plot_all_fig ==1 % if figures are required 192 | dstop = 1; 193 | dplot = 1; 194 | else 195 | break; 196 | end 197 | end 198 | 199 | % Check terminating condition 200 | if ii>5 201 | if max(xcorr_normal(spec_z(ii,:),spec_z(ii-1,:),nt/8))>0.99999 202 | dconv = dconv + 1 ; 203 | if dconv >= 5 204 | fprintf('\nSimulation is going to terminate\n'); 205 | if plot_all_fig ==1 % if figures are required 206 | dstop = 1; 207 | dplot = 1; 208 | else 209 | break; 210 | end 211 | end 212 | else 213 | dconv = 0; 214 | end 215 | end 216 | 217 | end 218 | try 219 | close(h1) 220 | catch err 221 | end 222 | 223 | tx = toc; 224 | fprintf('\nSimulation lasted (s) = %5.2f%\n', tx ); 225 | 226 | fprintf('\nOutput Peak Power (W) = %5.2f\n',max(uout.*conj(uout))); 227 | 228 | PulseEnergy = dt*sum(uout.*conj(uout)); 229 | fprintf('Output Pulse Energy in pJ = %5.2f\n', PulseEnergy); 230 | 231 | 232 | %% Plot results 233 | 234 | phase_out = phase(uout); 235 | delta_w = diff(phase_out); 236 | Eout = abs(uout).^2; 237 | [uout_max,I_uout_max] = max(Eout); 238 | [width,~,~] = fwhm(Eout); 239 | [~,I_l,I_r] = fwzm(Eout,1e-4); 240 | range = I_l:I_r; 241 | figure(6);[ax,p1,p2] = plotyy(t,Eout,t(range),delta_w(range),'plot','plot'); 242 | grid on; axis(ax(1),'tight'); 243 | axis(ax(2),[min(t),max(t),-2,2]); 244 | xlabel (['t (ps)',sprintf(', %.1fps',width*dt),... 245 | sprintf(', %.1fW(Peak)',PulseEnergy/width/dt),... 246 | sprintf(', %.1fMHz',RepeatFre/1e6)]); 247 | ylabel (ax(1),'|u(z,t)|^2 (W)'); 248 | ylabel(ax(2),'Chirp(THz)') % label right y-axis 249 | 250 | %% More plots 251 | if dplot 252 | Plot_ML_result 253 | end 254 | -------------------------------------------------------------------------------- /SimMolFil/+simulation/+builder/Evaluation.m: -------------------------------------------------------------------------------- 1 | classdef Evaluation < handle 2 | %EVALUATION A class that represnts a evaluatable/ a runnable program 3 | % Need to be properly constructed by a Builder 4 | % Once built, a Evaluation object e is callable, will output 5 | % simulation results for dufferent sets of arguments. 6 | 7 | properties (Access = private) 8 | program % collection of models in Map 9 | ids % id of models in order 10 | variables % collection of variables presenting light fields 11 | iter % iteration counter for recurrence node 12 | pointer % index point to id of current model 13 | end 14 | 15 | methods 16 | function obj = Evaluation(program) 17 | %EVAL Construct an instance of this class 18 | ids = zeros(length(program),1); 19 | for ii = 1:length(program) 20 | ids(ii) = program(ii).get_id(); 21 | end 22 | if length(program)>1 23 | program = cell(program); 24 | end 25 | obj.program = containers.Map(ids,program); 26 | obj.ids = ids; 27 | end 28 | 29 | function e = run(obj, kwargs) 30 | %RUN actually evaluate the program 31 | % Models in the program are evaluated one by one 32 | 33 | % kwargs should be a struct, it is like keyword argument 34 | if ~isa(kwargs, "struct") 35 | error("Evaluation: run needs one struct-type argument\n"); 36 | end 37 | % check parameters in kwargs. 38 | config = kwargs.configuration; 39 | % Initialise light field variables 40 | nt = config.nt; 41 | % Allocate maximum space for variables 42 | ones_temp = zeros(nt,max(cell2mat(keys(obj.program)))+1); 43 | obj.variables = complex(ones_temp, ones_temp); 44 | obj.iter = 0; 45 | % Start calculation 46 | obj.pointer = 1; % Model Pointer 47 | end_of_program = length(obj.ids); 48 | while (obj.pointer <= end_of_program) 49 | id = obj.ids(obj.pointer); 50 | model = obj.program(id); 51 | operation = model.get_operation(); 52 | op_type = obj.program(id).get_op_type(); 53 | % Get inputs idx in variables 54 | args_idx = obj.program(id).get_inputs_id()+1; 55 | args = obj.variables(:,args_idx); 56 | % Throw error if op_type not implemented 57 | disp(model); 58 | obj.(op_type)(model, operation, args, kwargs); 59 | end 60 | % return the value corresponding to the last model 61 | if isfield(kwargs, "Out_id") 62 | e = obj.variables(:,kwargs.Out_id); 63 | else 64 | e = obj.variables(:,obj.ids(end)+1); 65 | end 66 | end 67 | 68 | function m = subsref(obj,S) 69 | %SUBSREF make Evaluation object callable 70 | if S.type == "()" 71 | if length(obj) == 1 72 | % Evaluation_obj(struct(inputs,parameters...)) 73 | % Check arguments numbers 74 | if length(S.subs)~=1 && isa(S.subs{1},"struct") 75 | error("Evaluation: need one struct-type argument\n"); 76 | end 77 | m = obj.run(S.subs{1}); 78 | return 79 | end 80 | elseif S.type == "." 81 | m = builtin('subsref',obj,S); 82 | return 83 | end 84 | % Everything else results in error 85 | error("Evaluation: not implemented types of subsref\n"); 86 | end 87 | end 88 | 89 | % Implementation of concrete function for each Operations 90 | methods 91 | function Input(obj, model, operation, args, kwargs) 92 | % Read input from kwargs of Evaluation 93 | value = kwargs.(operation.name); 94 | if isa(value,"double") 95 | u = value; 96 | elseif isa(value,"string") 97 | if value == "sech" 98 | config = kwargs.("configuration"); 99 | u = rand_sech(config.nt, config.time)'; 100 | else 101 | error("Evaluation: not implemented kwargs value %s for operation %s\n", value, operation); 102 | end 103 | else 104 | error("Evaluation: not implemented kwargs type %s for operation %s\n", class(value), operation); 105 | end 106 | obj.variables(:,obj.ids(obj.pointer)+1) = u; 107 | obj.pointer = obj.pointer + 1; 108 | end 109 | 110 | function Const(obj, model, operation, args, kwargs) 111 | % Read Const value from operation parameters 112 | value = operation.parameters.("value"); 113 | if isa(value,"double") 114 | u = value; 115 | else 116 | error("Evaluation: not implemented kwargs type %s for operation %s\n", class(value), operation); 117 | end 118 | obj.variables(:,obj.ids(obj.pointer)+1) = u; 119 | obj.pointer = obj.pointer + 1; 120 | end 121 | 122 | function Fiber(obj, model, operation, args, kwargs) 123 | % Read Fiber component value from operation parameters 124 | config = kwargs.("configuration"); 125 | fiber = operation.parameters.("fiber").cal_gamma(config.lambda0); 126 | % use GNLSE solver 127 | [u,~,~] = IP_CQEM_FD(transpose(args),config.dt,config.dz,fiber,config.f0,config.tol,0,1); 128 | obj.variables(:,obj.ids(obj.pointer)+1) = transpose(u); 129 | obj.pointer = obj.pointer + 1; 130 | end 131 | 132 | function Show(obj, model, operation, args, kwargs) 133 | config = kwargs.("configuration"); 134 | plotter = operation.parameters.("plotter"); 135 | if ~isempty(plotter) 136 | plotter(config,args); 137 | else 138 | error("Evaluation: no plotter for operation %s\n", operation); 139 | end 140 | obj.variables(:,obj.ids(obj.pointer)+1) = args; 141 | obj.pointer = obj.pointer + 1; 142 | end 143 | 144 | function Filter(obj, model, operation, args, kwargs) 145 | config = kwargs.("configuration"); 146 | filter = operation.parameters.("filter"); 147 | u = filter.filter_gauss(args, config.f0, config.df); 148 | obj.variables(:,obj.ids(obj.pointer)+1) = u; 149 | obj.pointer = obj.pointer + 1; 150 | end 151 | 152 | function CouplerOut1(obj, model, operation, args, kwargs) 153 | config = kwargs.("configuration"); 154 | coupler = operation.parameters.("coupler"); 155 | u = coupler.couplerOut1(args(:,1),args(:,2)); 156 | obj.variables(:,obj.ids(obj.pointer)+1) = u; 157 | obj.pointer = obj.pointer + 1; 158 | end 159 | 160 | function CouplerOut2(obj, model, operation, args, kwargs) 161 | config = kwargs.("configuration"); 162 | coupler = operation.parameters.("coupler"); 163 | u = coupler.couplerOut2(args(:,1),args(:,2)); 164 | obj.variables(:,obj.ids(obj.pointer)+1) = u; 165 | obj.pointer = obj.pointer + 1; 166 | end 167 | 168 | function Recurrence(obj, model, operation, args, kwargs) 169 | config = kwargs.("configuration"); 170 | condition = operation.parameters.("condition"); 171 | if condition == "Run_until_stop" 172 | if obj.iter == config.N_trip 173 | di = length(obj.program); % jump out of the main loop 174 | else 175 | di = 1; 176 | end 177 | obj.iter = obj.iter + 1; 178 | end 179 | obj.variables(:,obj.ids(obj.pointer)+1) = args; 180 | obj.pointer = obj.pointer + di; 181 | end 182 | 183 | function Feedback(obj, model, operation, args, kwargs) 184 | inputs_id = model.get_inputs_id(); 185 | recurrence_model = obj.program(inputs_id(1)); 186 | % Hack into the recurrence model, reconnect input 187 | obj.program(inputs_id(1)) = recurrence_model.set_inputs(obj.program(inputs_id(2))); 188 | % Jump to where the recurrence model is 189 | obj.pointer = find(obj.ids==inputs_id(1)); 190 | end 191 | 192 | function Join(obj, model, operation, args, kwargs) 193 | obj.variables(:,obj.ids(obj.pointer)+1) = args(:,1); 194 | obj.pointer = obj.pointer + 1; 195 | end 196 | 197 | end 198 | end 199 | 200 | -------------------------------------------------------------------------------- /SimMolFil/unittests/EvaluationTest.m: -------------------------------------------------------------------------------- 1 | classdef EvaluationTest < matlab.unittest.TestCase 2 | %EVALUATIONTEST Summary of this class goes here 3 | % Detailed explanation goes here 4 | 5 | methods(TestMethodSetup) 6 | function createFixture(testCase) 7 | function clearModel() 8 | clear Model 9 | end 10 | testCase.addTeardown(@clearModel); 11 | end 12 | end 13 | 14 | methods (Test) 15 | function testArrayInput(testCase) 16 | In = simulation.Input("In"); 17 | show = simulation.Show(struct("plotter",@plot_model)); 18 | Out = show(In); 19 | Eval = Out.build(simulation.builder.Builder()); 20 | 21 | config = simulation.Configuration(); 22 | input = rands(config.nt,1); 23 | result = Eval(struct("configuration",config,... 24 | "In",input)); 25 | testCase.assertEqual(result,input); 26 | end 27 | 28 | function testSechInput(testCase) 29 | In = simulation.Input("In"); 30 | show = simulation.Show(struct("plotter",@plot_model)); 31 | Out = show(In); 32 | Eval = Out.build(simulation.builder.Builder()); 33 | 34 | config = simulation.Configuration(); 35 | input = rand_sech(config.nt, config.time)'; 36 | result = Eval(struct("configuration",config,... 37 | "In","sech")); 38 | testCase.assertEqual(result,input); 39 | end 40 | 41 | function testConst(testCase) 42 | config = simulation.Configuration(); 43 | const = rands(config.nt,1); 44 | Out = simulation.Const(const); 45 | Eval = Out.build(simulation.builder.Builder()); 46 | 47 | result = Eval(struct("configuration",config)); 48 | testCase.assertEqual(result,const); 49 | end 50 | 51 | function testSingleFiberEvaluation(testCase) 52 | config = simulation.Configuration(); 53 | fiber = component.Fiber(); 54 | fiber.L = 0.1; 55 | fiber = fiber.cal_gamma(config.lambda0); 56 | 57 | SMF = simulation.Fiber("SMF", fiber); 58 | In = simulation.Input("In"); 59 | Out = In + SMF; 60 | Eval = Out.build(simulation.builder.Builder()); 61 | 62 | input = rands(config.nt,1); 63 | result = Eval(struct("configuration",config,... 64 | "In",input)); 65 | 66 | compare = IP_CQEM_FD(input',config.dt,config.dz,fiber,config.f0,config.tol,0,1); 67 | testCase.assertEqual(result,transpose(compare)); 68 | end 69 | 70 | function testActiveFiberEvaluation(testCase) 71 | config = simulation.Configuration(); 72 | 73 | fiber = component.ActiveFiber(); 74 | fiber.L = 0.001; 75 | fiber = fiber.cal_gamma(config.lambda0)... 76 | .set_RepeatFre(fiber.L); 77 | 78 | SMF = simulation.Fiber("SMF", fiber); 79 | In = simulation.Input("In"); 80 | Out = In + SMF; 81 | Eval = Out.build(simulation.builder.Builder()); 82 | 83 | input = rands(config.nt,1); 84 | result = Eval(struct("configuration",config,... 85 | "In",input)); 86 | 87 | compare = IP_CQEM_FD(input',config.dt,config.dz,fiber,config.f0,config.tol,0,1); 88 | testCase.assertEqual(result,transpose(compare)); 89 | end 90 | 91 | function testMultipleFiberEvaluation(testCase) 92 | config = simulation.Configuration(); 93 | 94 | fiber = component.Fiber(); 95 | fiber.L = 0.001; 96 | fiber = fiber.cal_gamma(config.lambda0); 97 | 98 | createFixture(testCase); 99 | SMF1 = simulation.Fiber("SMF1", fiber); 100 | SMF2 = simulation.Fiber("SMF2", fiber); 101 | SMF3 = simulation.Fiber("SMF3", fiber); 102 | In = simulation.Input("In"); 103 | Out = In + SMF1 + SMF2 + SMF3; 104 | Eval = Out.build(simulation.builder.Builder()); 105 | 106 | input = rands(config.nt,1); 107 | result = Eval(struct("configuration",config,... 108 | "In",input)); 109 | 110 | u1 = IP_CQEM_FD(input',config.dt,config.dz,fiber,config.f0,config.tol,0,1); 111 | u2 = IP_CQEM_FD(u1,config.dt,config.dz,fiber,config.f0,config.tol,0,1); 112 | u3 = IP_CQEM_FD(u2,config.dt,config.dz,fiber,config.f0,config.tol,0,1); 113 | 114 | testCase.assertEqual(result,transpose(u3)); 115 | end 116 | 117 | function testFilterEvaluation(testCase) 118 | BPF = simulation.Filter("BPF", component.Filter(1030, 1030, 7)); 119 | In = simulation.Input("In"); 120 | Out = In + BPF; 121 | Eval = Out.build(simulation.builder.Builder()); 122 | 123 | config = simulation.Configuration(); 124 | input = rand_sech(config.nt, config.time)'; 125 | result = Eval(struct("configuration",config,... 126 | "In","sech")); 127 | testCase.assertEqual(true,true); 128 | end 129 | 130 | function testCouplerEvaluation(testCase) 131 | % Test Coupler model 132 | createFixture(testCase); 133 | rho = 0.3; 134 | In1 = simulation.Input("In1"); 135 | In2 = simulation.Input("In2"); 136 | OC = simulation.Coupler("OC", component.Coupler(rho)); 137 | 138 | [Out1,Out2] = [In1, In2] + OC; 139 | Eval1 = Out1.build(simulation.builder.Builder()); 140 | Eval2 = Out2.build(simulation.builder.Builder()); 141 | 142 | config = simulation.Configuration(); 143 | input1 = rand_sech(config.nt, config.time)'; 144 | input2 = fliplr(rand_sech(config.nt, config.time))'; 145 | result1 = Eval1(struct("configuration",config,... 146 | "In1",input1,"In2",input2)); 147 | result2 = Eval2(struct("configuration",config,... 148 | "In1",input1,"In2",input2)); 149 | 150 | [ u1o,u2o ] = coupler(input1,input2,rho); 151 | testCase.assertEqual(result1,u1o,"RelTol",1e-6); 152 | testCase.assertEqual(result2,u2o,"RelTol",1e-6); 153 | end 154 | 155 | function testRecuurence(testCase) 156 | createFixture(testCase); 157 | 158 | config = simulation.Configuration(); 159 | 160 | fiber = component.Fiber(); 161 | fiber.L = 0.001; 162 | fiber = fiber.cal_gamma(config.lambda0); 163 | 164 | SMF = simulation.Fiber("SMF", fiber); 165 | 166 | feedback = simulation.Feedback(); 167 | 168 | In = simulation.Input("In"); 169 | u = simulation.Recurrence("u",In,"Run_until_stop"); 170 | u1 = u + SMF; 171 | t = feedback(u,u1); 172 | 173 | config.N_trip = 10; 174 | Eval = t.build(simulation.builder.Builder()); 175 | input = rand_sech(config.nt,config.time)'; 176 | result = Eval(struct("configuration",config,... 177 | "In",input,"Out_id",3)); 178 | 179 | compare = input'; 180 | for ii = 1:config.N_trip 181 | compare = IP_CQEM_FD(compare,config.dt,config.dz,fiber,config.f0,config.tol,0,0); 182 | end 183 | testCase.assertEqual(result,transpose(compare)); 184 | end 185 | 186 | function testFigure8Evaluation(testCase) 187 | createFixture(testCase); 188 | 189 | % Structural Parameters to investigate 190 | landa_bw = 11; 191 | smf5_L = 0.025; 192 | NOLM_L = 0.0015; 193 | PsatdBm = 23.5; 194 | smf4_L = 0.002; 195 | 196 | % used default configuration 197 | config = simulation.Configuration(); 198 | 199 | % construct components 200 | coupler_NOLM = component.Coupler(0.3); 201 | coupler_output = component.Coupler(0.4); 202 | passive_fiber = component.Fiber("F10125").cal_gamma(config.lambda0); 203 | active_fiber = component.ActiveFiber("YDF10125", 37.5, PsatdBm,config.lambda0,80).cal_gamma(config.lambda0); 204 | filter = component.Filter(config.lambda0, landa_bw, 7); 205 | 206 | % assign components to models 207 | SMF1 = simulation.Fiber("SMF1", passive_fiber.set_L(0.0007)); 208 | SMF2 = simulation.Fiber("SMF2", passive_fiber.set_L(NOLM_L-0.0007)); 209 | SMF4 = simulation.Fiber("SMF4", passive_fiber.set_L(smf4_L)); 210 | SMF5 = simulation.Fiber("SMF5", passive_fiber.set_L(smf5_L)); 211 | AF = simulation.Fiber("AF", ... 212 | active_fiber.set_L(0.0008)... 213 | .set_RepeatFre(sum([NOLM_L,smf4_L,smf5_L,0.0008]))); 214 | BPF = simulation.Filter("BPF", filter); 215 | OC = simulation.Coupler("OC", coupler_output); 216 | Coupler_NOLM = simulation.Coupler("Coupler_NOLM", coupler_NOLM); 217 | 218 | % define functional models 219 | feedback = simulation.Feedback(); 220 | show = simulation.Show(struct("plotter",@plot_model)); 221 | join = simulation.Join(); 222 | 223 | % connect models 224 | % In->u->BPF->SMF4->AMF1->SMF5->NOLM->OC->u 225 | In = simulation.Input("In"); 226 | 227 | u = simulation.Recurrence("u",In,"Run_until_stop"); 228 | 229 | u1 = u + BPF + SMF4 + AF + SMF5; 230 | t = u1; 231 | [uf, ub] = [u1, 0] + Coupler_NOLM; 232 | ufo = uf + SMF1 + SMF2; 233 | ubo = ub + SMF2 + SMF1; 234 | [ur,ut] = [ubo, ufo] + Coupler_NOLM; 235 | 236 | [u2, uout] = [ut, 0] + OC; 237 | % show uout and feed u2 back to u 238 | t = feedback(u,join(u2,show(uout))); 239 | 240 | input = rand_sech(config.nt,config.time)'; 241 | config.N_trip = 20; 242 | config.tol = 1e-7; 243 | Eval = t.build(simulation.builder.Builder()); 244 | result = Eval(struct("configuration",config,... 245 | "In",input)); 246 | end 247 | end 248 | end 249 | 250 | --------------------------------------------------------------------------------