|
3次元-周期的境界条件下の下で定常状態の電子のエネルギーと電子状態を求めるプログラム
(020harmonicsPSD2D.bas)を公開します。これは、最急降下法による3次元の定常状態の電子状態を求めるプログラム
[013]に周期的境界条件を付けたものです。
表示の説明:
3次元-周期的境界条件下の自由空間(V(x,y,z)=0)では基底状態は|0>=constant, E(0)=0 になります。
x、y、z方向の周期が同じ場合、E1=E2=E3=E4=E5=E6で縮退しているため、|1>..|6>はこの固有空間の中の
任意の直交する関数の組でよいため、形が一意には決まりません。
試験環境:
本プログラムは十進BASIC 6.6.3.3 / macOS 10.7.5, 十進BASIC Ver 7.8.0 / windows 10 でテストしました。
-----------
!
! ========= periodic steepest descent method 3D ==========
!
! 020periodicPSD3D.bas
! Copyright(C) 2017 Mitsuru Ikeuchi
!
! ver 0.0.1 2017.07.10 created
!
OPTION ARITHMETIC NATIVE
DECLARE EXTERNAL SUB psd3d.setInitialCondition,psd3d.SDiteration,psd3d.drawState
DECLARE EXTERNAL FUNCTION INKEY$
LET Ax = PI/12 !rotate angle around x-axis
LET Ay = -PI/6 !rotate angle around y-axis
LET ddAy = PI/180 !Ay=Ay+ddAy
LET vIndex = 3 !vIndex=0: V=1/r, 1: V=(1/2)r^2, 2:V=0(r<=4) or V=16(r>4) 3:V=0
LET stateMax = 6 !state 0,1,...,stateMax-1
LET drawMode = 0 !drawMode=0:density3D, 1:grid |i> in (x,y,0)
LET ist = 0 !display state |i>
CALL setInitialCondition(stateMax,vIndex)
DO
LET Ay = Ay + ddAy
CALL SDiteration(stateMax, 2) !2 - iteration in SDiteration()
CALL drawState(ist,Ax,Ay,drawMode)
LET S$=INKEY$
IF S$="0" OR S$="1" OR S$="2" OR S$="3" OR S$="4" OR S$="5" THEN
LET ist = VAL(S$)
ELSEIF S$="W" OR S$="w" THEN
if ddAy=0.0 then LET ddAy=-pi/180 else LET ddAy = 0.0
ELSEIF S$="E" OR S$="e" THEN
IF ddAy=0.0 THEN LET ddAy= PI/180 ELSE LET ddAy = 0.0
ELSEIF S$="D" OR S$="d" THEN
LET drawMode = MOD(drawMode+1,2)
END IF
LOOP UNTIL S$=CHR$(27)
END
EXTERNAL FUNCTION INKEY$ !from decimal BASIC library
OPTION ARITHMETIC NATIVE
SET ECHO "OFF"
LET S$=""
CHARACTER INPUT NOWAIT: S$
LET INKEY$=S$
END FUNCTION
! ---------- periodic steepest descent method 3D ----------
!
! system Hamiltonian: H = -delta/2 + V(r) , delta r = div grad r
! eigen energy set { Ei }, eigen function set { |i> }
!
! procedure : successive approximation
! (i) trial function set { |0>,|1>,..,|i>,.. }
! (2) energy of |i> : ei = <i|H|i>/<i|i>
! (3) steepest gradient direction (H-ei)|i>
! (4) next generation : |i(next)> = |i> - dampingFactor*(H-ei)|i>
! (5) orthogonalization { |0>,|1>,..,|i>,.. } (Gram-Schmidt)
! (6) goto (2)
!
MODULE psd3d
MODULE OPTION ARITHMETIC NATIVE
OPTION BASE 0
PUBLIC SUB setInitialCondition, SDiteration, drawState
SHARE NUMERIC NNx, NNy, NNz, dx, dy, dz, iterCount
SHARE NUMERIC cosAx,sinAx,cosAy,sinAy,cx0,cy0,cz0 !--- 3D graphics
SHARE NUMERIC sdEnergy(10) ! electron state energy
SHARE NUMERIC sdState(10,65,65,65) ! electron states 0...20 0:ground state
SHARE NUMERIC wrk(65,65,65) ! state work space in steepestDescent
SHARE NUMERIC vv(65,65,65) ! external potential
SHARE NUMERIC xApex(0 TO 7),yApex(0 TO 7),zApex(0 TO 7) ! boxApex x- y- z-coordinate
SHARE NUMERIC pxApex(0 TO 7),pyApex(0 TO 7),pzApex(0 TO 7) ! rotated boxApex x- y- z-coordinate
SHARE NUMERIC boxEdge(0 TO 11,0 TO 2)! boxEdge(i,j) i-th edge j=0,1:j-th apex, j=2:for marking
LET NNx = 16 ! x-max number of sdState(,NNx,NNy,NNz)
LET NNy = 16 ! y-max number of sdState(,NNx,NNy,NNz)
LET NNz = 16 ! z-max number of sdState(,NNx,NNy,NNz)
LET dx = 0.5 ! (au) x division
LET dy = 0.5 ! (au) y division
LET dz = 0.5 ! (au) y division
LET iterCount = 0 ! sd iteration count
! ---------- set initial condition
EXTERNAL SUB setInitialCondition(stateMax,vIndex) !public
DECLARE EXTERNAL SUB setInitialState,setPotential,setBox
RANDOMIZE
CALL setInitialState(stateMax)
CALL setPotential(vIndex)
CALL setBox
SET WINDOW 0,500,0,500
END SUB
EXTERNAL SUB setInitialState(stateMax)
DECLARE EXTERNAL SUB normalizeState
RANDOMIZE
FOR ist=0 TO stateMax-1
FOR i=0 TO NNx-1
FOR j=0 TO NNy-1
FOR k=0 TO NNz-1
LET sdState(ist,i,j,k) = RND-0.5
NEXT k
NEXT j
NEXT i
CALL normalizeState(ist)
NEXT ist
END SUB
EXTERNAL SUB setPotential(vIndex)
FOR i=0 TO NNx-1
FOR j=0 TO NNy-1
FOR k=0 TO NNz-1
LET x = i*dx
LET y = j*dy
LET z = k*dz
IF vIndex=0 THEN
LET v0 = 10.0
IF SQR((x-8)*(x-8)+(z-8)*(z-8))<2 THEN LET V0 = 0.0
LET vv(i,j,k) = v0
ELSEIF vIndex=1 THEN
LET vv(i,j,k) = MIN(0.5*r*r,18)
ELSEIF vIndex=2 THEN
IF r<=4 THEN LET vv(i,j,k) = 0 ELSE LET vv(i,j,k) = 16
ELSE
LET vv(i,j,k) = 0
END IF
NEXT k
NEXT j
NEXT i
END SUB
EXTERNAL SUB setBox
IF boxEdge(11,1)<>7 THEN
DATA 0,0,0, 1,0,0, 0,1,0, 1,1,0, 0,0,1, 1,0,1, 0,1,1, 1,1,1
FOR i=0 TO 7
READ x,y,z
LET xApex(i) = x*NNx*dx
LET yApex(i) = y*NNy*dy
LET zApex(i) = z*NNz*dz
NEXT i
DATA 0,1,9, 0,2,9, 0,4,9, 1,3,9, 1,5,9, 2,3,9, 2,6,9, 3,7,9, 4,5,9, 4,6,9, 5,7,9, 6,7,9
MAT READ boxEdge !(0 TO 11,0 TO 2)
END IF
END SUB
! ---------- steepest descent iteration
EXTERNAL SUB SDiteration(stateMax, iterMax) !public
DECLARE EXTERNAL FUNCTION steepestDescent
DECLARE EXTERNAL SUB GramSchmidt,sortState
LET damp = 0.05 !damping factor in steepest descent
FOR i=0 TO iterMax-1
FOR ist=0 TO stateMax-1
LET sdEnergy(ist) = steepestDescent(ist, damp)
NEXT ist
CALL GramSchmidt(stateMax)
CALL sortState(stateMax)
LET iterCount = iterCount + 1
NEXT i
END SUB
EXTERNAL FUNCTION steepestDescent(ist, damp) !--- steepest descent method
DECLARE EXTERNAL FUNCTION energyOfState
DECLARE EXTERNAL SUB normalizeState
LET h2 = 2*dx*dx
LET ei = energyOfState(ist) !--- E_ist = <ist|H|ist>
FOR i=0 TO NNx-1 !--- |wrk> = (H-E_ist)|ist>
LET ip1 = MOD(i+1,NNx)
LET im1 = MOD(i-1+NNx,NNx)
FOR j=0 TO NNy-1
LET jp1 = MOD(j+1,NNy)
LET jm1 = MOD(j-1+NNy,NNy)
FOR k=0 TO NNz-1
LET kp1 = MOD(k+1,NNz)
LET km1 = MOD(k-1+NNz,NNz)
LET kesdState = (6*sdState(ist,i,j,k)-sdState(ist,ip1,j,k)-sdState(ist,im1,j,k)&
&-sdState(ist,i,jp1,k)-sdState(ist,i,jm1,k)-sdState(ist,i,j,kp1)-sdState(ist,i,j,km1))/h2
LET wrk(i,j,k) = kesdState+(vv(i,j,k)-ei)*sdState(ist,i,j,k)
NEXT k
NEXT j
NEXT i
FOR i=0 TO NNx-1 !--- |ist(next)> = |ist> - damp*|wrk> ( norm(|ist(next)>) <>1 )
FOR j=0 TO NNy-1
FOR k=0 TO NNz-1
LET sdState(ist,i,j,k) = sdState(ist,i,j,k)-damp*wrk(i,j,k)
NEXT k
NEXT j
NEXT i
CALL normalizeState(ist)
LET steepestDescent = ei
END FUNCTION
EXTERNAL FUNCTION energyOfState(ist) !--- E_ist = <ist|H|ist>/<ist|ist>
LET h2 = 2*dx*dx
LET s = 0
LET sn=0
FOR i=0 TO NNx-1 !--- |wrk> = (H-E_ist)|ist>
LET ip1 = MOD(i+1,NNx)
LET im1 = MOD(i-1+NNx,NNx)
FOR j=0 TO NNy-1
LET jp1 = MOD(j+1,NNy)
LET jm1 = MOD(j-1+NNy,NNy)
FOR k=0 TO NNz-1
LET kp1 = MOD(k+1,NNz)
LET km1 = MOD(k-1+NNz,NNz)
LET kesdState = (6*sdState(ist,i,j,k)-sdState(ist,ip1,j,k)-sdState(ist,im1,j,k)&
&-sdState(ist,i,jp1,k)-sdState(ist,i,jm1,k)-sdState(ist,i,j,kp1)-sdState(ist,i,j,km1))/h2
LET s = s + sdState(ist,i,j,k)*(kesdState+vv(i,j,k)*sdState(ist,i,j,k))
LET sn = sn+sdState(ist,i,j,k)*sdState(ist,i,j,k)
NEXT k
NEXT j
next i
LET energyOfState = s/sn
END FUNCTION
EXTERNAL SUB GramSchmidt(stateMax) !--- Gram-Schmidt orthonormalization
DECLARE EXTERNAL FUNCTION innerProduct
DECLARE EXTERNAL SUB normalizeState
CALL normalizeState(0)
FOR istate=1 TO stateMax-1
FOR ist=0 TO istate-1
LET s = innerProduct(ist,istate)
FOR i=0 TO NNx-1
FOR j=0 TO NNy-1
FOR k=0 TO NNz-1
LET sdState(istate,i,j,k) = sdState(istate,i,j,k) - s*sdState(ist,i,j,k)
NEXT k
NEXT j
NEXT i
NEXT ist
CALL normalizeState(istate)
NEXT iState
END SUB
EXTERNAL SUB sortState(stateMax)
FOR ist=stateMax-2 TO 0 STEP -1
IF sdEnergy(ist)>sdEnergy(ist+1)+0.00001 THEN
FOR i=0 TO NNx-1
FOR j=0 TO NNy-1
FOR k=0 TO NNz-1
LET w = sdState(ist,i,j,k)
LET sdState(ist,i,j,k) = sdState(ist+1,i,j,k)
LET sdState(ist+1,i,j,k) = w
NEXT k
NEXT j
NEXT i
LET w = sdEnergy(ist)
LET sdEnergy(ist) = sdEnergy(ist+1)
LET sdEnergy(ist+1) = w
END IF
NEXT ist
END SUB
EXTERNAL FUNCTION innerProduct(ist,jst) !--- <ist|jst>
LET s = 0
FOR i=0 TO NNx-1
FOR j=0 TO NNy-1
FOR k=0 TO NNz-1
LET s = s + sdState(ist,i,j,k)*sdState(jst,i,j,k)
NEXT k
NEXT j
NEXT i
LET innerProduct = s*dx*dy*dz
END FUNCTION
EXTERNAL SUB normalizeState(ist)
LET s = 0
FOR i=0 TO NNx-1
FOR j=0 TO NNy-1
FOR k=0 TO NNz-1
LET s = s + sdState(ist,i,j,k)*sdState(ist,i,j,k)
NEXT k
NEXT j
NEXT i
LET a = SQR(1/(s*dx*dy*dz))
FOR i=0 TO NNx-1
FOR j=0 TO NNy-1
FOR k=0 TO NNz-1
LET sdState(ist,i,j,k) = a*sdState(ist,i,j,k)
NEXT k
NEXT j
NEXT i
END SUB
! ---------- 3D graphics aid
EXTERNAL SUB setRotateXY(angleX,angleY)
LET cosAx = COS(angleX)
LET sinAx = SIN(angleX)
LET cosAy = COS(angleY)
LET sinAy = SIN(angleY)
LET cx0 = 0.5*NNx*dx
LET cy0 = 0.5*NNy*dy
LET cz0 = 0.5*NNz*dz
END SUB
EXTERNAL SUB rotateXY !particles and box apex
FOR i=0 TO 7
LET pxApex(i) = cosAy*(xApex(i)-cx0)+sinAy*(sinAx*(yApex(i)-cy0)+cosAx*(zApex(i)-cz0)) + cx0
LET pyApex(i) = cosAx*(yApex(i)-cy0)-sinAx*(zApex(i)-cz0) + cy0
LET pzApex(i) =-sinAy*(xApex(i)-cx0)+cosAy*(sinAx*(yApex(i)-cy0)+cosAx*(zApex(i)-cz0)) + cz0
NEXT i
END SUB
EXTERNAL SUB drawDisk3D(x,y,z,r,mag,xShift,yShift)
LET x1 = cosAy*(x-cx0)+sinAy*(sinAx*(y-cy0)+cosAx*(z-cz0)) + cx0
LET y1 = cosAx*(y-cy0)-sinAx*(z-cz0) + cy0
LET z1 =-sinAy*(x-cx0)+cosAy*(sinAx*(y-cy0)+cosAx*(z-cz0)) + cz0
DRAW disk WITH SCALE(r)*SHIFT(x1*mag+xShift,y1*mag+yShift)
END SUB
EXTERNAL SUB plotLines3D(x,y,z,mag,xShift,yShift)
LET x1 = cosAy*(x-cx0)+sinAy*(sinAx*(y-cy0)+cosAx*(z-cz0)) + cx0
LET y1 = cosAx*(y-cy0)-sinAx*(z-cz0) + cy0
LET z1 =-sinAy*(x-cx0)+cosAy*(sinAx*(y-cy0)+cosAx*(z-cz0)) + cz0
PLOT LINES: x1*mag+xShift, y1*mag+yShift;
END SUB
EXTERNAL SUB markFarEdge
! seek far apex --> iMin
LET zMin = pzApex(0)
LET iMin = 0
FOR i=1 TO 7
IF zMin>pzApex(i) THEN
LET zMin = pzApex(i)
LET iMin = i
END IF
NEXT i
!mark far edge
FOR iEdge = 0 TO 11
LET boxEdge(iEdge,2) = 0
IF (boxEdge(iEdge,0)=iMin OR boxEdge(iEdge,1)=iMin) THEN LET boxEdge(iEdge,2) = 1
NEXT iEdge
END SUB
EXTERNAL SUB plotNearEdge(mag,xp,yp,lineColor)
DECLARE EXTERNAL SUB plotEdge
FOR iEdge=0 TO 11
IF boxEdge(iEdge,2)=0 THEN !far edge mark = 0
CALL plotEdge(iEdge,mag,xp,yp,lineColor)
END IF
NEXT iEdge
END SUB
EXTERNAL SUB plotFarEdge(mag,xp,yp,lineColor)
DECLARE EXTERNAL SUB plotEdge
FOR iEdge=0 TO 11
IF boxEdge(iEdge,2)=1 THEN !far edge mark = 1
CALL plotEdge(iEdge,mag,xp,yp,lineColor)
END IF
NEXT iEdge
END SUB
EXTERNAL SUB plotEdge(iEdge,mag,xp,yp,lineColor)
SET LINE COLOR lineColor
FOR i=0 TO 1
LET iApex = boxEdge(iEdge,i)
PLOT LINES: pxApex(iApex)*mag+xp, pyApex(iApex)*mag+yp;
NEXT i
PLOT LINES
END SUB
! ---------- draw state
EXTERNAL SUB drawState(ist,xRotateAngle,yRotateAngle,drawMode)
DECLARE EXTERNAL SUB drawDensity3D,setRotateXY,drawDensity3D,drawStateGrid
SET DRAW MODE HIDDEN
CLEAR
IF drawMode=0 THEN
CALL drawDensity3D(ist,xRotateAngle,yRotateAngle,200/(NNx*dx),140,150) !!(ist,Ax,Ay,sc,xp,yp)
ELSEIF drawMode=1 THEN
CALL drawStateGrid(ist,200/(NNx*dx),0.1,140,200) !(ist,sc,zMag,xp,yp)
END IF
!--- caption
SET TEXT HEIGHT 10
SET TEXT COLOR 1 ! black
PLOT TEXT, AT 50, 70 ,USING "iterarion count =##### ":iterCount
PLOT TEXT, AT 50, 55 ,USING "E0 =###.######### E3 =###.#########(au)":sdEnergy(0),sdEnergy(3)
PLOT TEXT, AT 50, 40 ,USING "E1 =###.######### E4 =###.#########(au)":sdEnergy(1),sdEnergy(4)
PLOT TEXT, AT 50, 25 ,USING "E2 =###.######### E5 =###.#########(au)":sdEnergy(2),sdEnergy(5)
PLOT TEXT, AT 50, 10 :"periodic steepest descent method 3D"
PLOT TEXT, AT 50,470 :"[0],[1],...,[5] view state [esc] exit "
PLOT TEXT, AT 50,455 :"[D] change drawMode"
PLOT TEXT, AT 50,440 :"[W] rotateLeft/stop [E] rotateRight/stop"
SET DRAW MODE EXPLICIT
END SUB
EXTERNAL SUB drawDensity3D(ist,xRotateAngle,yRotateAngle,sc,xp,yp) !----- drawMode=0
DECLARE EXTERNAL SUB setRotateXY,rotateXY,markFarEdge,plotFarEdge,drawDisk3D,plotNearEdge
CALL setRotateXY(xRotateAngle,yRotateAngle)
CALL rotateXY !rotateXY BOX
CALL markFarEdge ! boxEdge(iEdge,2)=1:far side edge or 0:near side edge
CALL plotFarEdge(sc,xp,yp,8) !8:gray
FOR ii=0 TO NNx-1
LET i=ii
IF (pzApex(1)-pzApex(0)<0) THEN LET i=NNx-ii-1
FOR jj=0 TO NNy-1
LET j=jj
IF (pzApex(2)-pzApex(0)<0) THEN LET j=NNy-jj-1
FOR kk=0 TO NNz-1
LET k=kk
IF (pzApex(4)-pzApex(0)<0) THEN LET k=NNz-kk-1
LET psi = sdState(ist,i,j,k)
LET psi2 = psi*psi
IF psi2>0.001 THEN
IF psi>0 THEN SET AREA COLOR 4 ELSE SET AREA COLOR 2
CALL drawDisk3D(i*dx,j*dy,k*dz,ABS(psi)*10,sc,xp,yp)
END IF
NEXT kk
NEXT jj
NEXT ii
!SET AREA COLOR 1
!CALL drawDisk3D(0,0,0,5,sc,xp,yp)
CALL plotNearEdge(sc,xp,yp,1) !1:black
SET TEXT COLOR 1
SET TEXT HEIGHT 10
PLOT TEXT, AT 50,100:"|"&STR$(ist)&">"
PLOT TEXT, AT 50, 85 ,USING "Ax =###.#(deg) Ay =###.#(deg)":MOD(xRotateAngle*180/PI,360),MOD(yRotateAngle*180/PI,360)
END SUB
EXTERNAL SUB drawStateGrid(ist,sc,zMag,xp,yp) !--- drawMode=1
DECLARE EXTERNAL SUB setRotateXY,drawGridXY
CALL setRotateXY(-PI/3,-PI/6)
CALL drawGridXY(ist,sc,zMag,xp,yp)
SET TEXT COLOR 1
SET TEXT HEIGHT 10
PLOT TEXT, AT 50,100:"|"&STR$(ist)&"> in (x,y,0)"
END SUB
EXTERNAL SUB drawGridXY(ist,sc,zMag,xShift,yShift)
DECLARE EXTERNAL SUB plotLines3D
FOR j=0 TO NNy-1 STEP 1
FOR i=0 TO NNx-1
LET psi = sdState(ist,i,j,NNz/2)*200
IF psi>1 THEN
SET LINE COLOR 4 ! red
ELSEIF psi<-1 THEN
SET LINE COLOR 2 ! blue
ELSE
SET LINE COLOR 3 ! potential:green
END IF
CALL plotLines3D(i*dx,j*dx,zMag*(psi + 2*vv(i,j,NNz/2)),sc,xShift,yShift) !(x,y,z)
NEXT i
PLOT LINES
NEXT j
FOR i=0 TO NNx-1 STEP 1
FOR j=0 TO NNy-1
LET psi = sdState(ist,i,j,NNz/2)*200
IF psi>1 THEN
SET LINE COLOR 4 ! red
ELSEIF psi<-1 THEN
SET LINE COLOR 2 ! blue
ELSE
SET LINE COLOR 3 ! potential:green
END IF
CALL plotLines3D(i*dx,j*dx,zMag*(psi + 2*vv(i,j,NNz/2)),sc,xShift,yShift) !(x,y,z)
NEXT j
PLOT LINES
NEXT i
END SUB
END MODULE
|
|