C subroutine "zerodivy" to a zero-free "upper part" of a given C axis-parallel rectangle C adapted from zerofind.f C Sven Ivansson 1990 SUBROUTINE ZERODIVY (CDETSUB, UPREAL1,UPREAL2,UPIMAG1,UPIMAG2, $ DDSUPMIN,DDSUPMAX,DDSUPFAKTMAX, DERIVDRELMAX,DRELMAX, $ DRELGOALFAKT, ARGDIFSTORE, $ NPLINMAX,IASFCALL,IASBACK, $ YBELOW) C cdetsub subroutine cdetsub (px,py, rlndet,cdet) gives C "the function" as dexp(rlndet)*cdet , "the C function" must be analytic inside the rectangle C and continuous up to the boundary and zero-free C on the boundary C upreal1,upreal2 horizontal limits of the rectangle C upimag1,upimag2 vertical limits of the rectangle C ddsupmin minimal step that is handled (strict limit), C always take ddsupmin >= 0.0d0 ("argseg") C ddsupmax maximal step ("argseg") C ddsupfaktmax maximal factor for step change ("argseg") C derivdrelmax maximum tolerable "relative difference" in the C "derivative estimation at up1" for the "safe C start", always take derivdrelmax < 1.0d0 C ("argseg") C drelmax maximum allowed relative change of the analytic C function in each step, always take drelmax < 1.0d0 C ("argseg") C drelgoalfakt for choosing "next step", always take C drelgoalfakt < 1.0d0 ("argseg") C argdifstore lower limit in degrees for storage, always C take argdifstore < 180.0d0 ("argseg") C nplinmax input/output (OBS) maximum current value of nplin C iasfcall input/output (OBS) total number of cdetsub calls C from argseg C iasback input/output (OBS) total number of "back steps" C upon unsuccessful return from argseg C ybelow output lower y limit of the zero-free rectangle IMPLICIT NONE INTEGER NPLINDIM PARAMETER ( NPLINDIM = 1000 ) C nplin <= nplindim REAL*8 UPREAL1,UPREAL2,UPIMAG1,UPIMAG2, DDSUPMIN,DDSUPMAX, $ DDSUPFAKTMAX, DERIVDRELMAX,DRELMAX,DRELGOALFAKT, ARGDIFSTORE EXTERNAL CDETSUB INTEGER NPLINMAX,IASFCALL,IASBACK REAL*8 YBELOW INTEGER NPLIN, IASFAIL, NROOT, $ NPLOK1,NPLOK2,NPLOK3,NPLOK4, INDEX, I, $ NPNEL(3:4) REAL ARGNEL1D,ARGNEL2D, DDSUPNEL11, $ ARGNEL(0:nplindim,3:4), DDSUPNEL(nplindim,3:3) !!! REAL*8 DDSUP1,ARGDIFTEST, Y1, $ YLOK, ARGSLASK, SLASK, RLNDET,RLNDET0, $ ARGLIN(0:nplindim), ALNLIN(0:nplindim), DDSUPLIN(nplindim), $ XYNEL(0:nplindim,3:4) COMPLEX*16 UP1,UP2, CDET,CDET0, $ UPLIN(0:nplindim) ARGDIFTEST = 0.5D0*ARGDIFSTORE + DASIND(DRELMAX) C --------------------------------------------------- C a "nel" rectangle ! attributes for the "successively stripped C with its side indices ! from below" "nel" rectangle C 2 / C -------------- / npnel(1:4) , numbers of points C ! ! / (excluding the initial ones) C 3! !4 ! xynel (0:npnel(,),1:4) , x/y coordinates C ! ! ! argnel (0:npnel(,),1:4) , arg(cdet) degrees C -------------- / ddsupnel (1:npnel(,),1:4) , "ddsupinf" C 1 / C C note: storage in general not necessary for "sides 1 and 2" in this C case, for ddsupnel not for "side 4" either C C --------------------------------------------------- C --------------------------------------------------- C initial round UP1 = DCMPLX ( UPREAL1, UPIMAG1 ) CALL CDETSUB (UPREAL1,UPIMAG1, RLNDET0,CDET0) UP2 = DCMPLX ( UPREAL2, UPIMAG1 ) DDSUP1 = 0.0D0 CALL ARGSEG (CDETSUB, UP1,UP2, RLNDET0,CDET0, DDSUP1, $ DDSUPMIN,DDSUPMAX,DDSUPFAKTMAX, DERIVDRELMAX,DRELMAX, $ DRELGOALFAKT, ARGDIFSTORE, NPLINDIM, $ NPLIN,UPLIN,ARGLIN,ALNLIN,DDSUPLIN, RLNDET,CDET, $ IASFCALL,IASFAIL) IF (NPLIN.GT.NPLINMAX) NPLINMAX = NPLIN IF (IASFAIL.NE.0) THEN WRITE(*,*) ' %%% ARGSEG FAILURE ON "BIG PART 1" %%% ' WRITE(*,*) ' iasfail=',IASFAIL WRITE(*,*) UP1 WRITE(*,*) UP2 STOP 316 END IF NPLOK1 = NPLIN ! ARGNEL1D = ARGLIN(NPLIN) - ARGLIN(0) ! DDSUPNEL11 = DDSUPLIN(1) ! ccc! npnel(1) = nplin ccc! do i = 0, nplin ccc! xynel(i,1) = dreal(uplin(i)) ccc! end do ccc! do i = 0, nplin ccc! argnel(i,1) = arglin(i) ccc! end do ccc! do i = 1, nplin ccc! ddsupnel(i,1) = ddsuplin(i) ccc! end do UP1 = UP2 UP2 = DCMPLX ( UPREAL2, UPIMAG2 ) DDSUP1 = DDSUPLIN(NPLIN) CALL ARGSEG (CDETSUB, UP1,UP2, RLNDET,CDET, DDSUP1, $ DDSUPMIN,DDSUPMAX,DDSUPFAKTMAX, DERIVDRELMAX,DRELMAX, $ DRELGOALFAKT, ARGDIFSTORE, NPLINDIM, $ NPLIN,UPLIN,ARGLIN,ALNLIN,DDSUPLIN, RLNDET,CDET, $ IASFCALL,IASFAIL) IF (NPLIN.GT.NPLINMAX) NPLINMAX = NPLIN IF (IASFAIL.NE.0) THEN WRITE(*,*) ' %%% ARGSEG FAILURE ON "BIG PART 4" %%% ' WRITE(*,*) ' iasfail=',IASFAIL WRITE(*,*) UP1 WRITE(*,*) UP2 STOP 316 END IF NPNEL(4) = NPLIN DO I = 0, NPLIN XYNEL(I,4) = DIMAG(UPLIN(I)) END DO DO I = 0, NPLIN ARGNEL(I,4) = ARGLIN(I) END DO ccc! do i = 1, nplin ccc! ddsupnel(i,4) = ddsuplin(i) ccc! end do UP1 = DCMPLX ( UPREAL1, UPIMAG1 ) UP2 = DCMPLX ( UPREAL1, UPIMAG2 ) DDSUP1 = DDSUPNEL11 CALL ARGSEG (CDETSUB, UP1,UP2, RLNDET0,CDET0, DDSUP1, $ DDSUPMIN,DDSUPMAX,DDSUPFAKTMAX, DERIVDRELMAX,DRELMAX, $ DRELGOALFAKT, ARGDIFSTORE, NPLINDIM, $ NPLIN,UPLIN,ARGLIN,ALNLIN,DDSUPLIN, RLNDET,CDET, $ IASFCALL,IASFAIL) IF (NPLIN.GT.NPLINMAX) NPLINMAX = NPLIN IF (IASFAIL.NE.0) THEN WRITE(*,*) ' %%% ARGSEG FAILURE ON "BIG PART 3" %%% ' WRITE(*,*) ' iasfail=',IASFAIL WRITE(*,*) UP1 WRITE(*,*) UP2 STOP 316 END IF NPNEL(3) = NPLIN DO I = 0, NPLIN XYNEL(I,3) = DIMAG(UPLIN(I)) END DO DO I = 0, NPLIN ARGNEL(I,3) = ARGLIN(I) END DO DO I = 1, NPLIN DDSUPNEL(I,3) = DDSUPLIN(I) END DO UP1 = UP2 UP2 = DCMPLX ( UPREAL2, UPIMAG2 ) DDSUP1 = DDSUPLIN(NPLIN) CALL ARGSEG (CDETSUB, UP1,UP2, RLNDET,CDET, DDSUP1, $ DDSUPMIN,DDSUPMAX,DDSUPFAKTMAX, DERIVDRELMAX,DRELMAX, $ DRELGOALFAKT, ARGDIFSTORE, NPLINDIM, $ NPLIN,UPLIN,ARGLIN,ALNLIN,DDSUPLIN, RLNDET,CDET, $ IASFCALL,IASFAIL) IF (NPLIN.GT.NPLINMAX) NPLINMAX = NPLIN IF (IASFAIL.NE.0) THEN WRITE(*,*) ' %%% ARGSEG FAILURE ON "BIG PART 2" %%%' WRITE(*,*) ' iasfail=',IASFAIL WRITE(*,*) UP1 WRITE(*,*) UP2 STOP 316 END IF NPLOK2 = NPLIN ! ARGNEL2D = ARGLIN(NPLIN) - ARGLIN(0) ! ccc! npnel(2) = nplin ccc! do i = 0, nplin ccc! xynel(i,2) = dreal(uplin(i)) ccc! end do ccc! do i = 0, nplin ccc! argnel(i,2) = arglin(i) ccc! end do ccc! do i = 1, nplin ccc! ddsupnel(i,2) = ddsuplin(i) ccc! end do C --------------------------------------------------- C division round 100 CONTINUE ccc! nplok1 = npnel(1) ccc! nplok2 = npnel(2) NPLOK3 = NPNEL(3) NPLOK4 = NPNEL(4) ARGSLASK = ( + ARGNEL1D $ - ARGNEL2D $ - ARGNEL(NPLOK3,3) + ARGNEL(0,3) $ + ARGNEL(NPLOK4,4) - ARGNEL(0,4) ) / $ 360.0D0 NROOT = IDNINT (ARGSLASK) IF (NROOT.EQ.0) THEN YBELOW = XYNEL(0,3) IF (YBELOW.GE.UPIMAG2) STOP 517 RETURN ELSE ccc! x1 = xynel(0,1) ccc! x2 = xynel(nplok1,1) Y1 = XYNEL(0,3) ccc! y2 = xynel(nplok3,3) END IF IF (NROOT.LT.0) STOP 125 110 CONTINUE ! y division YLOK = 0.5D0 * (Y1+UPIMAG2) 20 IF (YLOK.EQ.0.0D0) THEN YLOK = 0.5D0 * (Y1+YLOK) ! avoid the axes END IF INDEX = NPLOK3/2 DO WHILE (XYNEL(INDEX,3).LT.YLOK) INDEX = INDEX + 1 END DO DO WHILE (XYNEL(INDEX,3).GT.YLOK) INDEX = INDEX - 1 END DO UP1 = DCMPLX (UPREAL1,YLOK) CALL CDETSUB (UPREAL1,YLOK, RLNDET,CDET) UP2 = DCMPLX (UPREAL2,YLOK) DDSUP1 = DDSUPNEL(INDEX+1,3) CALL ARGSEG (CDETSUB, UP1,UP2, RLNDET,CDET, DDSUP1, $ DDSUPMIN,DDSUPMAX,DDSUPFAKTMAX, DERIVDRELMAX,DRELMAX, $ DRELGOALFAKT, ARGDIFSTORE, NPLINDIM, $ NPLIN,UPLIN,ARGLIN,ALNLIN,DDSUPLIN, RLNDET,CDET, $ IASFCALL,IASFAIL) IF (NPLIN.GT.NPLINMAX) NPLINMAX = NPLIN IF (IASFAIL.NE.0) THEN IASBACK = IASBACK + 1 YLOK = 0.5D0 * (Y1+YLOK) GOTO 20 END IF NPLOK1 = NPLIN ! ARGNEL1D = ARGLIN(NPLIN) - ARGLIN(0) ! ccc! npnel(1) = nplin ccc! do i = 0, nplin ccc! xynel(i,1) = dreal(uplin(i)) ccc! end do ccc! do i = 0, nplin ccc! argnel(i,1) = arglin(i) ccc! end do ccc! do i = 1, nplin ccc! ddsupnel(i,1) = ddsuplin(i) ccc! end do NPNEL(3) = NPLOK3 - INDEX XYNEL(0,3) = YLOK DO I = 1, NPNEL(3) XYNEL(I,3) = XYNEL(INDEX+I,3) END DO SLASK = 0.5D0 * ( ARGNEL(INDEX,3) + ARGNEL(INDEX+1,3) ) ARGSLASK = ARGLIN(0) + 360.0D0*IDNINT((SLASK-ARGLIN(0))/360.0D0) IF (DABS(ARGSLASK-SLASK).GE.ARGDIFTEST) THEN WRITE(*,*) WRITE(*,*) NROOT,' %%% argdiftest failure %%%' WRITE(*,*) SNGL(UPREAL1),SNGL(UPREAL2),SNGL(Y1),SNGL(UPIMAG2) STOP 103 END IF ARGNEL(0,3) = ARGSLASK DO I = 1, NPNEL(3) ARGNEL(I,3) = ARGNEL(INDEX+I,3) END DO DO I = 1, NPNEL(3) DDSUPNEL(I,3) = DDSUPNEL(INDEX+I,3) END DO INDEX = NPLOK4/2 DO WHILE (XYNEL(INDEX,4).LT.YLOK) INDEX = INDEX + 1 END DO DO WHILE (XYNEL(INDEX,4).GT.YLOK) INDEX = INDEX - 1 END DO NPNEL(4) = NPLOK4 - INDEX XYNEL(0,4) = YLOK DO I = 1, NPNEL(4) XYNEL(I,4) = XYNEL(INDEX+I,4) END DO SLASK = 0.5D0 * ( ARGNEL(INDEX,4) + ARGNEL(INDEX+1,4) ) ARGSLASK = ARGLIN(NPLIN) + 360.0D0* $ IDNINT((SLASK-ARGLIN(NPLIN))/360.0D0) IF (DABS(ARGSLASK-SLASK).GE.ARGDIFTEST) THEN WRITE(*,*) WRITE(*,*) NROOT,' %%% argdiftest failure %%%' WRITE(*,*) SNGL(UPREAL1),SNGL(UPREAL2),SNGL(Y1),SNGL(UPIMAG2) STOP 103 END IF ARGNEL(0,4) = ARGSLASK DO I = 1, NPNEL(4) ARGNEL(I,4) = ARGNEL(INDEX+I,4) END DO ccc! do i = 1, npnel(4) ccc! ddsupnel(i,4) = ddsupnel(index+i,4) ccc! end do GOTO 100 C --------------------------------------------------- END