基于安卓模拟平面腔自再现模振幅分布

之前用过Matlab软件,采用了Fox-Li数值迭代法对平行平面腔的自再现模过程进行模拟,得到稳定模式的振幅分布,对自再现模进行过相应研究。最近在学习安卓过程中,便想也通过写一个app来实现,锻炼下自己,也可进一步加深理解。


自再现模

光波在平面腔内往返传播,每次传播横向场分布即横模都将受到一定的约束,产生一定的改变。当多次传播后,场分布不再改变,此时的横模就称为自再现模。图解如下:

基于安卓模拟平面腔自再现模振幅分布_第1张图片
自再现模.jpg

条形镜的自再现模

通过菲涅耳——基尔霍夫衍射公式推导出自再现模公式,得到条形镜的自再现模公式如下:

条形镜自再现模公式.png

u(x')是原镜面上的场分布。通过公式求出到达另一镜面上的场分布u(x),通过不断迭代计算,当u(x)趋于稳定时,就得到了自再现模。这里我们设初始u(x)=1。 其中a为腔镜半宽度,L为腔长,k是波矢量。具体迭代操作就是,将-a到a的积分区间分割,初始u(x)=1,要求新的u(x),就是对[-a,a]上每一分割点都基于公式,将积分转换为累加计算得到,对得到的u(x)回代又能得到新的u(x),设置迭代100次,基本就能得到稳定的分布。

安卓实现

复数类

由于上面公式的数据是复数类型的,而Java没有这种数据类型,所以只能自己定义复数类,实际就是在这个类中包含两个double类型数据,一个表示实部,一个表示虚部,和各种方法用于后面进行操作,根据需要,我设置的方法有,重写toString方法、加法运算、乘法运算(为操作方便分别定义了与复数间的和与实数间的乘法)、以及实部与虚部数据的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类型进行操作,所以需要自定义这两个方法,用于对复数类进行计算。对于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;  
   }  

还需要定义复数求模方法abs()和归一化方法normalize()。定义完就可以进行迭代计算了。

自定义View类

完成上面数据计算工作,为了绘制曲线,就需要自定义View,以实现绘制振幅曲线。具体就是将前面计算得到的[-a,a]间的每一分割点的振幅大小显示出来。先把x轴上每一分割点与相应的y坐标一一对应起来,注意,y轴是屏幕由上向下增大的,为方便观看,应当是振幅越大,y坐标值越小。然后调用canvas的drawLine方法连接每个点,得到曲线。


在MainActivity中,自定义一个线程,实现每完成一次迭代计算,更新一次主线程UI显示就能实现迭代过程的振幅分布曲线动态显示。效果如下:


基于安卓模拟平面腔自再现模振幅分布_第2张图片
1.jpg
基于安卓模拟平面腔自再现模振幅分布_第3张图片
2.jpg
基于安卓模拟平面腔自再现模振幅分布_第4张图片
3.jpg
基于安卓模拟平面腔自再现模振幅分布_第5张图片
4.jpg
基于安卓模拟平面腔自再现模振幅分布_第6张图片
matlab模拟的图.png

后面还可以通过设置编辑框来改变镜宽和腔长等参量,进一步观察效果,以及绘制坐标值等。

你可能感兴趣的:(基于安卓模拟平面腔自再现模振幅分布)