/* * WMM-Application: * directional coupler with varying gap width, coupled mode theory * --- parameter scans --- */ /* * WMM * Wave-matching method for mode analysis of dielectric waveguides * Manfred Hammer * (2002) */ #include #include #include #include"wmminc.h" /* coupler parameters (lengths in micrometers) */ #define Wgps 2.00 // straight waveguide: core width #define Wgpv 0.14 // straight waveguide: core thickness #define Wgpng 1.98 // straight waveguide: core refractive index #define Wgpnb 1.45 // substrate/straight waveguide, background refr. index #define Wgpw 2.75 // ring waveguide: core width #define Wgpt 1.0 // ring waveguide: core thickness #define Wgpnr 1.596 // ring waveguide: core refractive index #define Wgpna 1.0 // cover refractive index double Wgpb = 1.0; // straight waveguide: burying depth double Wgpg = 0.0; // straight waveguide: center displacement from ring rim double Wgpp = 0.0; // position of ring waveguide; 0: closest approach #define Wgpl 1.55 // vacuum wavelength #define WgpR 100.0 // ring radius, outer rim #define WgpZ 30.0 // half length of the directional couplers, // cores are considered to be decoupled for |z| > Z #define Numz 30 // number of discretization steps in the numerical // integration of the coupled mode equations Polarization POL=QTE; // QTE or QTM (semivectorial simulation) /* Parameter scans: range and stepsize */ #define Pmin 0.5 #define Pmax 2.5 #define Pstep 0.05 // adjust the statement in line 248 ! #define CalcBasisModes 1 // 1: calculate the basis fields, save them to files // 0: read them from previously stored files /* the straight waveguide */ Waveguide swgdef() { Waveguide g(1, 1); g.hx(0) = 0.0; g.hx(1) = Wgpv; g.hy(0) = -Wgps/2.0; g.hy(1) = Wgps/2.0; g.n(0,0) = Wgpnb; g.n(0,1) = Wgpnb; g.n(0,2) = Wgpnb; g.n(1,0) = Wgpnb; g.n(1,1) = Wgpng; g.n(1,2) = Wgpnb; g.n(2,0) = Wgpnb; g.n(2,1) = Wgpnb; g.n(2,2) = Wgpnb; g.lambda = Wgpl; return g; } /* the ring waveguide */ Waveguide rwgdef() { Waveguide g(1, 1); g.hx(0) = 0.0; g.hx(1) = Wgpt; g.hy(0) = -Wgpw/2.0; g.hy(1) = Wgpw/2.0; g.n(0,0) = Wgpnb; g.n(0,1) = Wgpnb; g.n(0,2) = Wgpnb; g.n(1,0) = Wgpna; g.n(1,1) = Wgpnr; g.n(1,2) = Wgpna; g.n(2,0) = Wgpna; g.n(2,1) = Wgpna; g.n(2,2) = Wgpna; g.lambda = Wgpl; return g; } /* the entire coupler structure */ #define Ltol 1.0e-8 Waveguide cpwgdef() { if(Wgpnb <= Ltol) { fprintf(stderr, "mres.c: cpwgdef: Wgpb<=0 not implemented.\n"); exit(1); } Dvector hytmp(4); hytmp(0) = -Wgpp-Wgpw; hytmp(1) = -Wgpp; hytmp(2) = Wgpg-Wgps/2.0; hytmp(3) = Wgpg+Wgps/2.0; hytmp.sort(0); Dvector hy(4); hy(0) = hytmp(0); int ny=1; for(int j=1; j<=3; ++j) { if(fabs(hy(ny-1) - hytmp(j)) >= Ltol) { hy(ny) = hytmp(j); ++ny; } } --ny; Waveguide wg(3, ny); wg.hx(0) = -Wgpb-Wgpv; wg.hx(1) = -Wgpb; wg.hx(2) = 0.0; wg.hx(3) = Wgpt; for(int i=0; i<=ny; ++i) wg.hy(i) = hy(i); for(int m=0; m<=ny+1; ++m) { double y; Rect r; r = wg.rectbounds(1, m); y = (r.y0+r.y1)/2.0; wg.n(0,m) = Wgpnb; if(y < Wgpg-Wgps/2.0 || y > Wgpg+Wgps/2.0) wg.n(1, m) = Wgpnb; else wg.n(1, m) = Wgpng; wg.n(2,m) = Wgpnb; if(y < -Wgpp-Wgpw || y > -Wgpp) wg.n(3, m) = Wgpna; else wg.n(3, m) = Wgpnr; wg.n(4,m) = Wgpna; } wg.lambda = Wgpl; return wg; } /* mode solver parameters */ WMM_Parameters pardef() { WMM_Parameters p; p.vform = HXHY; p.vnorm = NRMMH; p.ccomp = CCALL; p.ini_d_alpha = 0.01; p.ini_N_alpha = 10; p.ini_alpha_max = 2.0; p.ini_steps = 20; p.ref_num = 5; p.ref_exp = 4.0; p.ref_sdf = 0.5; p.fin_d_alpha = 0.01; p.fin_N_alpha = 30; p.fin_alpha_max = 3.0; p.btol = 1.0e-7; p.mshift = 1.0e-8; return p; } /* coupled mode theory simulation */ int main() { WMM_Parameters par = pardef(); WMM_ModeArray ma; WMM_Mode m, stmo, rimo; Waveguide wg; if(CalcBasisModes == 1) { wg = swgdef(); WMM_findfundmode(wg, POL, SYM, 0.0, 0.0, par, 's', 't', ma); stmo = ma(0); stmo.write_def('s', 't'); ma.clear(); wg = rwgdef(); WMM_findfundmode(wg, POL, SYM, 0.0, 0.0, par, 'r', 'i', ma); rimo = ma(0); rimo.write_def('r', 'i'); ma.clear(); } else { stmo.read_def(POL, SYM, 's', 't'); rimo.read_def(POL, SYM, 'r', 'i'); } Dmatrix sigma(2,2); Dvector sbeta(2); Dmatrix samp(2,2); Dmatrix S(2,2); Dmatrix BK(2,2); double betaq = 0.5*(stmo.beta + rimo.beta); Cmatrix M0(2,2); Cmatrix Mp(2,2); Cmatrix M1(2,2); Cmatrix N1(2,2); Cmatrix N2(2,2); Cmatrix N3(2,2); Cmatrix N4(2,2); Cmatrix One; One.unit(2); Cvector inA(2); inA(0) = CC1; inA(1) = CC0; Cvector ina(2); ina(0) = CC0; ina(1) = CC1; Cvector out; Cmatrix T(2,2); Cmatrix Tp(2,2); double h = WgpZ*2.0/((double)Numz); for(double p=Pmin; p<=Pmax; p+=Pstep) { // ... Wgpb = p; // ... fprintf(stderr, "\n(( %g ))\n", p); T.unit(2); fprintf(stderr, "<< CMT: "); double z = -WgpZ; Wgpp = WgpR-sqrt(WgpR*WgpR-z*z); ma.clear(); m = stmo; m.translate(-Wgpb-Wgpv, Wgpg); ma.add(m); m = rimo; m.translate(0.0, -(Wgpp+Wgpw/2.0)); ma.add(m); wg = cpwgdef(); CMTmats(ma, wg, S, BK); S.inverse(); M0 = mult(add(mult(One, betaq), mult(mult(S, BK), -1.0)), CCI); for(int zi=0; zi<=Numz-1; ++zi) { z += h/2.0; Wgpp = WgpR-sqrt(WgpR*WgpR-z*z); ma.clear(); m = stmo; m.translate(-Wgpb-Wgpv, Wgpg); ma.add(m); m = rimo; m.translate(0.0, -(Wgpp+Wgpw/2.0)); ma.add(m); wg = cpwgdef(); CMTmats(ma, wg, S, BK); S.inverse(); Mp = mult(add(mult(One, betaq), mult(mult(S, BK), -1.0)), CCI); z += h/2.0; Wgpp = WgpR-sqrt(WgpR*WgpR-z*z); ma.clear(); m = stmo; m.translate(-Wgpb-Wgpv, Wgpg); ma.add(m); m = rimo; m.translate(0.0, -(Wgpp+Wgpw/2.0)); ma.add(m); wg = cpwgdef(); CMTmats(ma, wg, S, BK); S.inverse(); M1 = mult(add(mult(One, betaq), mult(mult(S, BK), -1.0)), CCI); N1 = mult(M0, h); N2 = mult(mult(Mp, add(One, mult(N1, 0.5))), h); N3 = mult(mult(Mp, add(One, mult(N2, 0.5))), h); N4 = mult(mult(M1, add(One, N3)), h); Tp = One; Tp = add(Tp, mult(N1, 1.0/6.0)); Tp = add(Tp, mult(N2, 1.0/3.0)); Tp = add(Tp, mult(N3, 1.0/3.0)); Tp = add(Tp, mult(N4, 1.0/6.0)); T = mult(Tp, T); M0 = M1; fprintf(stderr, "."); } fprintf(stderr, " Ok. >>\n"); T = mult(T, expi(-betaq*(2.0*WgpZ))); fprintf(stderr, "T:\n"); T.write(stderr); fprintf(stderr, "|kappa|^2: %g\n", T(1, 0).sqabs()); fprintf(stderr, " %g\n", T(0, 1).sqabs()); double kappa = 0.5*(T(0, 1).sqabs()+T(1, 0).sqabs()); fprintf(stderr, "average: %g\n", kappa); double tau = T(0, 0).sqabs(); double rho = T(1, 1).sqabs(); fprintf(stderr, "|tau|^2: %g\n", tau); fprintf(stderr, "|rho|^2: %g\n", rho); tau = 0.5*(tau+rho); fprintf(stderr, "average: %g\n", tau); fprintf(stderr, "|tau|^2+|kappa|^2: %g\n", tau+kappa); fprintf(stderr, "\n"); apptoxyf("kappa", p, kappa); apptoxyf("tau", p, tau); apptoxyf("total", p, tau+kappa); } ma.clear(); return 0; }