電磁波(光)の伝搬の雛形プログラムの公開

 投稿者:mike  投稿日:2017年 2月 6日(月)11時11分42秒
   電磁波(光)の伝搬(FDTD法)の雛形プログラムを公開します。
 雛形なので、なるべくFDTD法の本質的な部分だけをわかりやすく書いたつもりです。
(高速化や汎用性をねらうと、mikeの力量ではプログラムが読み難くなりますので)
光の伝搬はMaxwellの電磁場の方程式を用いて現在の電場Ezと磁場Hx,Hyからdt時間後の電場Ezと磁場Hx,Hyを求めます。
これを繰り返して時間発展させていきます。
3次元(Ex,Ey,Ez,Hx,Hy,Hz)だと計算時間が長く(Ez(200,200,200) etc.)なり、
波が動いてのを見ることが難しいので、2次元にします(Ez(200,200) etc.)。
Ezと相互に結びつきの強いHx,Hyの3つのみで、矛盾なく2次元にすることができます。
この雛形プログラムでは、パルス状の平面波を誘電体(誘電率εr=4 or 屈折率n=2)にあて、そのふるまいを観察します。
誘電体での波の反射,透過、散乱が見られます。透過のとき、波の速度が1/2のなることがわかります。

表示の説明:
青のグリッドは電場Ezを鳥瞰したものです。青色は真空中(あるいは空気中)、赤い部分はガラスのような屈折率2の誘電体を表します。
長さや時間の間には、時間刻みdt、空間刻みdxの間にdx=c*dt(c=1)の関係があります。
(たとえばdt=1psとするとc=3e8 m/sとしてdx=0.3mmになります)

試験環境:
本プログラムは十進BASIC 0.6.6.0 / macOS 10.7.5と
十進BASIC Ver 7.7.8 / windows 10でテストしました。


!
! ========= FDTD 2D ==========
!
! waveFDTD2D.bas
! Mitsuru Ikeuchi (c) copyleft
!
! ver 0.0.1   2017.02.06
!
OPTION ARITHMETIC NATIVE
DECLARE EXTERNAL SUB fdtd2d.setInitialCondition, fdtd2d.evolveField, fdtd2d.drawField
DECLARE EXTERNAL FUNCTION fdtd2d.systemTime
!
!CALL setInitialCondition(epsilon,mue,sigma)
CALL setInitialCondition(4.0,1.0,0.0)     !dielectric material
!CALL setInitialCondition(1.0,4.0,0.0)    !Magnetic material
!CALL setInitialCondition(1.0,1.0,0.01)   !resistor
!CALL setInitialCondition(1.0,1.0,0.0)    !vacuum or air
!CALL setInitialCondition(1000.0,1.0,0.1) ! metal
!
FOR it=1 TO 1000
   CALL evolveField
   CALL evolveField
   CALL drawField
NEXT it
!
END

! ---------- FDTD2D module  ----------
!
!  time evolution : from Maxwell equation,
!    d(mu H)/dt = - rot E    (B = mu H)
!    d(ep E)/dt = -j + rot H (D=ep E, j=sg E)
!  FDTD:Finite-difference time-domain method
!    2D subset: Ez,Hx,Hy - finite difference approximation
!
MODULE fdtd2d
MODULE OPTION ARITHMETIC NATIVE
OPTION BASE 0
PUBLIC SUB setInitialCondition, evolveField, drawField
PUBLIC FUNCTION systemTime
SHARE NUMERIC sysTime, dt,epsilon,reg,sgm,Jz,omega,theta,NNx,NNy
SHARE NUMERIC cosAx,sinAx,cosAy,sinAy,cx0,cy0,cz0 !--- 3D graphics
SHARE NUMERIC Ez(320,320)             ! electric field
SHARE NUMERIC Hx(320,320),Hy(320,320) ! magnetic field
SHARE NUMERIC ep(320,320)             ! dielectric constant
SHARE NUMERIC mu(320,320)             ! permeability
SHARE NUMERIC sg(320,320)             ! conductivity
LET sysTime = 0      ! system time
LET dt = 1           ! time step
LET dx = 1           ! x-division  dx=dy=dz=1  no use
LET omega = PI/32    ! generator wave phase angle change
LET theta = 0        ! generator phase angle
LET NNx = 241        ! max number of Ez(i,) etc.
LET NNy = 241        ! max number of Ez(,j) etc.
!
! set initial condition
!
EXTERNAL SUB setInitialCondition(epsilon,mue,sigma)
   LET theta = 0.0
   !clear field
   FOR i=0 TO NNx
      FOR j=0 TO NNy
         LET Ez(i,j) = 0
         LET Hx(i,j) = 0
         LET Hy(i,j) = 0
         LET ep(i,j) = 1
         LET mu(i,j) = 1
         LET sg(i,j) = 0
      NEXT j
   NEXT i
   !set material
   FOR i=0 TO NNx
      FOR j=0 TO NNy
         IF (i>=60 AND i<140 AND j>=50 AND j<150) THEN
            LET ep(i,j) = epsilon
            LET mu(i,j) = mue
            LET sg(i,j) = sigma
         END IF
      NEXT j
   NEXT i
   ! set window
   LET xmargin = 60
   LET ymargin = 100
   SET WINDOW -xmargin,400-xmargin,-ymargin,400-ymargin
END SUB
!
! evolve Field Ez,Hx,Hy
!
EXTERNAL SUB evolveField
   DECLARE EXTERNAL SUB generateEz,evolveEz,evolveHxHy
   LET sysTime = sysTime + dt
   CALL evolveEz
   CALL generateEz(2)
   CALL evolveHxHy
END SUB
!
EXTERNAL SUB generateEz(nwave)
   LET theta = theta + omega*dt
   LET Ezt = SIN(theta)
   LET a = 0
   IF theta<2*PI*nwave THEN
      LET a=1
   ELSEIF theta<2*PI*nwave+0.13*PI THEN
      LET a=COS(theta)
   END IF
   IF theta<2*PI*nwave+0.5*PI THEN
      FOR j=0 TO NNy
         LET Ez(0,j) = a*a*Ezt
      NEXT j
   END IF
END SUB
!
EXTERNAL SUB evolveEz  ! dD/dt=rotH + J ,D=epsi*E
   LET a = 1/(2*SQR(2))
   FOR i=0 TO NNx-1
      FOR j=0 TO NNy-1
         LET Ez(i,j)=Ez(i,j)-sg(i,j)*0.5*dt*Ez(i,j)+(a/ep(i,j))*((Hy(i+1,j)-Hy(i,j))-(Hx(i,j+1)-Hx(i,j)))
      NEXT j
   NEXT i
END SUB
!
EXTERNAL SUB evolveHxHy  ! dB/dt=-rotE ,B=mue*H
!no reflection boundary
   LET a = 1/(2*SQR(2))
   LET c = (1-a)/(1+a)
   FOR i=0 TO NNx-1
      LET Hx(i,0) = c*Hx(i,0) + Hx(i,1)
      LET Hx(i,NNy) = c*Hx(i,NNy) + Hx(i,NNy-1)
   NEXT i
   FOR j=0 TO NNy-1
      LET Hy(0,j) = c*Hy(0,j) + Hy(1,j)
      LET Hy(NNx,j) = c*Hy(NNx,j) + Hy(NNx-1,j)
   NEXT j
   !
   FOR i=0 TO NNx-1
      FOR j=1 TO NNy-1
         LET Hx(i,j) = Hx(i,j) - (a/mu(i,j))*(Ez(i,j)-Ez(i,j-1))
      NEXT j
   NEXT i
   FOR i=1 TO NNx-1
      FOR j=0 TO NNy-1
         LET Hy(i,j) = Hy(i,j) + (a/mu(i,j))*(Ez(i,j)-Ez(i-1,j))
      NEXT j
   NEXT i
   !no reflection boundary
   FOR i=0 TO NNx-1
      LET Hx(i,0) = Hx(i,0) - c*Hx(i,1)
      LET Hx(i,NNy) = Hx(i,NNy) - c*Hx(i,NNy-1)
   NEXT i
   FOR j=0 TO NNy-1
      LET Hy(0,j) = Hy(0,j) - c*Hy(1,j)
      LET Hy(NNx,j) = Hy(NNx,j) - c*Hy(NNx-1,j)
   NEXT j
END SUB
!
! utility
!
EXTERNAL FUNCTION systemTime
   LET systemTime = sysTime
END FUNCTION
!
! 3D graphics
!
EXTERNAL SUB setRotateXYParameters(angleX,angleY,xCenter,yCenter,zCenter)
   LET cosAx = COS(angleX)
   LET sinAx = SIN(angleX)
   LET cosAy = COS(angleY)
   LET sinAy = SIN(angleY)
   LET cx0 = xCenter
   LET cy0 = yCenter
   LET cz0 = zCenter
END SUB

EXTERNAL SUB plotLines3D(x,y,z) !shift*xRotateAx*yRotateAy*(shift^-1)
   LET x1 = cosAy*(x-cx0)+sinAy*(sinAx*(y-cy0)+cosAx*(z-cz0))
   LET y1 = cosAx*(y-cy0)-sinAx*(z-cz0)
   LET z1 =-sinAy*(x-cx0)+cosAy*(sinAx*(y-cy0)+cosAx*(z-cz0))
   PLOT LINES: x1+cx0, y1+cy0; !z=z1+cz0
END SUB
!
! draw field Ez,Hx,Hy
!
EXTERNAL SUB drawField
   DECLARE EXTERNAL SUB drawEz
   !
   SET DRAW MODE HIDDEN
   CLEAR
   !CALL setRotateXYParameters(angleX,angleY,xCenter,yCenter,zCenter)
   CALL drawEz(-PI/6,-PI/12)  !(xRotateAngle,yRotateAngle)
   !draw caption
   SET TEXT HEIGHT 8
   SET TEXT COLOR 1 ! black
   PLOT TEXT, AT 0,-20 ,USING "time =#####.# ":sysTime
   PLOT TEXT, AT 0,-35 ,USING  "field size = #### x ####":NNx,NNy
   PLOT TEXT, AT 0,-50 :"2-dimensional FDTD"
   !
   SET DRAW MODE EXPLICIT
END SUB
!
EXTERNAL SUB drawEz(xRotateAngle,yRotateAngle)
   DECLARE EXTERNAL SUB setRotate,plotLines3D
   LET sc = 1.0
   LET zMag = 20
   !CALL setRotateXYParameters(angleX,angleY,xCenter,yCenter,zCenter)
   CALL setRotateXYParameters(xRotateAngle,yRotateAngle,NNx/2,NNy/2,0)
   SET COLOR 2 ! blue : Ez
   FOR j=0 TO NNy-1 STEP 5
      FOR i=0 TO NNx-1
         IF Ez(i,j)>=0 THEN SET COLOR 2 ELSE SET COLOR 9 !>=0:bule <0:dark blue
         IF ep(i,j)>1 OR mu(i,j)>1 OR sg(i,j)>0 THEN SET COLOR 4 !something material
         CALL plotLines3D(i*sc,j*sc,zMag*Ez(i,j)) !(x,y,z)
      NEXT i
      PLOT LINES
   NEXT j
   FOR i=0 TO NNx-1 STEP 5
      FOR j=0 TO NNy-1
         IF Ez(i,j)>=0 THEN SET COLOR 2 ELSE SET COLOR 9
         IF ep(i,j)>1 OR mu(i,j)>1 OR sg(i,j)>0 THEN SET COLOR 4
         CALL plotLines3D(i*sc,j*sc,zMag*Ez(i,j))
      NEXT j
      PLOT LINES
   NEXT i
END SUB
!
END MODULE

 

戻る