00001
00002
00003
00005
00006
00007
00008
00009
00010
00011
00013 #include "Grating2D.h"
00014 #include <string>
00015 #include <iostream>
00016 #include <ctime>
00017 #include "tools.h"
00018
00019 #include "tbci/f_bandmatrix.h"
00020 #include "tbci/matrix.h"
00021
00022 using std::cout;
00023 using std::complex;
00024 using std::cin;
00025 using std::endl;
00026 using TBCI::Vector;
00027 using TBCI::F_Matrix;
00028 using TBCI::CSCMatrix;
00029 using TBCI::lu_invert;
00030
00034 bool memorysave;
00035
00039 Grating2D::Grating2D(int layers)
00040 {
00041 nLayers=layers;
00042
00043 while ((signed) layer.size()<nLayers) layer.push_back(GratingLayer2D());
00044 mu=1.;
00045 setMemsave(true);
00046 }
00047
00048 Grating2D::~Grating2D()
00049 {
00050 }
00051
00055 const Grating2D &Grating2D::operator=(Grating2D &in)
00056 {
00057 setnLayers(in.getnLayers());
00058 setnOrds(in.getnOrds());
00059 setN1(in.getN1());
00060 setN3(in.getN3());
00061 setLambda(in.getLambda());
00062 setPhi(in.getPhi());
00063 setTheta(in.getTheta());
00064 setSizeY(in.getSizeY());
00065 setSizeX(in.getSizeX());
00066 incid.resize(in.incid);
00067
00068 setMemsave(in.getMemsave());
00069
00070 R.resize(in.R);
00071 T.resize(in.T);
00072 Q12.resize(in.Q12);
00073 Q2.resize(in.Q2);
00074 tau.resize(in.tau);
00075 T_tilde.resize(in.T_tilde);
00076 R_tilde.resize(in.R_tilde);
00077 G.resize(in.G);
00078 W21.resize(in.G);
00079 W23.resize(in.W23);
00080 alpha_1.resize(in.alpha_1);
00081 alpha_3.resize(in.alpha_3);
00082 beta_1.resize(in.beta_1);
00083 beta_3.resize(in.beta_3);
00084 gamma_1.resize(in.gamma_1);
00085 gamma_3.resize(in.gamma_3);
00086 k1=in.k1;
00087 k3=in.k3;
00088
00089 trans.resize(in.trans);
00090 ref.resize(in.ref);
00091 efficiencyR.resize(in.efficiencyR);
00092 efficiencyT.resize(in.efficiencyT);
00093
00094 for (int l=0;l<getnLayers();l++) layer[l]=in.layer[l];
00095
00096 return *this;
00097 }
00098
00099
00103 void Grating2D::minimiseMemory(void)
00104 {
00105 Q12.resize(0);
00106 Q2.resize(0);
00107 tau.resize(0);
00108 T_tilde.resize(0);
00109 R_tilde.resize(0);
00110 G.resize(0);
00111 W21.resize(0);
00112 W23.resize(0);
00113 for (int l=0;l<nLayers;l++) layer[l].minimiseMemory();
00114 }
00127 void Grating2D::setParameters(int ords, double pX, double pY, Vector<double> thick, double lam, double angleZ, double angleX, complex<double> ref1, complex<double> ref3)
00128 {
00129 setnOrds(ords);
00130 setSizeX(pX);
00131 setSizeY(pY);
00132 setLambda(lam);
00133 setTheta(angleZ);
00134 setPhi(angleX);
00135 setN1(ref1);
00136 setN3(ref3);
00137 for (int i=0;i<nLayers;i++)
00138 {
00139 layer[i].setParameters(nOrds, periodX, periodY, thick[i], lambda, theta, phi, n1);
00140 }
00141 calcAlphaBetaGamma();
00142 }
00143
00144 void Grating2D::setTransPt(Vector<double> tX, Vector<double> tY)
00145 {
00146 for (int i=0;i<nLayers;i++) layer[i].setTransPt(tX,tY);
00147 }
00148
00152 void Grating2D::setTransPt()
00153 {
00154 double pX,pY;
00155 Vector<double> tX, tY;
00156 for (int l=0;l<nLayers;l++)
00157 {
00158 tX.resize(layer[l].getnPixelsX());
00159 tY.resize(layer[l].getnPixelsY());
00160
00161 pX=periodX/tX.size();
00162 pY=periodY/tY.size();
00163 for (unsigned int i=0;i<tX.size();i++) tX[i]=pX*(i+1);
00164 for (unsigned int i=0;i<tY.size();i++) tY[i]=pY*(i+1);
00165 layer[l].setTransPt(tX,tY);
00166 }
00167 }
00168
00169
00170 void Grating2D::setRefInd(vector< Matrix< complex<double> > > N)
00171 {
00172 for (int i=0;i<nLayers;i++) layer[i].setRefInd(N[i]);
00173 }
00174
00175
00176
00177 void Grating2D::setMemsave(bool b)
00178 {
00179 memorysave=b;
00180 for (int i=0;i<nLayers;i++)
00181 {
00182 layer[i].memsave(b);
00183 }
00184 }
00185 bool Grating2D::getMemsave(void) {return memorysave;}
00186
00187
00188 double Grating2D::getSizeX(void){return periodX;}
00189 void Grating2D::setSizeX(double d)
00190 {
00191 periodX=d;
00192 for (int l=0;l<nLayers;l++) layer[l].setSizeX(periodX);
00193 }
00194 double Grating2D::getSizeY(void){return periodY;}
00195 void Grating2D::setSizeY(double d)
00196 {
00197 periodY=d;
00198 for (int l=0;l<nLayers;l++) layer[l].setSizeY(periodY);
00199 }
00200
00201 int Grating2D::getnLayers(void){return nLayers;}
00202
00207 void Grating2D::setnLayers(int l)
00208 {
00209 nLayers=layer.size();
00210
00211 if (l<nLayers) while ((signed) layer.size()>l) layer.pop_back();
00212
00213 if (l>nLayers) while ((signed) layer.size()<l) layer.push_back(GratingLayer2D());
00214 nLayers=l;
00215 }
00216
00221 double Grating2D::getLambda(void){return lambda;}
00222 void Grating2D::setLambda(double d)
00223 {
00224 lambda=d;
00225 k1=2.*real(n1)*M_PI/lambda;
00226 k3=2.*real(n3)*M_PI/lambda;
00227 for (unsigned int l=0;l<layer.size();l++) layer[l].setLambda(lambda);
00228 }
00229 double Grating2D::getTheta(void){return theta*180./M_PI;}
00230 void Grating2D::setTheta(double d)
00231 {
00232 theta=M_PI/180.*d;
00233 for (unsigned int l=0;l<layer.size();l++) layer[l].setTheta(d);
00234 }
00235
00236 double Grating2D::getPhi(void){return phi*180./M_PI;}
00237 void Grating2D::setPhi(double d)
00238 {
00239 phi=M_PI/180.*d;
00240 for (unsigned int l=0;l<layer.size();l++) layer[l].setPhi(d);
00241 }
00242 complex<double>Grating2D::getN1(void){return n1;}
00243 void Grating2D::setN1(complex<double>c)
00244 {
00245 n1=c;
00246 k1=2.*real(n1)*M_PI/lambda;
00247 for (unsigned int l=0;l<layer.size();l++) layer[l].setN1(c);
00248 }
00249 complex<double>Grating2D::getN3(void){return n3;}
00250 void Grating2D::setN3(complex<double>c)
00251 {
00252 n3=c;
00253 k3=2.*real(n3)*M_PI/lambda;
00254 }
00255
00256 int Grating2D::getnOrds(void) {return nOrds;}
00257 void Grating2D::setnOrds(int ords)
00258 {
00259 if (ords%2==0)
00260 {
00261 cout<<"Attempt to set nOrds to an even number ("<<ords<<"), an odd number is required, set nOrds to "<<ords+1<<endl;
00262 nOrds=ords+1;
00263 }
00264 nOrds=ords;
00265 nOrdsSq=nOrds*nOrds;
00266 for (unsigned int i=0;i<layer.size();i++) layer[i].setnOrds(nOrds);
00267 }
00268
00274 complex<double> Grating2D::getReflection(string pol, int row, int column)
00275 {
00276 if ((pol=="X")||(pol=="x")) return ref[row*nOrds+column];
00277 if ((pol=="Y")||(pol=="y")) return ref[row*nOrds+column+nOrdsSq];
00278 else
00279 {
00280
00281 return 0.;
00282 }
00283 }
00284
00290 complex<double> Grating2D::getTransmission(string pol, int row, int column)
00291 {
00292 if ((pol=="X")||(pol=="x")) return trans[row*nOrds+column];
00293 if ((pol=="Y")||(pol=="y")) return trans[row*nOrds+column+nOrdsSq];
00294 else
00295 {
00296
00297 return 0.;
00298 }
00299 }
00300
00306 complex<double> Grating2D::getIncid(string pol, int row, int column)
00307 {
00308 if ((pol=="X")||(pol=="x")) return incid[row*nOrds+column];
00309 if ((pol=="Y")||(pol=="y")) return incid[row*nOrds+column+nOrdsSq];
00310 else return 0.;
00311 }
00312
00320 complex<double> Grating2D::getR(int a, int b){return R(a,b);}
00328 complex<double> Grating2D::getT(int a, int b){return T(a,b);}
00329
00333 complex<double> Grating2D::getAlphaT(int n){return alpha_3[n];}
00337 complex<double> Grating2D::getBetaT(int n){return beta_3[n];}
00341 complex<double> Grating2D::getAlphaR(int n){return alpha_1[n];}
00345 complex<double> Grating2D::getBetaR(int n){return beta_1[n];}
00346
00347
00353 void Grating2D::setIncid(Matrix< complex<double> >x, Matrix< complex<double> >y)
00354 {
00355 if (signed(incid.size())!=2*nOrdsSq) incid.resize(2*nOrdsSq);
00356 complex<double> normalise;
00357 for (int i=0;i<nOrds;i++)
00358 {
00359 for (int j=0;j<nOrds;j++)
00360 {
00361 incid[i*nOrds+j]=x(i,j);
00362 incid[i*nOrds+j+nOrdsSq]=y(i,j);
00363 }
00364 }
00365
00366
00367 normalise = 1./gamma_1[(nOrds-1)/2*nOrds+(nOrds-1)/2]*((k1-beta_1[(nOrds-1)/2])*norm(incid[(nOrds-1)/2*nOrds+(nOrds-1)/2])+(k1-alpha_1[(nOrds-1)/2])*norm(incid[(nOrds-1)/2*nOrds+(nOrds-1)/2+nOrdsSq])+alpha_1[(nOrds-1)/2]*beta_1[(nOrds-1)/2]*(incid[(nOrds-1)/2*nOrds+(nOrds-1)/2]*conj(incid[(nOrds-1)/2*nOrds+(nOrds-1)/2+nOrdsSq])+incid[(nOrds-1)/2*nOrds+(nOrds-1)/2+nOrdsSq]*conj(incid[(nOrds-1)/2*nOrds+(nOrds-1)/2])));
00368
00369 incid[(nOrds-1)/2*nOrds+(nOrds-1)/2]/=sqrt(normalise);
00370 incid[(nOrds-1)/2*nOrds+(nOrds-1)/2+nOrdsSq]/=sqrt(normalise);
00371 }
00372
00377 Matrix< complex<double> > Grating2D::getIncid(string pol)
00378 {
00379 Matrix< complex<double> > in(nOrds,nOrds);
00380 for (int i=0;i<nOrds;i++)
00381 {
00382 for (int j=0;j<nOrds;j++)
00383 {
00384 in(i,j)=incid[i*nOrds+j+(pol=="y"?nOrdsSq:0)];
00385 }
00386 }
00387 return in;
00388 }
00389
00390
00391 void Grating2D::solve()
00392 {
00393 for (int l=0;l<nLayers;l++) layer[l].solve();
00394 setSMatrix();
00395 calcEfficiencyR();
00396 calcEfficiencyT();
00397 }
00398
00399
00403 void Grating2D::calcAlphaBetaGamma(void)
00404 {
00405 if ((signed int)alpha_1.size()!=nOrds) alpha_1.resize(0.,nOrds);
00406 if ((signed int)alpha_3.size()!=nOrds) alpha_3.resize(0.,nOrds);
00407 if ((signed int)beta_1.size()!=nOrds) beta_1.resize(0.,nOrds);
00408 if ((signed int)beta_3.size()!=nOrds) beta_3.resize(0.,nOrds);
00409 if ((signed int)gamma_1.size()!=nOrdsSq) gamma_1.resize(0.,nOrdsSq);
00410 if ((signed int)gamma_3.size()!=nOrdsSq) gamma_3.resize(0.,nOrdsSq);
00411
00412 for (int i=0;i<nOrds;i++)
00413 {
00414 alpha_3[i]=2.*M_PI/lambda*n3*sin(theta)*cos(phi)+(i-(nOrds-1)/2)*2.*M_PI/periodX;
00415 alpha_1[i]=2.*M_PI/lambda*n3*sin(theta)*cos(phi)+(i-(nOrds-1)/2)*2.*M_PI/periodX;
00416 beta_3[i]=2.*M_PI/lambda*n3*sin(theta)*sin(phi)+(i-(nOrds-1)/2)*2.*M_PI/periodY;
00417 beta_1[i]=2.*M_PI/lambda*n3*sin(theta)*sin(phi)+(i-(nOrds-1)/2)*2.*M_PI/periodY;
00418 }
00419
00420 for (int i=0;i<nOrdsSq;i++)
00421 {
00422 gamma_3[i]=sqrt(pow(2.*M_PI/lambda*n3,2)-alpha_3[i/nOrds]*alpha_3[i/nOrds]-beta_3[i%nOrds]*beta_3[i%nOrds]);
00423 gamma_1[i]=sqrt(pow(2.*M_PI/lambda*n1,2)-alpha_1[i/nOrds]*alpha_1[i/nOrds]-beta_1[i%nOrds]*beta_1[i%nOrds]);
00424 if ( (real(gamma_1[i])+imag(gamma_1[i]))<0 ) gamma_1[i]*=-1.;
00425 if ( (real(gamma_3[i])+imag(gamma_3[i]))<0 ) gamma_3[i]*=-1.;
00426 }
00427
00428 }
00429
00430 void Grating2D::calcBoundaryW(void)
00431 {
00432 complex<double> eps=n3*n3;
00433
00434
00435 W23.resize(0.,2*nOrdsSq, 2*nOrdsSq);
00436 for (int i=0;i<nOrdsSq;i++)
00437 {
00438 W23(i,i)=-alpha_3[(i%nOrdsSq)/nOrds]*beta_3[i%nOrds]/(sqrt(mu)*k1*gamma_3[i]);
00439 W23(i+nOrdsSq,i+nOrdsSq)=(alpha_3[(i%nOrdsSq)/nOrds]*beta_3[i%nOrds])/(sqrt(mu)*k1*gamma_3[i]);
00440 W23(i,i+nOrdsSq)=(alpha_3[i/nOrds]*alpha_3[i/nOrds]-mu*k1*k1*n3*n3)/(sqrt(mu)*k1*gamma_3[i]);
00441 W23(i+nOrdsSq,i)=(mu*k1*k1*n3*n3-beta_3[i%nOrds]*beta_3[i%nOrds])/(sqrt(mu)*k1*gamma_3[i]);
00442 }
00443 W23=invert(W23);
00444 }
00445
00449 void Grating2D::setSMatrix(void)
00450 {
00451 Matrix< complex<double> > unit(2*nOrdsSq,2*nOrdsSq),T_tilde(2*nOrdsSq,2*nOrdsSq);
00452 unit.setunit();
00453 Vector < complex<double> > expTerm(2*nOrdsSq);
00454
00455 calcBoundaryW();
00456
00457
00458 GratingLayer2D dummy;
00459 Matrix< complex<double> > dummyn;
00460 dummyn.resize(1,1);
00461 dummy.setParameters(nOrds, periodX, periodY, 0., lambda, theta, phi, n1);
00462 dummyn(0,0)=n1;
00463 dummy.setRefInd(dummyn);
00464 dummy.solveHomogeneous();
00465
00466 if ((signed int)R.size()!=pow(2*nOrdsSq,2)) R.resize(0.,2*nOrdsSq,2*nOrdsSq);
00467 if ((signed int)R_tilde.size()!=pow(2*nOrdsSq,2)) R_tilde.resize(0.,2*nOrdsSq, 2*nOrdsSq);
00468 if ((signed int)T.size()!=pow(2*nOrdsSq,2)) T.resize(0,2*nOrdsSq, 2*nOrdsSq);
00469 if ((signed int)G.size()!=pow(2*nOrdsSq,2)) G.resize(0.,2*nOrdsSq, 2*nOrdsSq);
00470 if ((signed int)tau.size()!=pow(2*nOrdsSq,2)) tau.resize(0.,2*nOrdsSq, 2*nOrdsSq);
00471 if ((signed int)Q12.size()!=pow(2*nOrdsSq,2)) Q12.resize(0.,2*nOrdsSq,2*nOrdsSq);
00472 if ((signed int)Q2.size()!=pow(2*nOrdsSq,2)) Q2.resize(0.,2*nOrdsSq,2*nOrdsSq);
00473 if ((signed int)trans.size()!=2*nOrdsSq) trans.resize(0.,2*nOrdsSq);
00474 if ((signed int)ref.size()!=2*nOrdsSq) ref.resize(0.,2*nOrdsSq);
00475 T.setunit();
00476 R.fill(0.);
00477 R_tilde.fill(0.);
00478 Q2=layer[0].invEigVecH*dummy.eigVecH;
00479
00480
00481 Q12=layer[0].invEigVecE*dummy.eigVecE+Q2;
00482 tau=invert(Q12);
00483
00484
00485 for (int j=0;j<2*nOrdsSq;j++)
00486 {
00487 expTerm(j)=exp(I*dummy.getGamma(j)*dummy.getThickness());
00488 }
00489
00490
00491 R=unit-complex<double>(2.,0.)*Q2*tau;
00492 T=complex<double>(2.)*T;
00493 T.mult_rows(expTerm);
00494 T=T*tau;
00495
00496 for (int i=0;i<nLayers;i++)
00497 {
00498
00499 for (int j=0;j<2*nOrdsSq;j++)
00500 {
00501 expTerm(j)=exp(I*layer[i].getGamma(j)*layer[i].getThickness());
00502 }
00503 G=0.; tau=0.;
00504 R_tilde=multFrontBack(R,expTerm);
00505
00506 if (i<nLayers-1)
00507 {
00508 G=layer[i+1].invEigVecH*layer[i].eigVecH*(unit-R_tilde);
00509 tau=layer[i+1].invEigVecE*layer[i].eigVecE*(unit+R_tilde)+G;
00510 tau=invert(tau);
00511 }
00512 else
00513 {
00514 G=W23*layer[i].eigVecH*(unit-R_tilde);
00515 tau=layer[i].eigVecE*(unit+R_tilde)+G;
00516 tau=invert(tau);
00517 }
00518 R=unit-complex<double>(2.)*G*tau;
00519 T=complex<double>(2.)*multFront(T,expTerm)*tau;
00520
00521 }
00522
00523 trans=T*incid;
00524 ref=R*incid;
00525
00526
00527 if (memorysave)
00528 {
00529 R_tilde.resize(0);
00530 T_tilde.resize(0);
00531 Q12.resize(0);
00532 Q2.resize(0);
00533 G.resize(0);
00534 tau.resize(0);
00535 }
00536 }
00537
00538 void Grating2D::calcEfficiencyR()
00539 {
00540 double e=0.;
00541 efficiencyR.resize(nOrds, nOrds);
00542 for (int m=0;m<nOrds;m++)
00543 {
00544 for (int n=0;n<nOrds;n++)
00545 {
00546 efficiencyR(m,n)=1./gamma_1[m*nOrds+n]*(
00547 (k1*k1-beta_1[n]*beta_1[n])*norm(getReflection("x",m,n))+(k1*k1-alpha_1[m]*alpha_1[m])*norm(getReflection("y",m,n))+alpha_1[m]*beta_1[n]*(getReflection("x",m,n)*conj(getReflection("y",m,n))+getReflection("y",m,n)*conj(getReflection("x",m,n))));
00548 e+=abs(efficiencyR(m,n));
00549 }
00550 }
00551 }
00552
00553 void Grating2D::calcEfficiencyT()
00554 {
00555 double e=0.;
00556 efficiencyT.resize(nOrds, nOrds);
00557 for (int m=0;m<nOrds;m++)
00558 {
00559 for (int n=0;n<nOrds;n++)
00560 {
00561 efficiencyT(m,n)=1./gamma_3[m*nOrds+n]*((k3*k3-beta_3[n]*beta_3[n])*norm(getTransmission("x",m,n))+(k3*k3-alpha_3[m]*alpha_3[m])*norm(getTransmission("y",m,n))+alpha_3[m]*beta_3[n]*(getTransmission("x",m,n)*conj(getTransmission("y",m,n))+getTransmission("y",m,n)*conj(getTransmission("x",m,n))));
00562 e+=abs(efficiencyT(m,n));
00563 }
00564 }
00565 }
00566
00574 complex<double> Grating2D::calcTransField(double x, double y, double z, string pol)
00575 {
00576 complex<double> f=0, f2=0;
00577 if (pol=="x")
00578 {
00579 for (int i=0;i<nOrdsSq;i++)
00580 {
00581 f+= trans[i]*exp(I*(alpha_3[i/nOrds]*x+beta_3[i%nOrds]*y-gamma_3[i]*z));
00582 }
00583 }
00584 else if (pol=="y")
00585 {
00586 for (int i=0;i<nOrdsSq;i++)
00587 {
00588 f+= trans[i+nOrdsSq]*exp(I*(alpha_3[i/nOrds]*x+beta_3[i%nOrds]*y-gamma_3[i]*z));
00589 }
00590 }
00591 return f;
00592 }
00601 void Grating2D::writeField(string filename, string refTrans, string pol, double z, int pointsX, int pointsY)
00602 {
00603 ofstream out;
00604 complex<double> c;
00605 out.open((filename+".dat").c_str());
00606 for (int i=0;i<pointsX;i++)
00607 {
00608 for (int j=0;j<pointsY;j++)
00609 {
00610 c=calcTransField((1.*i)/pointsX*periodX, (1.*j)/pointsY*periodY, z, pol);
00611 if (refTrans=="t") out << norm(c) <<"\t";
00612 }
00613 out<<endl;
00614 }
00615 out.close();
00616 }
00617
00618 void Grating2D::writeParameters(string filename)
00619 {
00620 ofstream out;
00621 out.open((filename).c_str());
00622 out<<"Lambda=\t"<<lambda<<endl;
00623 out<<"Phi=\t"<<phi<<endl;
00624 out<<"Theta=\t"<<theta<<endl;
00625 out<<"n1=\t"<<real(n1)<<"\t"<<imag(n1)<<endl;
00626 out<<"n3=\t"<<real(n3)<<"\t"<<imag(n3)<<endl;
00627 out<<"PeriodX=\t"<<periodX<<endl;
00628 out<<"PeriodY=\t"<<periodY<<endl;
00629 out<<"nOrds=\t"<<nOrds<<endl;
00630 out<<"nPixelsX=\t"<<layer[0].getnPixelsX()<<endl;
00631 out<<"nPixelsY=\t"<<layer[0].getnPixelsY()<<endl;
00632 out <<"\n\nREFRACTIVE INDEX\n";
00633 for (unsigned int i=0;i<layer[0].getRefInd().rows();i++)
00634 {
00635 for (unsigned int j=0;j<layer[0].getRefInd().columns();j++)
00636 {
00637 out<<real(layer[0].getRefInd(i,j))<<"\t"<<imag(layer[0].getRefInd(i,j))<<endl;
00638 }
00639 }
00640 out<<"\n\nTRANSMISSION ORDERS\n";
00641 for (int i=0;i<2*nOrdsSq;i++) out<<real(trans[i])<<"\t"<<imag(trans[i])<<endl;
00642 out<<"\n\nREFLECTION ORDERS\n";
00643 for (int i=0;i<2*nOrdsSq;i++) out<<real(ref[i])<<"\t"<<imag(ref[i])<<endl;
00644 out.close();
00645 }
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 double Grating2D::delta(int i, int j){return ((i==j)?1.:0.);}