之前用過Matlab軟件,采用了Fox-Li數(shù)值迭代法對(duì)平行平面腔的自再現(xiàn)模過程進(jìn)行模擬,得到穩(wěn)定模式的振幅分布,對(duì)自再現(xiàn)模進(jìn)行過相應(yīng)研究。最近在學(xué)習(xí)安卓過程中,便想也通過寫一個(gè)app來實(shí)現(xiàn),鍛煉下自己,也可進(jìn)一步加深理解。
自再現(xiàn)模
光波在平面腔內(nèi)往返傳播,每次傳播橫向場(chǎng)分布即橫模都將受到一定的約束,產(chǎn)生一定的改變。當(dāng)多次傳播后,場(chǎng)分布不再改變,此時(shí)的橫模就稱為自再現(xiàn)模。圖解如下:

條形鏡的自再現(xiàn)模
通過菲涅耳——基爾霍夫衍射公式推導(dǎo)出自再現(xiàn)模公式,得到條形鏡的自再現(xiàn)模公式如下:

u(x')是原鏡面上的場(chǎng)分布。通過公式求出到達(dá)另一鏡面上的場(chǎng)分布u(x),通過不斷迭代計(jì)算,當(dāng)u(x)趨于穩(wěn)定時(shí),就得到了自再現(xiàn)模。這里我們?cè)O(shè)初始u(x)=1。其中a為腔鏡半寬度,L為腔長(zhǎng),k是波矢量。具體迭代操作就是,將-a到a的積分區(qū)間分割,初始u(x)=1,要求新的u(x),就是對(duì)[-a,a]上每一分割點(diǎn)都基于公式,將積分轉(zhuǎn)換為累加計(jì)算得到,對(duì)得到的u(x)回代又能得到新的u(x),設(shè)置迭代100次,基本就能得到穩(wěn)定的分布。
安卓實(shí)現(xiàn)
復(fù)數(shù)類
由于上面公式的數(shù)據(jù)是復(fù)數(shù)類型的,而Java沒有這種數(shù)據(jù)類型,所以只能自己定義復(fù)數(shù)類,實(shí)際就是在這個(gè)類中包含兩個(gè)double類型數(shù)據(jù),一個(gè)表示實(shí)部,一個(gè)表示虛部,和各種方法用于后面進(jìn)行操作,根據(jù)需要,我設(shè)置的方法有,重寫toString方法、加法運(yùn)算、乘法運(yùn)算(為操作方便分別定義了與復(fù)數(shù)間的和與實(shí)數(shù)間的乘法)、以及實(shí)部與虛部數(shù)據(jù)的get和set。
public class Complex {
private double real;
private double img;
public Complex(double real,double img){
this.real = real;
this.img = img;
}
public Complex(double real){
this.real = real;
img = 0;
}
public Complex(){
real = 0;
img = 0;
}
@Override
public String toString() {
return real+" + "+img+"i";
}
public Complex plus(Complex b){
return new Complex(this.real+b.real,this.img+b.img);
}
public Complex multiply(double b){
return new Complex(this.real*b,this.img*b);
}
public Complex multiply(Complex c) {
double a = this.real;
double b = this.img;
double d = c.getReal();
double e = c.getImg();
return new Complex(a * d - b * e, a * e + b * d);
}
public double getReal(){
return this.real;
}
public double getImg(){
return this.img;
}
public void setReal(double real){
this.real = real;
}
public void setImg(double img){
this.img = img;
}
}
exp(Complex c)和sqrt(Complex c)方法
由公式可以知道,我們需要進(jìn)行exp和sqrt計(jì)算。由于Math中的exp和sqrt方法都只能對(duì)double類型進(jìn)行操作,所以需要自定義這兩個(gè)方法,用于對(duì)復(fù)數(shù)類進(jìn)行計(jì)算。對(duì)于exp方法,可以基于歐拉公式:exp(a+bi)=exp(a)(cosb+isinb)。而sqrt方法,則可以這樣得到:設(shè)(m+ni)(m+ni)=(a+bi),得到m2-n2=a,2mn=b。求解得到用a,b表示的m和n,代碼如下:
public Complex exp(Complex c){
Complex result = new Complex();
double a = c.getReal();
double b = c.getImg();
double expa = Math.exp(a);
result.setImg(expa*Math.sin(b));
result.setReal(expa*Math.cos(b));
return result;
}
public Complex sqrt(Complex c){
Complex result = new Complex();
double a = c.getReal();
double b = c.getImg();
//result = m + ni;
double m = Math.sqrt((a+Math.sqrt(a*a+b*b))/2);
double n = b/(2*m);
result.setReal(m);
result.setImg(n);
return result;
}
還需要定義復(fù)數(shù)求模方法abs()和歸一化方法normalize()。定義完就可以進(jìn)行迭代計(jì)算了。
自定義View類
完成上面數(shù)據(jù)計(jì)算工作,為了繪制曲線,就需要自定義View,以實(shí)現(xiàn)繪制振幅曲線。具體就是將前面計(jì)算得到的[-a,a]間的每一分割點(diǎn)的振幅大小顯示出來。先把x軸上每一分割點(diǎn)與相應(yīng)的y坐標(biāo)一一對(duì)應(yīng)起來,注意,y軸是屏幕由上向下增大的,為方便觀看,應(yīng)當(dāng)是振幅越大,y坐標(biāo)值越小。然后調(diào)用canvas的drawLine方法連接每個(gè)點(diǎn),得到曲線。
在MainActivity中,自定義一個(gè)線程,實(shí)現(xiàn)每完成一次迭代計(jì)算,更新一次主線程UI顯示就能實(shí)現(xiàn)迭代過程的振幅分布曲線動(dòng)態(tài)顯示。效果如下:





后面還可以通過設(shè)置編輯框來改變鏡寬和腔長(zhǎng)等參量,進(jìn)一步觀察效果,以及繪制坐標(biāo)值等。