Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calculate the power( ratio) in the bucket and times the diffraction limit #80

Open
tianjiaoshanzai opened this issue Nov 26, 2023 · 0 comments

Comments

@tianjiaoshanzai
Copy link

tianjiaoshanzai commented Nov 26, 2023

Hello, @FredvanGoor

I am simulating the calculation of a circular aperture beam passing through a lens and converging at the focal plane. I want to calculate what is the radius of the spot when the energy in the barrel at the focal plane is 83.9%. And calculate its times of the diffraction limit.

If the diameter of the center of the first dark ring (Airy disk) of a Fraunhofer diffraction pattern is taken as the diffraction limit diameter.Theoretically, When focused through an ideal lens to the focal plane, the measured ideal diffraction limit diameter should be $d_{difflimit} =\theta _{difflimit} *f$ = $2.44 * λ * f / D$, where λ is the wavelength, f is the focal length, and D is the diameter of the circular aperture.[1]

$$u_{\mathrm{~ref}}=\frac{\int_{0}^{2\pi}\int_{0}^{d_{u,\mathrm{ref}}/2 }I\left(r\right)\mathrm{d}r\mathrm{d}\theta}{\iint I\left(r\right)\mathrm{d}r\mathrm{d}\theta}$$

Formula 1

According to Formula 1, it can be calculated that $u_{ref}$ =0.839,when $d_{u,\mathrm{ref}}$ is taken as diffraction limit diameter metioned above

There are some details for $u_{ref}$

According to Fraunhofer diffraction theory, the far-field intensity distribution of the reference beam with radius $r$ is calculated in paraximal approximation see A.1

$$I\left(r\right)=I_0\left\lbrace\frac{2J_{1}\left[\pi d_{u,near}r/\left(f\lambda\right)\right]}{\pi d_{u,near}r/\left(f\lambda\right)}-\varepsilon^2\frac{2J_{1}\left[\pi\varepsilon d_{u,near}r/\left(f\lambda\right)\right]}{\pi\varepsilon d_{u,near}r/\left(f\lambda\right)}\right\rbrace^2\cdots\cdots\cdots\cdots(\text{ A.}1)$$

$I_{0}$ -- the reference beam far-field peak intensity;
$J_{1}$ -- first-order Bessel function;
$d_\mathrm{u.near}$ -- reference beam near-field beam diameter;
$f$ -- device equivalent focal length;
$\lambda$ -- actual beam laser wavelength;
$\varepsilon$ - center blocking ratio. (center circle area as a proportion of total area)

Let $I(r)=0$, the positional equation to be satisfied by the zero radius of the circular beam intensity is given in Eq. (A.2).

$J_1[\pi d_\text{u.near}r/(f\lambda)]-\varepsilon J_1[\pi\varepsilon d_\text{u,near}r/(f\lambda)]=0\quad........................( A.2 )$

According to Formula 1, when $\varepsilon$ = 0, it can be calculated that c=2.44, $u_{ref}$ =0.839

So the calculation result we would expect should be $\beta = d_{simulate}/d_{therory} =1 $,where $d_{simulate}$ is the circular diameter of the region that accounts for 83.9% of the total energy in the simulation results,and $d_{therory}$ = $2.44 * F.lam * f / w$

But in practice, the code didn't work as I thought it would.

Code Parts

At first, I tried combining the Lens() and Propagate() functions.
Then ,I tried LensFarfield() Fuction
And now,I am trying use Spherical coordinates

calRediuswithPow.py is the base function I used to calculate it, there are some things wrong with its algorithm, such as the center of mass calculating itself, and the energy calculating itself, but I don't think it's going to be particularly wrong for the same field and it's propagation, and during debugging, the energy percentage was not more than 0.3% wrong

They all produce beta results that are way off compared to one, generally speaking aspherical coordinate calculations will be about 30% off, and will change greatly with focal length, and diameter of the circular hole,even if I use "ideal sampling": $dx=\frac{\lambda *z}{L}$ [2]73-74. Spherical coordinates in my example are calculated to be 0.3-0.4, which is off by 60-70%.

I'm not sure what went wrong, the radius calculations should not logically produce such a large deviation. Is there something I am not taking into account in my simulation method.

calRediuswithPow.py

use calRediuswithPow() function to calculate the radius corresponding to energy in specify bucket

from LightPipes import *

import matplotlib as mpl
import numpy as np

import copy as _copy


def calRediuswithPow(fieldIn,energyPercent=0.839):
    '''
    Calculate the radius corresponding to the ring energy

    Parameters
    ----------
    energyPercent : double
        
    fieldIn : lp.Field
        The input field.
    Returns
    -------
    The Redius correspend to the energyPercent power.
    """
        ----------

   
    '''
    fieldIn=_copy.copy(fieldIn)
    I=Intensity(fieldIn)
    
    sumEnergy=0
    # sumEnergy=sum(I)
    sumEnergy1=0

    sumEnergy1=0
    
    F_row=np.size(fieldIn.field,0)
    F_col=np.size(fieldIn.field,1)

    for i in range(F_row):
        for j in range(F_col):
            sumEnergy+=I[i][j]

    #sumEnergy2=Power(fieldIn)
    
    targetEnergy=energyPercent*sumEnergy
    # Y, X = fieldIn.mgrid_cartesian

    #Determine spot center of mass Coordinate system with array indexed x,y coordinates
    x_power_sum=0
    y_power_sum=0
    for i in range(F_row):
        for j in range(F_col):
            x_power_sum+=I[i][j]*i

    for i in range(F_row):
        for j in range(F_col):
            y_power_sum+=I[i][j]*j
    
    x_center=x_power_sum/sumEnergy
    y_center=y_power_sum/sumEnergy
	
	
    #Calculate the approximation of the true radius using the Bisection method.
    # First set the maximum value of the radius to the diagonal of the matrix
    r_max=np.sqrt(F_row**2+F_col**2)
    r_min=0

    girdR=binarySearchR(I,r_max,r_min,targetEnergy,x_center,y_center,F_row,F_col)
    Rres=girdR*fieldIn.dx

    return Rres


def binarySearchR(intensityIn,r_max,r_min,targetEnergy,x_center,y_center,F_row,F_col):
    '''
    Bisection method to approximate the real radius (the fitting effect is a bit poor, later can be changed to a point by point cascade outward expansion)
	The error is close to 0.3%

    '''

    while r_min <= r_max:
        r_mid=(r_min+(r_max-r_min)/2)

        midEnergy=calPowerWithRadius(intensityIn,F_row,F_col,x_center,y_center,r_mid)
        if midEnergy == targetEnergy:
            return r_mid
        elif midEnergy>targetEnergy:
            r_max=r_mid-1
        else:
            r_min=r_mid+1

         #close
    return r_mid

	#TODO:Sort, compute distance from center of mass for all cells, put into set sort, set map


def calPowerWithRadius(intensityIn,F_row,F_col,x_center,y_center,radius):
    '''
    Calculate the power within a specified radius
    
    '''
    powerRes=0
    for i in range(F_row):
        for j in range(F_col):
            if ((i-x_center)**2+(j-y_center)**2)<=radius**2:
                powerRes+=intensityIn[i][j]

    return powerRes            
LensAndLensFarfieldTry.py

try combine Lens() and Propagate() And try LensFarfield()

from LightPipes import *
import matplotlib as mpl
import numpy as np

import calRediuswithPow

mpl.use('TkAgg')

import matplotlib.pyplot as plt

#import Utils

# wavelength = 500*nm
# size = 7*mm
# N = 100

# w0 = 1*mm
# f = 1*m
# z = 1*m

wavelength = 1000 * nm
N = 3000 #2840
size = 125 * mm
f = 5.5*m
z = f
w0 = 1*mm

# dx = wavelength*z/size
# N = int(size/dx)

F = Begin(size, wavelength, N)
F= CircAperture(R=50*mm,Fin=F)

F = Lens(F, f)
# F = Fresnel(F, z)
# F = Forvard(F, z)
F = Propagate(F, f)

# F2=LensFresnel(f2,f,F2);
# F=LensFarField(F,f)
# F=Forward(F)


#############################Beita calculate start###############################################

d = 100*mm
FToCalB=F

Dpow=calRediuswithPow.calRediuswithPow(FToCalB,0.839)*2
DTherory=2.44*FToCalB.lam*f/d

beita=Dpow/DTherory

print('The Beita is :',beita)



#############################Beita calculate end###############################################
TrySphericalCoordinates.py

Try use Spherical Coordinatesto calculate

from LightPipes import *
import matplotlib.pyplot as plt

#import Utils
import calRediuswithPow


def TheExample(N):
    fig = plt.figure(figsize=(15, 9.5))
    ax1 = fig.add_subplot(221)
    ax2 = fig.add_subplot(222)
    ax3 = fig.add_subplot(223)
    ax4 = fig.add_subplot(224)
    labda = 1000 * nm
    size = 10 * mm

    f = 100 * cm
    f1 = 10 * m
    f2 = f1 * f / (f1 - f)
    frac = f / f1
    newsize = frac * size
    w = 10 * mm
    w=w/5

    #something wrong#########################################
    # wavelength = 1000 * nm
    # # N = 500
    # size = 125 * mm
    # f = 500 * mm
    # z = 500 * mm
    # w0 = 1 * mm
    ############################################


    F = Begin(size, labda, N)
    F = CircAperture(F, R=w)


    # 1) Using Lens and Fresnel:
    F1 = Lens(f, 0, 0, F)
    # F1 = Fresnel(f, F1)
    F1 = Propagate(F1,f)
    phi1 = Phase(F1)
    phi1 = PhaseUnwrap(phi1)
    I1 = Intensity(0, F1)
    x1 = []
    for i in range(N):
        x1.append((-size / 2 + i * size / N) / mm)

    # 2) Using Lens + LensFresnel and Convert:
    F2 = Lens(f1, 0, 0, F)
    F2 = LensFresnel(f2, f, F2)
    F2 = Convert(F2)
    phi2 = Phase(F2)
    phi2 = PhaseUnwrap(phi2)
    I2 = Intensity(0, F2)
    #Utils.show(F2,"F2 Inten")
    x2 = []

    for i in range(N):
        x2.append((-newsize / 2 + i * newsize / N) / mm)

    ax1.plot(x1, phi1[int(N / 2)], 'k--', label='Without spherical coordinates')
    ax1.plot(x2, phi2[int(N / 2)], 'k', label='With spherical coordinates')
    ax1.set_xlim(-newsize / 2 / mm, newsize / 2 / mm)
    ax1.set_ylim(-2, 4)
    ax1.set_xlabel('x [mm]')
    ax1.set_ylabel('phase [rad]')
    ax1.set_title('phase, N = %d' % N)
    legend = ax1.legend(loc='upper center', shadow=True)

    ax2.plot(x1, I1[int(N / 2)], 'k--', label='Without spherical coordinates')
    ax2.plot(x2, I2[int(N / 2)], 'k', label='With spherical coordinates')
    ax2.set_xlim(-newsize / 2 / mm, newsize / 2 / mm)
    ax2.set_ylim(0, 1000)
    ax2.set_xlabel('x [mm]')
    ax2.set_ylabel('Intensity [a.u.]')
    ax2.set_title('intensity, N = %d' % N)
    legend = ax2.legend(loc='upper center', shadow=True)

    ax3.imshow(I1)
    ax3.axis('off')
    ax3.set_title('Without spherical coordinates')
    ax3.set_xlim(int(N / 2) - N * frac / 2, int(N / 2) + N * frac / 2)
    ax3.set_ylim(int(N / 2) - N * frac / 2, int(N / 2) + N * frac / 2)
    ax4.imshow(I2)
    ax4.axis('off')
    ax4.set_title('With spherical coordinates')
    plt.figtext(0.3, 0.95, 'Spherical Coordinates, f = 100cm lens\nGrid dimension is: %d x %d pixels' % (N, N),
                fontsize=18, color='red')

    #############################Beita calculate start###############################################

    d = w
    FToCalB=F2

    Dpow=calRediuswithPow.calRediuswithPow(FToCalB,0.839)*2
    DTherory=2.44*FToCalB.lam*f/d

    beita=Dpow/DTherory

    print('The Beita is :',beita)

    #############################Beita calculate end###############################################


# TheExample(100)  # 100 x 100 grid

TheExample(1000)  # 1000 x 1000 grid
plt.show()

Others

Spherical coordinates is a little hard to understand, for example I don't know how to set f1 and z. @ldoyle 's xplanation confused me even more

End

Thanks for your reading!
I've been puzzling over these calculations for a long time, so if you have time please help me!

References

[1] Hecht E. Optics[M]. 5.Boston: Pearson Education, Inc.,2017: vi, 480-484.
[2] Voelz D G.Computational fourier optics: a MATLAB tutorial[J],2011.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant