def calcvrt0(M, Mvv, Mrv, Mvr, Mtv, Mvt, fvn, frn, ftn): lu = splu(Mvv) #Mhatrr and Mhattr b = lu.solve(Mvr) Mhatrr = -Mrv * b _addToDiagonal(Mhatrr, M.lx) Mhattr = -Mtv * b #Mhatrt and Mhattt b = lu.solve(Mvt) Mhatrt = -Mrv * b Mhattt = -Mtv * b _addToDiagonal(Mhattt, M.lx) #fhatrn b = lu.solve(fvn) a = Mrv * b fhatrn = frn - a #fhattn b = lu.solve(fvn) a = Mtv * b fhattn = ftn - a MAT = pl.bmat([[Mhatrr, Mhatrt], [Mhattr, Mhattt]]) RHS = pl.bmat([[fhatrn], [fhattn]]) V = pl.solve(MAT, RHS) r = V[:M.NM, 0] t = V[M.NM:, 0] sol = lu.solve(fvn - Mvr * r - Mvt * t) return sol, r, t
def calcScatteringMatrix(M,P,x): ## FE analysis to acquire scattering matrices (see Dossou2006) instead of solving for one incident ## condition as done in FE(). # #@param M Model object containing geometrical information #@param P Physics object containing physical parameters #@param x The design domain with 0 corresponding to eps1 and 1 corresponding to eps2 # and intermediate values to weighted averages in between. See physics.interpolate #@return Dictionary containing the matrices R,T,R',T' that the scattering matrix consists of. # as well as normal data # #see also FE() A,B = P.interpolate(x) Mvv = assembleMvv(A,B,M,P) Mrv,Mvr,Mtv,Mvt,fvn,frn = assembleMxxfx(M,P) lu = splu(Mvv) #Mhatrr and Mhattr b = lu.solve(Mvr) Mhatrr = -Mrv*b _addToDiagonal(Mhatrr, M.lx) Mhattr = -Mtv*b #Mhatrt and Mhattt b = lu.solve(Mvt) Mhatrt = -Mrv*b Mhattt = -Mtv*b _addToDiagonal(Mhattt, M.lx) #fhatrn b = lu.solve(fvn) a = Mrv*b fhatrn = frn-a #fhattn b = lu.solve(fvn) a = Mtv*b fhattn = -a MAT = pl.bmat([[Mhatrr, Mhatrt], [Mhattr, Mhattt]]) RHS = pl.bmat([[ Mhatrr-2*M.lx*pl.identity(M.NM), Mhatrt], [Mhattr, Mhattt-2*M.lx*pl.identity(M.NM)]]) #Solve Eq (53) in Dossou 2006 RTtilde = pl.solve(MAT,RHS) RIn = RTtilde[:M.NM,:M.NM] TIn = RTtilde[M.NM:,:M.NM] ROut = RTtilde[M.NM:,M.NM:] TOut = RTtilde[:M.NM,M.NM:] results = {} results["RIn"] = RIn results["TIn"] = TIn results["ROut"] = ROut results["TOut"] = TOut results.update(M.getParameters()) results.update(P.getParameters()) return results
def calcdp(rep_no, thetainput): rep_no = rep_no wav = 505 lam = 400 thetain = thetainput / 180 * pl.pi nAir = 1.0 nBac = 1.38 nMed = 1.34 pol = 'Ey' nelx = 40 z_uc = 2.0 * math.sqrt(3) ##Reference model FE_start_time = time.time() Mres = model(lx=2 * lam, lz=(1 + rep_no) * (z_uc) * lam, nelx=nelx) Pres = physics(Mres, wav, nAir, nBac, thetaIn=thetain, pol=pol) if 1: #Put to zero to avoid re-simulation and use last saved results materialResAir = Pres.newMaterial(nAir) materialResBac = Pres.newMaterial(nBac) materialResMed = Pres.newMaterial(nMed) xres = Mres.generateEmptyDesign() makeSlab(xres, Mres, (rep_no) * (z_uc) * lam, (1 + rep_no) * (z_uc) * lam, materialResAir) makeSlab(xres, Mres, 0 * (z_uc) * lam, (rep_no) * (z_uc) * lam, materialResMed) for x in range(0, rep_no): makeCircle(xres, Mres, lam, x * (z_uc) * lam, lam, materialResBac) makeCircle(xres, Mres, 0, (x + 1 / 2) * (z_uc) * lam, lam, materialResBac) makeCircle(xres, Mres, 2 * lam, (x + 1 / 2) * (z_uc) * lam, lam, materialResBac) makeCircle(xres, Mres, lam, (rep_no) * (z_uc) * lam, lam, materialResBac) if 0: #Show design pl.imshow(xres.T, interpolation='none', vmin=0, vmax=4) pl.colorbar() pl.savefig("full_structure.png", bbox_inches='tight') pl.show() exit() res = FE(Mres, Pres, xres) #saveDicts("SmatrixRIInternalReference.h5",res,'a') #else: #res = loadDicts("SmatrixRIInternalReference.h5")[0] mR, thetaR, R, mT, thetaT, T = calcRT(Mres, Pres, res["r"], res["t"]) Rres = R Tres = T FE_time = time.time() - FE_start_time CSM_start_time = time.time() ##Scattering matrix model air-material boundary M = model(lx=2.0 * lam, lz=1 * (z_uc) * lam, nelx=nelx) P = physics(M, wav, nAir, nBac, thetaIn=thetain, pol=pol) materialAir = P.newMaterial(nAir) materialBac = P.newMaterial(nBac) materialMed = P.newMaterial(nMed) x = M.generateEmptyDesign() makeSlab(x, M, 0, 1.0 * (z_uc) * lam, materialAir) makeCircle(x, M, lam, 0, lam, materialBac) if 0: #Show design pl.imshow(x.T, interpolation='none', vmin=0, vmax=4) pl.colorbar() pl.savefig("upper_half.png", bbox_inches='tight') pl.show() exit() res = calcScatteringMatrix(M, P, x) S1 = RTtoS(res["RIn"], res["TIn"], res["TOut"], res["ROut"]) matL = pl.bmat([[pl.diag(pl.sqrt(P.chiIn)), pl.zeros((M.NM, M.NM))], [pl.zeros((M.NM, M.NM)), pl.diag(pl.sqrt(P.chiOut))]]) matR = pl.bmat([[pl.diag(1 / pl.sqrt(P.chiIn)), pl.zeros((M.NM, M.NM))], [pl.zeros((M.NM, M.NM)), pl.diag(1 / pl.sqrt(P.chiOut))]]) S1real = matL * S1 * matR Stot = S1 Stotreal = S1real thetainNew = thetain ##Scattering matrix model unit cell M = model(lx=2.0 * lam, lz=(z_uc) * lam, nelx=nelx) thetainNew = pl.arcsin(P.nIn / P.nOut * pl.sin(thetainNew)) P = physics(M, wav, nBac, nBac, thetaIn=thetainNew, pol=pol) # materialAir = P.newMaterial(nAir) materialBac = P.newMaterial(nBac) materialMed = P.newMaterial(nMed) x = M.generateEmptyDesign() makeSlab(x, M, 0, 1.0 * (z_uc) * lam, materialMed) makeCircle(x, M, lam, 0, lam, materialBac) makeCircle(x, M, lam, 1.0 * (z_uc) * lam, lam, materialBac) makeCircle(x, M, 0, (1 / 2) * (z_uc) * lam, lam, materialBac) makeCircle(x, M, 2 * lam, (1 / 2) * (z_uc) * lam, lam, materialBac) if 0: #Show design pl.imshow(x.T, interpolation='none', vmin=0, vmax=4) pl.colorbar() pl.savefig("lower_half.png", bbox_inches='tight') pl.show() exit() res = calcScatteringMatrix(M, P, x) S2 = RTtoS(res["RIn"], res["TIn"], res["TOut"], res["ROut"]) matL = pl.bmat([[pl.diag(pl.sqrt(P.chiIn)), pl.zeros((M.NM, M.NM))], [pl.zeros((M.NM, M.NM)), pl.diag(pl.sqrt(P.chiOut))]]) matR = pl.bmat([[pl.diag(1 / pl.sqrt(P.chiIn)), pl.zeros((M.NM, M.NM))], [pl.zeros((M.NM, M.NM)), pl.diag(1 / pl.sqrt(P.chiOut))]]) S2real = matL * S2 * matR for x in range(1, rep_no + 1): Stot = stackElements(Stot, S2) Stotreal = stackElements(Stotreal, S2real) CSM_time = time.time() - CSM_start_time #Stack the two scattering elements #Stot = stackElements(S1,S2) RIn, TIn, TOut, ROut = StoRT(Stot) results = {} results["RIn"] = RIn results["TIn"] = TIn results["ROut"] = ROut results["TOut"] = TOut results.update(M.getParameters()) results.update(P.getParameters()) #saveDicts("SmatrixRICalculations.h5",results,'a') #Define incident wave as a plane wave einc = pl.zeros((2 * M.NM, 1), dtype='complex').view(pl.matrix) einc[M.NM // 2, 0] = 1. tmp = Stot * einc rnew = tmp[:M.NM].view(pl.ndarray).flatten() tnew = tmp[M.NM:].view(pl.ndarray).flatten() mR, thetaR, Rnew, mT, thetaT, Tnew = calcRT(Mres, Pres, rnew, tnew) title = "speed_wrt_rep_no_FE.csv" txtdata = open(title, "a") txtdata.write("{:f}, {:.8f}\n".format(rep_no, FE_time)) title = "speed_wrt_rep_no_CSM.csv" txtdata = open(title, "a") txtdata.write("{:f}, {:.8f}\n".format(rep_no, CSM_time)) print("rep_no={:f}, FE_time={:.8f}, CSM_time={:.8f}".format( rep_no, FE_time, CSM_time)) txtdata.close() #Define incident wave as a plane wave einc = pl.zeros((2 * M.NM, 1), dtype='complex').view(pl.matrix) einc[M.NM // 2, 0] = 1. #Stotreal = S1real if 0: pl.imshow(abs(S1real), interpolation='none', vmin=0, vmax=1) print abs(S1real).max() pl.colorbar() pl.show() pl.imshow(abs(S2real), interpolation='none', vmin=0, vmax=1) print abs(S2real).max() pl.colorbar() pl.show() tmp = Stotreal * einc r = tmp[:M.NM].view(pl.ndarray).flatten() t = tmp[M.NM:].view(pl.ndarray).flatten() idx = Pres.propModesIn R = abs(r[idx])**2 idx = Pres.propModesOut T = abs(t[idx])**2 return
def RTtoS(RIn, TIn, TOut, ROut): S = pl.bmat([[RIn, TOut], [TIn, ROut]]) return S
def calcdp(wavinput, thetainput): rep_no = 50 wav = wavinput lam = 400 thetain = thetainput / 180 * pl.pi nAir = 1.0 nBac = 1.38 nMed = 1.34 #nMaterial2 = nIn #When nMaterial2 == nIn, the methods works #nOut = nMaterial2 pol = 'Ey' nelx = 40 z_uc = 2.0 * math.sqrt(3) ##Scattering matrix model air-material boundary Mres = model(lx=2 * lam, lz=(1 + rep_no) * (z_uc) * lam, nelx=nelx) Pres = physics(Mres, wav, nAir, nBac, thetaIn=thetain, pol=pol) if 1: #Put to zero to avoid re-simulation and use last saved results materialResAir = Pres.newMaterial(nAir) materialResBac = Pres.newMaterial(nBac) materialResMed = Pres.newMaterial(nMed) xres = Mres.generateEmptyDesign() makeSlab(xres, Mres, (rep_no) * (z_uc) * lam, (1 + rep_no) * (z_uc) * lam, materialResAir) makeSlab(xres, Mres, 0 * (z_uc) * lam, (rep_no) * (z_uc) * lam, materialResMed) for x in range(0, rep_no): makeCircle(xres, Mres, lam, x * (z_uc) * lam, lam, materialResBac) makeCircle(xres, Mres, 0, (x + 1 / 2) * (z_uc) * lam, lam, materialResBac) makeCircle(xres, Mres, 2 * lam, (x + 1 / 2) * (z_uc) * lam, lam, materialResBac) makeCircle(xres, Mres, lam, (rep_no) * (z_uc) * lam, lam, materialResBac) if 0: #Show design pl.imshow(xres.T, interpolation='none', vmin=0, vmax=4) pl.colorbar() pl.savefig("full_structure.png", bbox_inches='tight') pl.show() exit() ##Scattering matrix model air-material boundary M = model(lx=2.0 * lam, lz=1 * (z_uc) * lam, nelx=nelx) #Notice how nOut here is nMaterial2 P = physics(M, wav, nAir, nBac, thetaIn=thetain, pol=pol) materialAir = P.newMaterial(nAir) materialBac = P.newMaterial(nBac) materialMed = P.newMaterial(nMed) x = M.generateEmptyDesign() makeSlab(x, M, 0, 1.0 * (z_uc) * lam, materialAir) makeCircle(x, M, lam, 0, lam, materialBac) if 0: #Show design pl.imshow(x.T, interpolation='none', vmin=0, vmax=4) pl.colorbar() pl.savefig("upper_half.png", bbox_inches='tight') pl.show() exit() res = calcScatteringMatrix(M, P, x) S1 = RTtoS(res["RIn"], res["TIn"], res["TOut"], res["ROut"]) matL = pl.bmat([[pl.diag(pl.sqrt(P.chiIn)), pl.zeros((M.NM, M.NM))], [pl.zeros((M.NM, M.NM)), pl.diag(pl.sqrt(P.chiOut))]]) matR = pl.bmat([[pl.diag(1 / pl.sqrt(P.chiIn)), pl.zeros((M.NM, M.NM))], [pl.zeros((M.NM, M.NM)), pl.diag(1 / pl.sqrt(P.chiOut))]]) S1real = matL * S1 * matR Stot = S1 Stotreal = S1real thetainNew = thetain ##Scattering matrix model unit cell M = model(lx=2.0 * lam, lz=(z_uc) * lam, nelx=nelx) thetainNew = pl.arcsin(P.nIn / P.nOut * pl.sin(thetainNew)) P = physics(M, wav, nBac, nBac, thetaIn=thetainNew, pol=pol) # materialAir = P.newMaterial(nAir) materialBac = P.newMaterial(nBac) materialMed = P.newMaterial(nMed) x = M.generateEmptyDesign() makeSlab(x, M, 0, 1.0 * (z_uc) * lam, materialMed) makeCircle(x, M, lam, 0, lam, materialBac) makeCircle(x, M, lam, 1.0 * (z_uc) * lam, lam, materialBac) makeCircle(x, M, 0, (1 / 2) * (z_uc) * lam, lam, materialBac) makeCircle(x, M, 2 * lam, (1 / 2) * (z_uc) * lam, lam, materialBac) if 0: pl.imshow(x.T, interpolation='none', vmin=0, vmax=4) pl.colorbar() pl.savefig("lower_half.png", bbox_inches='tight') pl.show() exit() res = calcScatteringMatrix(M, P, x) S2 = RTtoS(res["RIn"], res["TIn"], res["TOut"], res["ROut"]) matL = pl.bmat([[pl.diag(pl.sqrt(P.chiIn)), pl.zeros((M.NM, M.NM))], [pl.zeros((M.NM, M.NM)), pl.diag(pl.sqrt(P.chiOut))]]) matR = pl.bmat([[pl.diag(1 / pl.sqrt(P.chiIn)), pl.zeros((M.NM, M.NM))], [pl.zeros((M.NM, M.NM)), pl.diag(1 / pl.sqrt(P.chiOut))]]) S2real = matL * S2 * matR for x in range(1, rep_no + 1): Stot = stackElements(Stot, S2) Stotreal = stackElements(Stotreal, S2real) RIn, TIn, TOut, ROut = StoRT(Stot) results = {} results["RIn"] = RIn results["TIn"] = TIn results["ROut"] = ROut results["TOut"] = TOut results.update(M.getParameters()) results.update(P.getParameters()) #saveDicts("SmatrixRICalculations.h5",results,'a') #Define incident wave as a plane wave einc = pl.zeros((2 * M.NM, 1), dtype='complex').view(pl.matrix) einc[M.NM // 2, 0] = 1. tmp = Stot * einc rnew = tmp[:M.NM].view(pl.ndarray).flatten() tnew = tmp[M.NM:].view(pl.ndarray).flatten() mR, thetaR, Rnew, mT, thetaT, Tnew = calcRT(Mres, Pres, rnew, tnew) for i in range(len(mR)): title = "reflect_mode_n_equals_{:d}_50.csv".format(mR[i]) txtdata = open(title, "a") txtdata.write("{:d}, {:f}, {:.8f}\n".format(wavinput, thetainput, Rnew[i])) #print("m={:d}, theta={:f}, mode={:d}, R={:.8f}".format(wavinput,thetainput,mR[i],Rnew[i])) txtdata.close() for i in range(len(mT)): title = "trans_mode_n_equals_{:d}_50.csv".format(mT[i]) txtdata = open(title, "a") txtdata.write("{:d}, {:f}, {:.8f}\n".format(wavinput, thetainput, Tnew[i])) #print("m={:d}, theta={:f}, mode={:d}, T={:.8f}".format(wavinput,thetainput,mT[i],Tnew[i])) txtdata.close() #Define incident wave as a plane wave einc = pl.zeros((2 * M.NM, 1), dtype='complex').view(pl.matrix) einc[M.NM // 2, 0] = 1. #Stotreal = S1real if 0: pl.imshow(abs(S1real), interpolation='none', vmin=0, vmax=1) print abs(S1real).max() pl.colorbar() pl.show() pl.imshow(abs(S2real), interpolation='none', vmin=0, vmax=1) print abs(S2real).max() pl.colorbar() pl.show() tmp = Stotreal * einc r = tmp[:M.NM].view(pl.ndarray).flatten() t = tmp[M.NM:].view(pl.ndarray).flatten() idx = Pres.propModesIn R = abs(r[idx])**2 idx = Pres.propModesOut T = abs(t[idx])**2 return
def main(): lam = 505 thetain = -30 / 180 * pl.pi nIn = 2.8 nMaterial1 = 5.9 nMaterial2 = 4.2 #nMaterial2 = nIn #When nMaterial2 == nIn, the methods works nOut = 4.3 #If nOut<nIn, we can have values in the S matrix exceeding 1 nOut = 2.1 #nOut = nMaterial2 pol = 'Ey' nelx = 80 ##Reference model (one circle + one burried circle) Mres = model(lx=lam, lz=2 * lam, nelx=nelx) Pres = physics(Mres, lam, nIn, nOut, thetaIn=thetain, pol=pol) if 1: #Put to zero to avoid re-simulation and use last saved results materialRes1 = Pres.newMaterial(nMaterial1) materialRes2 = Pres.newMaterial(nMaterial2) materialResOut = Pres.newMaterial(nOut) xres = Mres.generateEmptyDesign() makeSlab(xres, Mres, 0, 0.5 * lam, materialResOut) makeSlab(xres, Mres, 0.5 * lam, 1.5 * lam, materialRes2) makeCircle(xres, Mres, 250, 200, materialRes1) makeCircle(xres, Mres, 250 + lam, 200, materialRes1) if 0: #Show design pl.imshow(xres.T, interpolation='none', vmin=0, vmax=4) pl.colorbar() pl.savefig("full_structure.png", bbox_inches='tight') pl.show() exit() res = FE(Mres, Pres, xres) saveDicts("SmatrixRIInternalReference.h5", res, 'w') else: res = loadDicts("SmatrixRIInternalReference.h5")[0] mR, thetaR, R, mT, thetaT, T = calcRT(Mres, Pres, res["r"], res["t"]) Rres = R Tres = T ##Scattering matrix model 1 (one burried circle) M = model(lx=lam, lz=lam, nelx=nelx) #Notice how nOut here is nMaterial2 P = physics(M, lam, nIn, nMaterial2, thetaIn=thetain, pol=pol) material1 = P.newMaterial(nMaterial1) material2 = P.newMaterial(nMaterial2) x = M.generateEmptyDesign() makeSlab(x, M, 0, .5 * lam, material2) makeCircle(x, M, 250, 200, material1) if 0: #Show design pl.imshow(x.T, interpolation='none', vmin=0, vmax=4) pl.colorbar() pl.savefig("upper_half.png", bbox_inches='tight') pl.show() exit() res = calcScatteringMatrix(M, P, x) S1 = RTtoS(res["RIn"], res["TIn"], res["TOut"], res["ROut"]) matL = pl.bmat([[pl.diag(pl.sqrt(P.chiIn)), pl.zeros((M.NM, M.NM))], [pl.zeros((M.NM, M.NM)), pl.diag(pl.sqrt(P.chiOut))]]) matR = pl.bmat([[pl.diag(1 / pl.sqrt(P.chiIn)), pl.zeros((M.NM, M.NM))], [pl.zeros((M.NM, M.NM)), pl.diag(1 / pl.sqrt(P.chiOut))]]) S1real = matL * S1 * matR ##Scattering matrix model 2 (one burried circle) M = model(lx=lam, lz=lam, nelx=nelx) thetainNew = pl.arcsin(P.nIn / P.nOut * pl.sin(thetain)) P = physics(M, lam, nMaterial2, nOut, thetaIn=thetainNew, pol=pol) material1 = P.newMaterial(nMaterial1) material2 = P.newMaterial(nMaterial2) materialOut = P.newMaterial(nOut) x = M.generateEmptyDesign() makeSlab(x, M, .5 * lam, lam, material2) makeSlab(x, M, 0, .5 * lam, materialOut) makeCircle(x, M, 250, 200, material1) if 0: #Show design pl.imshow(x.T, interpolation='none', vmin=0, vmax=4) pl.colorbar() pl.savefig("lower_half.png", bbox_inches='tight') pl.show() exit() res = calcScatteringMatrix(M, P, x) S2 = RTtoS(res["RIn"], res["TIn"], res["TOut"], res["ROut"]) matL = pl.bmat([[pl.diag(pl.sqrt(P.chiIn)), pl.zeros((M.NM, M.NM))], [pl.zeros((M.NM, M.NM)), pl.diag(pl.sqrt(P.chiOut))]]) matR = pl.bmat([[pl.diag(1 / pl.sqrt(P.chiIn)), pl.zeros((M.NM, M.NM))], [pl.zeros((M.NM, M.NM)), pl.diag(1 / pl.sqrt(P.chiOut))]]) S2real = matL * S2 * matR if 0: #Define incident wave as a plane wave einc = pl.zeros((2 * M.NM, 1), dtype='complex').view(pl.matrix) einc[M.NM // 2, 0] = 1. tmp = S2 * einc rnew = tmp[:M.NM].view(pl.ndarray).flatten() tnew = tmp[M.NM:].view(pl.ndarray).flatten() mR, thetaR, Rnew, mT, thetaT, Tnew = calcRT(M, P, rnew, tnew) tmp = S2real * einc r = tmp[:M.NM].view(pl.ndarray).flatten() t = tmp[M.NM:].view(pl.ndarray).flatten() idx = P.propModesIn R = abs(r[idx])**2 idx = P.propModesOut T = abs(t[idx])**2 print "-" * 50 print R print Rnew print T print Tnew print abs(R - Rnew).max() print abs(T - Tnew).max() exit() #Stack the two scattering elements Stot = stackElements(S1, S2) #Define incident wave as a plane wave einc = pl.zeros((2 * M.NM, 1), dtype='complex').view(pl.matrix) einc[M.NM // 2, 0] = 1. tmp = Stot * einc rnew = tmp[:M.NM].view(pl.ndarray).flatten() tnew = tmp[M.NM:].view(pl.ndarray).flatten() mR, thetaR, Rnew, mT, thetaT, Tnew = calcRT(Mres, Pres, rnew, tnew) print("-" * 32) print(Rres) print(Rnew) print("-" * 10) print(Tres) print(Tnew) print("-" * 32) print("Error in reflection : {:.2e}".format(abs(Rnew - Rres).max())) print("Error in transmission: {:.2e}".format(abs(Tnew - Tres).max())) #print("(note: since the significant numbers are in general between 0.01 and 1") #print(" we required a much lower error (1e-6 or better) to confirm that it works)") #Define incident wave as a plane wave einc = pl.zeros((2 * M.NM, 1), dtype='complex').view(pl.matrix) einc[M.NM // 2, 0] = 1. Stotreal = stackElements(S1real, S2real) #Stotreal = S1real if 1: pl.imshow(abs(S1real), interpolation='none', vmin=0, vmax=1) print abs(S1real).max() pl.colorbar() pl.show() pl.imshow(abs(S2real), interpolation='none', vmin=0, vmax=1) print abs(S2real).max() pl.colorbar() pl.show() tmp = Stotreal * einc r = tmp[:M.NM].view(pl.ndarray).flatten() t = tmp[M.NM:].view(pl.ndarray).flatten() idx = Pres.propModesIn R = abs(r[idx])**2 idx = Pres.propModesOut T = abs(t[idx])**2 print "-" * 50 print Rres print Rnew print R print("Error in reflection : {:.2e}".format(abs(R - Rres).max())) print("Error in transmission: {:.2e}".format(abs(T - Tres).max()))
def pade(N, lam0, dlam, M, P, x): N = 2 #The current implementation is only valid for N=2 #diferenctaite all the elemnts of K by k #Fvec has relation to k_0 through alpha - facter hthat #if possible separte Fvec out into elements of facters of alpha #equal to eq 3 in papser, make into coo_matrix for input A, B = P.interpolate(x) Mvv_0 = assembleMvv(A, B, M, P) Mrv_0, Mvr_0, Mtv_0, Mvt_0, fvn_0, frn_0, FFUp_0, FFDown_0 = assembleMxxfx( M, P) Mvv_1 = assembledev1Mvv(A, B, M, P) Mrv_1, Mvr_1, Mtv_1, Mvt_1, fvn_1, frn_1, FFUp_1, FFDown_1 = assembledev1Mxxfx( M, P, FFUp_0, FFDown_0) Mvv_2 = assembledev2Mvv(A, B, M, P) #check fvn. frn Mrv_2, Mvr_2, Mtv_2, Mvt_2, fvn_2, frn_2 = assembledev2Mxxfx( M, P, FFUp_0, FFDown_0, FFUp_1, FFDown_1) # These matrices are just used for checks later on: I = pl.identity(M.NM) #Identity matrix Z = pl.zeros((M.NM, M.NM)) P_0 = pl.bmat([[Mvv_0, Mvr_0, Mvt_0], [Mrv_0, M.lx * I, Z], [Mtv_0, Z, M.lx * I]]) P_1 = pl.bmat([[Mvv_1, Mvr_1, Mvt_1], [Mrv_1, Z, Z], [Mtv_1, Z, Z]]) P_2 = pl.bmat([[Mvv_2, Mvr_2, Mvt_2], [Mrv_2, Z, Z], [Mtv_2, Z, Z]]) #Note that u contains the same content as sol,r and t u = [] sol = [] r = [] t = [] #Note that the LU factorisation on calcvrt0 can be reused for calculating all the u's! #(which would speed up things, but not change the result obviously...) frn_0[M.Nm, 0] = -M.lx #mode 0 incidence ftn_0 = pl.zeros(frn_0.shape, dtype=complex) sol_0, r_0, t_0 = calcvrt0(M, Mvv_0, Mrv_0, Mvr_0, Mtv_0, Mvt_0, fvn_0, frn_0, ftn_0) sol.append(sol_0) r.append(r_0) t.append(t_0) u.append(pl.concatenate((sol_0, r_0, t_0))) if 1: #Check that the solution is correct f = pl.concatenate((fvn_0, frn_0, ftn_0)) print("Solution error for 0'th order: ", abs(P_0 * u[0] - f).max()) _Mvv = Mvv_0 _Mrv = Mrv_0 _Mvr = Mvr_0 _Mtv = Mtv_0 _Mvt = Mvt_0 _fvn = -(Mvv_1 * sol[0] + Mvr_1 * r[0] + Mvt_1 * t[0]) _frn = -(Mrv_1 * sol[0]) _ftn = -(Mtv_1 * sol[0]) sol_1, r_1, t_1 = calcvrt0(M, _Mvv, _Mrv, _Mvr, _Mtv, _Mvt, _fvn, _frn, _ftn) sol.append(sol_1) r.append(r_1) t.append(t_1) u.append(pl.concatenate((sol_1, r_1, t_1))) if 1: print("Solution error for 1'th order: ", abs(P_0 * u[1] + P_1 * u[0]).max()) #This will not work for our implementation since higher order derivates of the matrix is non-zero #And eqn(19) in Jensen 2007 therefore has to be recalculated for our specific case. This is caused by #derivations of the small dense transmission/reflection matrices (Mrv,Mvt and so on) being non-zero if 0: for i in range(2, N + 1): sol_i, r_i, t_i = calcvrt0( M, Mvv_0, Mrv_0, Mvr_0, Mtv_0, Mvt_0, -(Mvv_1 * sol[i - 1] + Mvr_1 * r[i - 1] + Mvt_1 * t[i - 1]) - (Mvv_2 * sol[i - 2] + Mvr_2 * r[i - 2] + Mvt_2 * t[i - 2]), -(Mrv_1 * sol[i - 1]) - (Mrv_2 * sol[i - 2]), -(Mtv_1 * sol[i - 1]) - (Mtv_2 * sol[i - 2])) sol.append(sol_i) r.append(r_i) t.append(t_i) u.append(pl.concatenate((sol_i, r_i, t_i))) sol_N1, r_N1, t_N1 = calcvrt0( M, Mvv_0, Mrv_0, Mvr_0, Mtv_0, Mvt_0, -(Mvv_1 * sol[N] + Mvr_1 * r[N] + Mvt_1 * t[N]) - (Mvv_2 * sol[N - 1] + Mvr_2 * r[N - 1] + Mvt_2 * t[N - 1]), -(Mrv_1 * sol[N]) - (Mrv_2 * sol[N - 1]), -(Mtv_1 * sol[N]) - (Mtv_2 * sol[N - 1])) _fvn = -(Mvv_1 * sol[1] + Mvr_1 * r[1] + Mvt_1 * t[1]) _fvn += -(Mvv_2 * sol[0] + Mvr_2 * r[0] + Mvt_2 * t[0]) _frn = -(Mrv_1 * sol[1]) _frn += -(Mrv_2 * sol[0]) _ftn = -(Mtv_1 * sol[1]) _ftn += -(Mtv_2 * sol[0]) sol_2, r_2, t_2 = calcvrt0(M, _Mvv, _Mrv, _Mvr, _Mtv, _Mvt, _fvn, _frn, _ftn) sol.append(sol_2) r.append(r_2) t.append(t_2) u.append(pl.concatenate((sol_2, r_2, t_2))) if 1: print("Solution error for 2'th order: ", abs(P_0 * u[2] + P_1 * u[1] + P_2 * u[0]).max()) uconjT = pl.bmat([vec.conj() for vec in u[::-2]]).T urev = pl.bmat(u[::-2]) Pmat = uconjT * urev Q = pl.linalg.inv(Pmat) #Check the inversion... Even though it succeeds if 0: print("Pmax:", abs(Pmat).max()) print("P*Q:") print(Pmat * Q) uplus = Q * uconjT b = -uplus * u[N] #Check if b solves the equation we wanted if 1: print("Error for b:", abs(urev * b + u[N]).max()) a = [] a += [0] #If we start summing at 1, then the 0'th element should be zero #b starts at index 1 and not zero in Jensen 2007, there the elements have to be shifted one a += [u[1] + b[0, 0] * u[0]] if N != 2: exit("this part only implemented for N=2") a += [u[2] + b[0, 0] * u[1] + b[1, 0] * u[0]] #List of wavelengths llam = pl.linspace(lam0 - dlam, lam0 + dlam, 81) #List of sigmas with k0 subtracted lsigma = 2 * pl.pi / llam - 2 * pl.pi / lam0 lR = [] for sigma in lsigma: u_nom = u[0] + a[1] * sigma + a[2] * sigma**2 u_denom = 1 + b[0, 0] * sigma + b[1, 0] * sigma**2 usigma = u_nom / u_denom nnodes = (M.nelx + 1) * (M.nelz + 1) solsigma = usigma[:nnodes] rsigma = usigma[nnodes:nnodes + M.NM] tsigma = usigma[nnodes + M.NM:] mR, thetaR, R, mT, thetaT, T = calcRT(M, P, rsigma, tsigma) lR += [float(R[mR == 0])] return llam, lR
def FE(M,P,x,printResults=True): ## FE analysis to solve Maxwell's equations in 2D for either H or E polarisation (=Helmholtz's equation) ## using periodic boundary conditions and wave expansions at the boundaries. The approach was originally ## implemented using Fuchi2010 and later modifications from Dossou2006 (original article) were added # #@param M Model object containing geometrical information #@param P Physics object containing physical parameters #@param x The design domain with 0 corresponding to eps1 and 1 corresponding to eps2 # and intermediate values to weighted averages in between. See physics.interpolate #@param printResults print results to stdout after simulation #@return sol is the discretised solution, r are the complex reflection coefficients # and t are the complex transmission coefficients #Calculate A and B, as the would be given in the Helmholtz equation in Eq (1) in Friis2012. # (this notation makes it easy to switch between E and H field due to duality) A,B = P.interpolate(x) Mvv = assembleMvv(A,B,M,P) Mrv,Mvr,Mtv,Mvt,fvn,frn = assembleMxxfx(M,P) frn[M.Nm,0] = -M.lx #mode 0 lu = splu(Mvv) #Mhatrr and Mhattr b = lu.solve(Mvr) Mhatrr = -Mrv*b _addToDiagonal(Mhatrr, M.lx) Mhattr = -Mtv*b #Mhatrt and Mhattt b = lu.solve(Mvt) Mhatrt = -Mrv*b Mhattt = -Mtv*b _addToDiagonal(Mhattt, M.lx) #fhatrn b = lu.solve(fvn) a = Mrv*b fhatrn = frn-a #fhattn b = lu.solve(fvn) a = Mtv*b fhattn = -a MAT = pl.bmat([[Mhatrr, Mhatrt], [Mhattr, Mhattt]]) RHS = pl.bmat([ [fhatrn],[fhattn]]) V = pl.solve(MAT,RHS) r = V[:M.NM,0] t = V[M.NM:,0] #Solve the system using LU factorisation (as recommended in Dossou2006, p 130, bottom) sol = lu.solve(fvn-Mvr*r-Mvt*t) print(pl.shape(r)) print(pl.shape(t)) print(pl.shape(sol)) r = r.view(pl.ndarray).ravel() t = t.view(pl.ndarray).ravel() #Cast solution into a form that matches the input model sol = sol.reshape(M.nelx+1,M.nelz+1,order='F') #Print simulation results if printResults: _printResultsToScreen(M,P,r,t) print("r") print(r) print(t) print(sol) results = {} results["solution"] = sol results["x"] = x results["r"] = r results["t"] = t results.update(M.getParameters()) results.update(P.getParameters()) return results