!Copyright (c) 2013 by tdem.org under guide of Xiu Li(lixiu@chd.edu.cn) !written by Huaifeng Sun(sunhuaifeng@gmail.com) and Xushan Lu(luxushan@gmail.com) !Code distribution @ tdem.org or sunhuaifeng.com ! --------------------------------Subroutine part---------------------------------------------! subroutine Iteration use constantparameters USE CONSTANTPARAMETERS USE ELECTROMAGNETIC_VARIABLES USE RES_MODEL_PARAMETER USE TIME_PARAMETER implicit none real::t1,t2,t !t1 denotes original cpu time at the beginning of each computation fraction, t2 denotes the end cpu time and t=t2-t1 REAL*8 CA,CB,DELX1,DELY1,DELZ1 !ca, cb, delx1, dely1, delz1 are all middle variables used in the computation of EM field REAL*8 TEMP_SIG,temp_cacb !Temp_sig and temp_cacb are middle variables used in the computation of EM field REAL*8 DELY2,DELZ2,delx2 !They are all middle variables as above ones. integer num,i,j,k,ii !num is the number of computation fraction real*8,allocatable::Meps_r(:),Mdelt(:),Msource(:),Mcq(:) !They are local substitution of eps_r, delt and cq do num=1,num_fra_com,1 !The outer loop which begins from the first fraction ends at the last fraction call cpu_time(t1) !Record the cpu time at the beginning of each computing fraction allocate(mdelt(0:mstop(num)),meps_r(mstop(num)),mcq(mstop(num)),msource(mstop(num))) ! The memory of mdelt, meps_r, mcq and msource are allocated at the begining of fraction do ii=mstart(num),mstart(num)+mstop(num)-1,1 mdelt(ii-mstart(num)+1)=delt(ii) meps_r(ii-mstart(num)+1)=eps_r(ii) mcq(ii-mstart(num)+1)=cq(ii) msource(ii-mstart(num)+1)=source(ii) !Link the local value of mdelt, meps_r, mcq and msorce to the global value of delt, eps_r, cq and source array. end do print*,'Now computing fraction:',num mdelt(0)=mdelt(1) !$acc data copy(Ex(1:nx,1:nyb,1:nzb),Ey(1:nxb,1:ny,1:nzb),Ez(1:nxb,1:nyb,1:nz))& !$acc copy(Hx(1:nxb,1:ny,0:nz),Hy(1:nx,1:nyb,0:nz),Hz(1:nx,1:ny,1:nzb)),copyin(cdelx(1:nx))& !$acc copyin(ccsig(1:nx,1:ny,1:nz),mdelt(0:mstop(num)),cdely(1:ny),cdelz(1:nz),mcq(1:mstop(num)),meps_r(1:mstop(num)))& !$acc copyin(is_ex_in_source(1:nx,2:nyb-1),is_ey_in_source(2:nx,1:ny),msource(1:mstop(num))) ! OpenACC directive, copy in and out of Ex,Ey,Ez,Hx,Hy,Hz, copy in ccsig, mdelt, cdelz, mcq, meps_r, is_ex_in_source, is_ey_in_source do loop=1,mstop(num),1 ! --------------------------------update the value of Ex and Ey in source area---------------------------------------! !$acc parallel async(1) !$acc loop gang DO J=2,NYB-1 !$acc loop vector DO I=1,NX K=NZ/2+1 DELY1=(CDELY(J-1)+CDELY(J))/2.0D0 DELZ1=CDELZ(NZ/2+1) TEMP_SIG=CCSIG(I,J-1,K-1)*CDELY(J-1)*CDELZ(K-1)& &+CCSIG(I,J-1,K)*CDELY(J-1)*CDELZ(K)& &+CCSIG(I,J,K-1)*CDELY(J)*CDELZ(K-1)& &+CCSIG(I,J,K)*CDELY(J)*CDELZ(K) TEMP_SIG=TEMP_SIG/(4.0D0*DELY1*DELZ1) CA=(2.0D0*Meps_r(loop)-Mdelt(LOOP-1)*TEMP_SIG)/(2.0*Meps_r(loop)+Mdelt(LOOP-1)*TEMP_SIG) CB=(2.0D0*MDELT(LOOP-1))/(2.0*Meps_r(loop)+MDELT(LOOP-1)*TEMP_SIG) EX(I,J,K)=CA*EX(I,J,K)+CB*((HZ(I,J,K)-HZ(I,J-1,K))/DELY1-(HY(I,J,K)-HY(I,J,K-1))/DELZ1)-cb*Msource(loop)*is_ex_in_source(i,j) ENDDO ENDDO !$acc end parallel ! end of updating Ex while k=Nzs+1 ! update the value of Ey while k=Nzs+1 !$acc parallel async(2) !$acc loop gang DO J=1,NY !$acc loop vector DO I=2,NX K=NZ/2+1 DELX1=(CDELX(I-1)+CDELX(I))/2.0 DELZ1=CDELZ(NZ/2+1) TEMP_SIG=CCSIG(I-1,J,K-1)*CDELX(I-1)*CDELZ(K-1)& &+CCSIG(I-1,J,K)*CDELX(I-1)*CDELZ(K)& &+CCSIG(I,J,K-1)*CDELX(I)*CDELZ(K-1)& &+CCSIG(I,J,K)*CDELX(I)*CDELZ(K) TEMP_SIG=TEMP_SIG/(4.0D0*DELX1*DELZ1) CA=(2.0D0*Meps_r(loop)-MDELT(LOOP-1)*TEMP_SIG)/(2.0D0*Meps_r(loop)+MDELT(LOOP-1)*TEMP_SIG) CB=(2.0D0*MDELT(LOOP-1))/(2.0D0*Meps_r(loop)+MDELT(LOOP-1)*TEMP_SIG) EY(I,J,K)=CA*EY(I,J,K)+CB*((HX(I,J,K)-HX(I,J,K-1))/DELZ1-(HZ(I,J,K)-HZ(I-1,J,K))/DELX1)-cb*Msource(loop)*is_ey_in_source(i,j) ENDDO ENDDO !$acc end parallel ! end of uptating Ey while k=Nzs+1 ! ---------------------------------------------------Ex Part-------------------------------------------------------------! !$acc parallel async(3) !$acc loop gang DO K=NZ/2+2,NZ !$acc loop worker DO J=2,NY !$acc loop vector DO I=1,NX DELY1=(CDELY(J-1)+CDELY(J))/2.0D0 DELZ1=(CDELZ(K-1)+CDELZ(K))/2.0D0 TEMP_SIG=CCSIG(I,J-1,K-1)*CDELY(J-1)*CDELZ(K-1)& &+CCSIG(I,J-1,K)*CDELY(J-1)*CDELZ(K)& &+CCSIG(I,J,K-1)*CDELY(J)*CDELZ(K-1)& &+CCSIG(I,J,K)*CDELY(J)*CDELZ(K) TEMP_SIG=TEMP_SIG/(4.0D0*DELY1*DELZ1) CA=(2.0D0*Meps_r(loop)-MDELT(LOOP-1)*TEMP_SIG)/(2.0D0*Meps_r(loop)+MDELT(LOOP-1)*TEMP_SIG) CB=(2.0D0*MDELT(LOOP-1))/(2.0D0*Meps_r(loop)+MDELT(LOOP-1)*TEMP_SIG) EX(I,J,K)=CA*EX(I,J,K)+CB*((HZ(I,J,K)-HZ(I,J-1,K))/DELY1-(HY(I,J,K)-HY(I,J,K-1))/DELZ1) ENDDO ENDDO ENDDO !$acc end parallel !$acc parallel async(4) !$acc loop gang DO K=2,NZ/2 !$acc loop worker DO J=2,NY !$acc loop vector DO I=1,NX DELY1=(CDELY(J-1)+CDELY(J))/2.0D0 DELZ1=(CDELZ(K-1)+CDELZ(K))/2.0D0 TEMP_SIG=CCSIG(I,J-1,K-1)*CDELY(J-1)*CDELZ(K-1)& &+CCSIG(I,J-1,K)*CDELY(J-1)*CDELZ(K)& &+CCSIG(I,J,K-1)*CDELY(J)*CDELZ(K-1)& &+CCSIG(I,J,K)*CDELY(J)*CDELZ(K) TEMP_SIG=TEMP_SIG/(4.0D0*DELY1*DELZ1) CA=(2.0D0*Meps_r(loop)-MDELT(LOOP-1)*TEMP_SIG)/(2.0D0*Meps_r(loop)+MDELT(LOOP-1)*TEMP_SIG) CB=(2.0D0*MDELT(LOOP-1))/(2.0D0*Meps_r(loop)+MDELT(LOOP-1)*TEMP_SIG) EX(I,J,K)=CA*EX(I,J,K)+CB*((HZ(I,J,K)-HZ(I,J-1,K))/DELY1-(HY(I,J,K)-HY(I,J,K-1))/DELZ1) ENDDO ENDDO ENDDO !$acc end parallel ! ================end of updating Ex==================! ! -----------------------------------------update the value of Ey--------------------------------! !$acc parallel async(5) !$acc loop gang DO K=NZ/2+2,NZ !$acc loop worker DO J=1,NY !$acc loop vector DO I=2,NX DELX1=(CDELX(I-1)+CDELX(I))/2.0D0 DELZ1=(CDELZ(K-1)+CDELZ(K))/2.0D0 TEMP_SIG=CCSIG(I-1,J,K-1)*CDELX(I-1)*CDELZ(K-1)& &+CCSIG(I-1,J,K)*CDELX(I-1)*CDELZ(K)& &+CCSIG(I,J,K-1)*CDELX(I)*CDELZ(K-1)& &+CCSIG(I,J,K)*CDELX(I)*CDELZ(K) TEMP_SIG=TEMP_SIG/(4.0D0*DELX1*DELZ1) CA=(2.0D0*Meps_r(loop)-MDELT(LOOP-1)*TEMP_SIG)/(2.0D0*Meps_r(loop)+MDELT(LOOP-1)*TEMP_SIG) CB=(2.0D0*MDELT(LOOP-1))/(2.0D0*Meps_r(loop)+MDELT(LOOP-1)*TEMP_SIG) EY(I,J,K)=CA*EY(I,J,K)+CB*((HX(I,J,K)-HX(I,J,K-1))/DELZ1-(HZ(I,J,K)-HZ(I-1,J,K))/DELX1) ENDDO ENDDO ENDDO !$acc end parallel !$acc parallel async(6) !$acc loop gang DO K=2,NZ/2 !$acc loop worker DO J=1,NY !$acc loop vector DO I=2,NXB-1 DELX1=(CDELX(I-1)+CDELX(I))/2.0D0 DELZ1=(CDELZ(K-1)+CDELZ(K))/2.0D0 TEMP_SIG=CCSIG(I-1,J,K-1)*CDELX(I-1)*CDELZ(K-1)& &+CCSIG(I-1,J,K)*CDELX(I-1)*CDELZ(K)& &+CCSIG(I,J,K-1)*CDELX(I)*CDELZ(K-1)& &+CCSIG(I,J,K)*CDELX(I)*CDELZ(K) TEMP_SIG=TEMP_SIG/(4.0D0*DELX1*DELZ1) CA=(2.0D0*Meps_r(loop)-MDELT(LOOP-1)*TEMP_SIG)/(2.0D0*Meps_r(loop)+MDELT(LOOP-1)*TEMP_SIG) CB=(2.0D0*MDELT(LOOP-1))/(2.0D0*Meps_r(loop)+MDELT(LOOP-1)*TEMP_SIG) EY(I,J,K)=CA*EY(I,J,K)+CB*((HX(I,J,K)-HX(I,J,K-1))/DELZ1-(HZ(I,J,K)-HZ(I-1,J,K))/DELX1) ENDDO ENDDO ENDDO !$acc end parallel !===============end of updating Ey===================! ! -------------------------------------update the value of Ez--------------------------------------! !$acc parallel async(7) !$acc loop gang DO K=1,NZ !$acc loop worker DO J=2,NYB-1 !$acc loop vector DO I=2,NXB-1 DELX1=(CDELX(I-1)+CDELX(I))/2.0D0 DELY1=(CDELY(J-1)+CDELY(J))/2.0D0 TEMP_SIG=CCSIG(I-1,J-1,K)*CDELX(I-1)*CDELY(J-1)& &+CCSIG(I-1,J,K)*CDELX(I-1)*CDELY(J)& &+CCSIG(I,J-1,K)*CDELX(I)*CDELY(J-1)& &+CCSIG(I,J,K)*CDELX(I)*CDELY(J) TEMP_SIG=TEMP_SIG/(4.0D0*DELX1*DELY1) TEMP_CACB=2.0D0*Meps_r(loop)+MDELT(LOOP-1)*TEMP_SIG CA=(2.0D0*Meps_r(loop)-MDELT(LOOP-1)*TEMP_SIG)/TEMP_CACB CB=(2.0D0*MDELT(LOOP-1))/TEMP_CACB EZ(I,J,K)=CA*EZ(I,J,K)+CB*((HY(I,J,K)-HY(I-1,J,K))/DELX1-(HX(I,J,K)-HX(I,J-1,K))/DELY1) ENDDO ENDDO ENDDO !$acc end parallel !$acc wait !===============end of updating Ez=========================! ! ------------------------------------update the value of Hx-----------------------------------------------! !$acc parallel async(8) !$acc loop gang DO K=1,NZ !$acc loop worker DO J=1,NY !$acc loop vector DO I=1,NXB DELY2=CDELY(J) DELZ2=CDELZ(K) HX(I,J,K)=HX(I,J,K)-MCQ(LOOP)*((EZ(I,J+1,K)-EZ(I,J,K))/DELY2-(EY(I,J,K+1)-EY(I,J,K))/DELZ2) ENDDO ENDDO ENDDO !$acc end parallel !================end of updating Hx=======================! ! -------------------------------------update the value of Hy---------------------------------------------! !$acc parallel async(9) !$acc loop gang DO K=1,NZ !$acc loop worker DO J=1,NYB !$acc loop vector DO I=1,NX DELZ2=CDELZ(K) DELX2=CDELX(I) HY(I,J,K)=HY(I,J,K)-MCQ(LOOP)*((EX(I,J,K+1)-EX(I,J,K))/DELZ2-(EZ(I+1,J,K)-EZ(I,J,K))/DELX2) ENDDO ENDDO ENDDO !$acc end parallel !$acc wait !===============end of updating Hy========================! !-------------------------------------update the value of Hz----------------------------------------------! !$acc kernels async(10) DO J=1,NY DO I=1,NX DO K=NZ,NZ/2+1,-1 !NZ,2,-1 ! DELX2=CDELX(I) DELY2=CDELY(J) DELZ2=CDELZ(K) HZ(I,J,K)=HZ(I,J,K+1)+DELZ2*((HX(I+1,J,K)-HX(I,J,K))/DELX2+(HY(I,J+1,K)-HY(I,J,K))/DELY2) ENDDO ENDDO ENDDO !$acc end kernels !$acc kernels async(11) DO K=1,NZ/2-1 DO J=1,NY DO I=1,NX DELX2=CDELX(I) DELY2=CDELY(J) DELZ2=CDELZ(K) HZ(I,J,K+1)=HZ(I,J,K)-DELZ2*((HX(I+1,J,K)-HX(I,J,K))/DELX2+(HY(I,J+1,K)-HY(I,J,K))/DELY2) ENDDO ENDDO ENDDO !$acc end kernels !$acc wait !===================end of updating Hz==========================! enddo !$acc end data call cpu_time(t2) t=t2-t1 print*,'The computing time for this fraction is:', t deallocate(meps_r,mcq,msource,mdelt) call WriteRecFiles(num) write(*,'(1x,e20.10e3,3x,e20.10e3)')Hz(nxs,nys+2,Nzs_air(1)),Hz(Nxs,Nys+2,Nz/2+1) write(*,*)'Now loop is:',mstart(num)+mstop(num)-1 print*,mstop(num),'steps have just finished' ENDDO end subroutine Iteration