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

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

u(x')是原鏡面上的場分布。通過公式求出到達另一鏡面上的場分布u(x),通過不斷迭代計算,當u(x)趨于穩(wěn)定時,就得到了自再現(xiàn)模。這里我們設初始u(x)=1。其中a為腔鏡半寬度,L為腔長,k是波矢量。具體迭代操作就是,將-a到a的積分區(qū)間分割,初始u(x)=1,要求新的u(x),就是對[-a,a]上每一分割點都基于公式,將積分轉換為累加計算得到,對得到的u(x)回代又能得到新的u(x),設置迭代100次,基本就能得到穩(wěn)定的分布。
安卓實現(xiàn)
復數(shù)類
由于上面公式的數(shù)據(jù)是復數(shù)類型的,而Java沒有這種數(shù)據(jù)類型,所以只能自己定義復數(shù)類,實際就是在這個類中包含兩個double類型數(shù)據(jù),一個表示實部,一個表示虛部,和各種方法用于后面進行操作,根據(jù)需要,我設置的方法有,重寫toString方法、加法運算、乘法運算(為操作方便分別定義了與復數(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)方法
由公式可以知道,我們需要進行exp和sqrt計算。由于Math中的exp和sqrt方法都只能對double類型進行操作,所以需要自定義這兩個方法,用于對復數(shù)類進行計算。對于exp方法,可以基于歐拉公式:exp(a+bi)=exp(a)(cosb+isinb)。而sqrt方法,則可以這樣得到:設(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;
}
還需要定義復數(shù)求模方法abs()和歸一化方法normalize()。定義完就可以進行迭代計算了。
自定義View類
完成上面數(shù)據(jù)計算工作,為了繪制曲線,就需要自定義View,以實現(xiàn)繪制振幅曲線。具體就是將前面計算得到的[-a,a]間的每一分割點的振幅大小顯示出來。先把x軸上每一分割點與相應的y坐標一一對應起來,注意,y軸是屏幕由上向下增大的,為方便觀看,應當是振幅越大,y坐標值越小。然后調用canvas的drawLine方法連接每個點,得到曲線。
在MainActivity中,自定義一個線程,實現(xiàn)每完成一次迭代計算,更新一次主線程UI顯示就能實現(xiàn)迭代過程的振幅分布曲線動態(tài)顯示。效果如下:





后面還可以通過設置編輯框來改變鏡寬和腔長等參量,進一步觀察效果,以及繪制坐標值等。