! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE VA15AD ###### !###### ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! !----------------------------------------------------------------------- ! ! PURPOSE: ! ! minimization code. ! !----------------------------------------------------------------------- ! ! AUTHOR: ! ! unknown, copied from Florida state University. ! !----------------------------------------------------------------------- ! ! ! ---------------------------------------------------------------------- ! ! CALL VA15AD(Numctr,MGRA,ctrv,CFUN,grad,DIAGCO,DIAG,IPRINT, ! : EPS,SWORK,YWORK,POINT,WORK,IFLAG,FTOL) ! ! SUBROUTINE va15ad(n,m,x,f,g,diagco,diag,iprint,eps,s,y, & 1,3 point,w,iflag,ftol) ! ! REAL :: x(n),g(n),s(m*n),y(m*n),diag(n),w(n+2*m) REAL :: ftol,gtol,xtol,stpmin,stpmax,stp,f,ys,sq, & yr,beta,one,zero,eps,xnorm,gnorm,yy,ddot,stp1 ! ! INTEGER :: bound,lp,iter,nfun,nfev,iprint(2),point,cp,iflag LOGICAL :: finish,diagco COMMON /va15dd/mp,lp, gtol SAVE DATA one,zero/1.0E+0,0.0E+0/ ! ! ------------------------------------------------------------ ! INITIALIZE ! ------------------------------------------------------------ ! IF(iflag == 0) GO TO 1 GO TO (72,10) iflag 1 iter= 0 IF(n <= 0.OR.m <= 0) GO TO 96 IF(gtol <= 1.d-04) THEN IF(lp > 0) WRITE(lp,145) gtol=1.d-02 END IF nfun= 1 point= 0 finish= .false. IF(diagco) THEN DO i=1,n IF (diag(i) <= zero) GO TO 95 END DO ELSE DO i=1,n diag(i)= 1.0D0 END DO END IF DO i=1,n s(i)= -g(i)*diag(i) END DO gnorm= SQRT(ddot(n,g,1,g,1)) IF( gnorm > 0.0 ) THEN stp1= one/gnorm ELSE iflag=-13 return ENDIF ! ! PARAMETERS FOR LINE SEARCH ROUTINE ! ---------------------------------- xtol= 1.0D-17 stpmin= 1.0D-20 stpmax= 1.0D+20 maxfev= 20 ! print*,'iprint=',iprint,iter,nfun,n,m,f,stp,finish CALL va15bd(iprint,iter,nfun, & n,m,x,f,g,stp,finish) ! ! ------------------------------------------------------------ ! MAIN ITERATION LOOP ! -------------------------------------------------------- ! 8 iter= iter+1 info=0 bound=iter-1 IF (iter > m)bound=m IF(iter == 1) GO TO 65 ! ! ------------------------------------------------------------ ! COMPUTE -HG AND THE DIAGONAL SCALING MATRIX IN DIAG ! ------------------------------------------------------------ ! IF(.NOT.diagco) THEN DO i=1,n diag(i)= ys/yy END DO ELSE iflag=2 RETURN END IF 10 CONTINUE DO i=1,n IF (diag(i) <= zero) GO TO 95 END DO ! cp= point IF (point == 0) cp=m w(n+cp)= one/ys DO i=1,n w(i)= -g(i) END DO cp= point DO ii= 1,bound cp=cp-1 IF (cp == -1)cp=m-1 sq= ddot(n,s(cp*n+1),1,w,1) w(n+m+cp+1)= w(n+cp+1)*sq DO k=1,n w(k)= w(k)-w(n+m+cp+1)*y(cp*n+k) END DO END DO ! DO i=1,n w(i)=diag(i)*w(i) END DO DO ii=1,bound yr= ddot(n,y(cp*n+1),1,w,1) beta= w(n+cp+1)*yr DO k=1,n w(k)= w(k)+s(cp*n+k)*(w(n+m+cp+1)-beta) END DO cp=cp+1 IF (cp == m)cp=0 END DO ! ! ------------------------------------------------------------ ! STORE THE NEW DIRECTION IN S ! ------------------------------------------------------------ ! DO j=1,n s(point*n+j)= w(j) END DO ! ! ------------------------------------------------------------ ! OBTAIN THE MINIMIZER OF THE FUNCTION ALONG THE ! DIRECTION S BY USING THE LINE SEARCH ROUTINE OF VD05AD ! ------------------------------------------------------------ 65 nfev=0 stp=one IF (iter == 1) stp=stp1 DO i=1,n w(i)=g(i) END DO 72 CONTINUE ! CALL vd05ad(n,x,f,g,s(point*n+1),stp,ftol,gtol, & xtol,stpmin,stpmax,maxfev,info,nfev,diag) ! IF (info == -1) THEN iflag=1 RETURN END IF IF (info /= 1) GO TO 90 nfun= nfun + nfev ! ! ------------------------------------------------------------ ! COMPUTE THE NEW S AND Y ! ------------------------------------------------------------ ! npt=point*n DO i=1,n s(npt+i)= stp*s(npt+i) y(npt+i)= g(i)-w(i) END DO ys= ddot(n,y(npt+1),1,s(npt+1),1) yy= ddot(n,y(npt+1),1,y(npt+1),1) point=point+1 IF (point == m)point=0 ! ! ------------------------------------------------------------ ! CONVERGENCE CHECK ! ------------------------------------------------------------ ! gnorm= ddot(n,g,1,g,1) gnorm=SQRT(gnorm) xnorm= ddot(n,x,1,x,1) xnorm=SQRT(xnorm) ! xnorm= MAX1(1.0,xnorm) xnorm= MAX(1.0,xnorm) ! IF (gnorm/xnorm <= eps) finish=.true. ! CALL va15bd(iprint,iter,nfun, & n,m,x,f,g,stp,finish) IF (finish) THEN iflag=0 RETURN END IF GO TO 8 ! ! ------------------------------------------------------------ ! END OF MAIN ITERATION LOOP. ERROR EXITS. ! ------------------------------------------------------------ ! 90 IF(lp <= 0) RETURN IF (info == 0) THEN iflag= -1 WRITE(lp,100)iflag ELSE IF (info == 2) THEN iflag= -2 WRITE(lp,105)iflag ELSE IF (info == 3) THEN iflag= -3 WRITE(lp,110)iflag ELSE IF (info == 4) THEN iflag= -4 WRITE(lp,115)iflag ELSE IF (info == 5) THEN iflag= -5 WRITE(lp,120)iflag ELSE IF (info == 6) THEN iflag= -6 WRITE(lp,125)iflag END IF RETURN ! 95 iflag= -7 IF(lp > 0) WRITE(lp,135)iflag,i RETURN 96 iflag= -8 IF(lp > 0) WRITE(lp,140)iflag ! ! ------------------------------------------------------------ ! FORMATS ! ------------------------------------------------------------ ! 100 FORMAT(/' IFLAG= ',i2,/' IMPROPER INPUT PARAMETERS DURING', & ' THE LINE SEARCH.') 105 FORMAT(/' IFLAG= ',i2,/' RELATIVE WIDTH OF THE INTERVAL OF', & ' UNCERTAINTY IN THE LINE SEARCH' & /'IS OF THE ORDER OF machine roundoff.') 110 FORMAT(/' IFLAG= ',i2,/' NUMBER OF CALLS TO FUNCTION IN THE', & ' LINE SEARCH HAS REACHED 20.') 115 FORMAT(/' IFLAG= ',i2,/' THE STEP IN THE LINE SEARCH IS', & ' TOO SMALL.') 120 FORMAT(/' IFLAG= ',i2,/' THE STEP IN THE LINE SEARCH IS', & ' TOO LARGE.') 125 FORMAT(/' IFLAG= ',i2,/' ROUNDING ERRORS PREVENT FURTHER', & ' PROGRESS IN THE LINE SEARCH.') 135 FORMAT(/' IFLAG= ',i2,/' THE',i5,'-TH DIAGONAL ELEMENT OF THE', & ' INVERSE HESSIAN APPROXIMATION IS NOT POSITIVE') 140 FORMAT(/' IFLAG= ',i2,/' IMPROPER INPUT PARAMETERS (N OR M', & ' ARE NOT POSITIVE)') 145 FORMAT(/' GTOL IS LESS THAN OR EQUAL TO 1.D-04', & / 'IT HAS BEEN RESET TO 1.D-02') RETURN END SUBROUTINE va15ad ! ! ! ! SUBROUTINE va15bd(iprint,iter,nfun, & 2 n,m,x,f,g,stp,finish) ! ! --------------------------------------------------------------------- ! THIS ROUTINE PRINTS MONITORING INFORMATION. THE FREQUENCY AND AMOUNT ! OF OUTPUT ARE SPECIFIED AS FOLLOWS: ! ! IPRINT(1) < 0 : NO OUTPUT IS GENERATED ! IPRINT(1) = 0 : OUTPUT ONLY AT FIRST AND LAST ITERATION ! IPRINT(1) 0 : OUTPUT EVERY IPRINT(1) ITERATION ! IPRINT(2) = 0 : ITERATION COUNT, FUNCTION VALUE, NORM OF THE GRADIENT ! ,NUMBER OF FUNCTION CALLS AND STEP LENGTH ! IPRINT(2) = 1 : + VECTOR OF VARIABLES AND GRADIENT VECTOR AT THE ! INITIAL POINT ! IPRINT(2) = 2 : + VECTOR OF VARIABLES ! IPRINT(2) = 3 : + GRADIENT VECTOR ! --------------------------------------------------------------------- ! REAL :: x(n),g(n),f,gnorm,stp,factor,ddot,gtol INTEGER :: iprint(2),iter,nfun,prob,lp LOGICAL :: finish COMMON /set/ factor,prob COMMON /va15dd/mp,lp, gtol ! IF (iprint(1) < 0)RETURN gnorm= ddot(n,g,1,g,1) gnorm= SQRT(gnorm) IF (iter == 0)THEN WRITE(mp,10) WRITE(mp,20) prob,n,m WRITE(mp,30)f,gnorm IF (iprint(2) >= 1)THEN WRITE(mp,40) WRITE(mp,50) (x(i),i=1,n) WRITE(mp,60) WRITE(mp,50) (g(i),i=1,n) END IF WRITE(mp,10) WRITE(mp,70) ELSE IF ((iprint(1) == 0).AND.(iter /= 1.AND..NOT.finish))RETURN IF (iprint(1) /= 0)THEN IF(MOD(iter-1,iprint(1)) == 0.OR.finish)THEN WRITE(mp,80)iter,nfun,f,gnorm,stp ELSE RETURN END IF ELSE WRITE(mp,80)iter,nfun,f,gnorm,stp END IF IF (iprint(2) == 2.OR.iprint(2) == 3)THEN IF (finish)THEN WRITE(mp,90) ELSE WRITE(mp,40) END IF WRITE(mp,50)(x(i),i=1,n) IF (iprint(2) == 3)THEN WRITE(mp,60) WRITE(mp,50)(g(i),i=1,n) END IF END IF IF (finish) WRITE(mp,100) END IF ! 10 FORMAT('*************************************************') 20 FORMAT(' PROB=',i3,' N=',i9,' NUMBER OF CORRECTIONS=',i2) 30 FORMAT(' F= ',1PD10.3,' GNORM= ',1PD10.3) 40 FORMAT(' VECTOR X= ') 50 FORMAT(6(2X,1PD10.3)) 60 FORMAT(' GRADIENT VECTOR G= ') 70 FORMAT(/' I NFN',4X,'FUNC',8X,'GNORM',7X,'STEPLENGTH'/) 80 FORMAT(2(i4,1X),3X,3(1PD10.3,2X)) 90 FORMAT(' FINAL POINT X= ') 100 FORMAT(/' THE MINIMIZATION TERMINATED WITHOUT DETECTING ERRORS.', & /' IFLAG = 0') ! RETURN END SUBROUTINE va15bd ! ! ---------------------------------------------------------- ! DATA BLOCK ! ---------------------------------------------------------- ! BLOCK DATA va15cd COMMON /va15dd/mp,lp, gtol INTEGER :: lp REAL :: gtol DATA mp,lp,gtol/6,6,9.0E-01/ END ! ! ------------------------------------------------------------- ! SUBROUTINE vd05ad(n,x,f,g,s,stp,ftol,gtol,xtol, & 1,2 stpmin,stpmax,maxfev,info,nfev,wa) INTEGER :: n,maxfev,info,nfev REAL :: f,stp,ftol,gtol,xtol,stpmin,stpmax REAL :: x(n),g(n),s(n),wa(n) SAVE ! ********** ! ! SUBROUTINE VD05AD ! ! THE PURPOSE OF VD05AD IS TO FIND A STEP WHICH SATISFIES ! A SUFFICIENT DECREASE CONDITION AND A CURVATURE CONDITION. ! THE USER MUST PROVIDE A SUBROUTINE WHICH CALCULATES THE ! FUNCTION AND THE GRADIENT. ! ! AT EACH STAGE THE SUBROUTINE UPDATES AN INTERVAL OF ! UNCERTAINTY WITH ENDPOINTS STX AND STY. THE INTERVAL OF ! UNCERTAINTY IS INITIALLY CHOSEN SO THAT IT CONTAINS A ! MINIMIZER OF THE MODIFIED FUNCTION ! ! F(X+STP*S) - F(X) - FTOL*STP*(GRADF(X)'S). ! ! IF A STEP IS OBTAINED FOR WHICH THE MODIFIED FUNCTION ! HAS A NONPOSITIVE FUNCTION VALUE AND NONNEGATIVE DERIVATIVE, ! THEN THE INTERVAL OF UNCERTAINTY IS CHOSEN SO THAT IT ! CONTAINS A MINIMIZER OF F(X+STP*S). ! ! THE ALGORITHM IS DESIGNED TO FIND A STEP WHICH SATISFIES ! THE SUFFICIENT DECREASE CONDITION ! ! F(X+STP*S) .LE. F(X) + FTOL*STP*(GRADF(X)'S), ! ! AND THE CURVATURE CONDITION ! ! ABS(GRADF(X+STP*S)'S)) .LE. GTOL*ABS(GRADF(X)'S). ! ! IF FTOL IS LESS THAN GTOL AND IF, FOR EXAMPLE, THE FUNCTION ! IS BOUNDED BELOW, THEN THERE IS ALWAYS A STEP WHICH SATISFIES ! BOTH CONDITIONS. IF NO STEP CAN BE FOUND WHICH SATISFIES BOTH ! CONDITIONS, THEN THE ALGORITHM USUALLY STOPS WHEN ROUNDING ! ERRORS PREVENT FURTHER PROGRESS. IN THIS CASE STP ONLY ! SATISFIES THE SUFFICIENT DECREASE CONDITION. ! ! THE SUBROUTINE STATEMENT IS ! ! SUBROUTINE VD05AD(N,X,F,G,S,STP,FTOL,GTOL,XTOL, ! STPMIN,STPMAX,MAXFEV,INFO,NFEV,WA) ! WHERE ! ! N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER ! OF VARIABLES. ! ! X IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE ! BASE POINT FOR THE LINE SEARCH. ON OUTPUT IT CONTAINS ! X + STP*S. ! ! F IS A VARIABLE. ON INPUT IT MUST CONTAIN THE VALUE OF F ! AT X. ON OUTPUT IT CONTAINS THE VALUE OF F AT X + STP*S. ! ! G IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE ! GRADIENT OF F AT X. ON OUTPUT IT CONTAINS THE GRADIENT ! OF F AT X + STP*S. ! ! S IS AN INPUT ARRAY OF LENGTH N WHICH SPECIFIES THE ! SEARCH DIRECTION. ! ! STP IS A NONNEGATIVE VARIABLE. ON INPUT STP CONTAINS AN ! INITIAL ESTIMATE OF A SATISFACTORY STEP. ON OUTPUT ! STP CONTAINS THE FINAL ESTIMATE. ! ! FTOL AND GTOL ARE NONNEGATIVE INPUT VARIABLES. TERMINATION ! OCCURS WHEN THE SUFFICIENT DECREASE CONDITION AND THE ! DIRECTIONAL DERIVATIVE CONDITION ARE SATISFIED. ! ! XTOL IS A NONNEGATIVE INPUT VARIABLE. TERMINATION OCCURS ! WHEN THE RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY ! IS AT MOST XTOL. ! ! STPMIN AND STPMAX ARE NONNEGATIVE INPUT VARIABLES WHICH ! SPECIFY LOWER AND UPPER BOUNDS FOR THE STEP. ! ! MAXFEV IS A POSITIVE INTEGER INPUT VARIABLE. TERMINATION ! OCCURS WHEN THE NUMBER OF CALLS TO FCN IS AT LEAST ! MAXFEV BY THE END OF AN ITERATION. ! ! INFO IS AN INTEGER OUTPUT VARIABLE SET AS FOLLOWS: ! ! INFO = 0 IMPROPER INPUT PARAMETERS. ! ! INFO =-1 A RETURN IS MADE TO COMPUTE THE FUNCTION AND GRADIENT. ! ! INFO = 1 THE SUFFICIENT DECREASE CONDITION AND THE ! DIRECTIONAL DERIVATIVE CONDITION HOLD. ! ! INFO = 2 RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY ! IS AT MOST XTOL. ! ! INFO = 3 NUMBER OF CALLS TO FCN HAS REACHED MAXFEV. ! ! INFO = 4 THE STEP IS AT THE LOWER BOUND STPMIN. ! ! INFO = 5 THE STEP IS AT THE UPPER BOUND STPMAX. ! ! INFO = 6 ROUNDING ERRORS PREVENT FURTHER PROGRESS. ! THERE MAY NOT BE A STEP WHICH SATISFIES THE ! SUFFICIENT DECREASE AND CURVATURE CONDITIONS. ! TOLERANCES MAY BE TOO SMALL. ! ! NFEV IS AN INTEGER OUTPUT VARIABLE SET TO THE NUMBER OF ! CALLS TO FCN. ! ! WA IS A WORK ARRAY OF LENGTH N. ! ! SUBPROGRAMS CALLED ! ! HARWELL-SUPPLIED...VD05BD ! ! FORTRAN-SUPPLIED...ABS,MAX,MIN ! ! ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983 ! JORGE J. MORE', DAVID J. THUENTE ! ! ********** INTEGER :: infoc,j LOGICAL :: brackt,stage1 REAL :: dg,dgm,dginit,dgtest,dgx,dgxm,dgy,dgym, & finit,ftest1,fm,fx,fxm,fy,fym,p5,p66,stx,sty, & stmin,stmax,width,width1,xtrapf,zero DATA p5,p66,xtrapf,zero /0.5E0,0.66E0,4.0E0,0.0E0/ IF(info == -1) GO TO 45 infoc = 1 ! ! CHECK THE INPUT PARAMETERS FOR ERRORS. ! IF (n <= 0 .OR. stp <= zero .OR. ftol < zero .OR. & gtol < zero .OR. xtol < zero .OR. stpmin < zero & .OR. stpmax < stpmin .OR. maxfev <= 0) RETURN ! ! COMPUTE THE INITIAL GRADIENT IN THE SEARCH DIRECTION ! AND CHECK THAT S IS A DESCENT DIRECTION. ! dginit = zero DO j = 1, n dginit = dginit + g(j)*s(j) END DO IF (dginit >= zero) RETURN ! ! INITIALIZE LOCAL VARIABLES. ! brackt = .false. stage1 = .true. nfev = 0 finit = f dgtest = ftol*dginit width = stpmax - stpmin width1 = width/p5 DO j = 1, n wa(j) = x(j) END DO ! ! THE VARIABLES STX, FX, DGX CONTAIN THE VALUES OF THE STEP, ! FUNCTION, AND DIRECTIONAL DERIVATIVE AT THE BEST STEP. ! THE VARIABLES STY, FY, DGY CONTAIN THE VALUE OF THE STEP, ! FUNCTION, AND DERIVATIVE AT THE OTHER ENDPOINT OF ! THE INTERVAL OF UNCERTAINTY. ! THE VARIABLES STP, F, DG CONTAIN THE VALUES OF THE STEP, ! FUNCTION, AND DERIVATIVE AT THE CURRENT STEP. ! stx = zero fx = finit dgx = dginit sty = zero fy = finit dgy = dginit ! ! START OF ITERATION. ! 30 CONTINUE ! ! SET THE MINIMUM AND MAXIMUM STEPS TO CORRESPOND ! TO THE PRESENT INTERVAL OF UNCERTAINTY. ! IF (brackt) THEN stmin = MIN(stx,sty) stmax = MAX(stx,sty) ELSE stmin = stx stmax = stp + xtrapf*(stp - stx) END IF ! ! FORCE THE STEP TO BE WITHIN THE BOUNDS STPMAX AND STPMIN. ! stp = MAX(stp,stpmin) stp = MIN(stp,stpmax) ! print*,'stp =================',stp ! ! IF AN UNUSUAL TERMINATION IS TO OCCUR THEN LET ! STP BE THE LOWEST POINT OBTAINED SO FAR. ! IF ((brackt .AND. (stp <= stmin .OR. stp >= stmax)) & .OR. nfev >= maxfev-1 .OR. infoc == 0 & .OR. (brackt .AND. stmax-stmin <= xtol*stmax)) stp = stx ! ! EVALUATE THE FUNCTION AND GRADIENT AT STP ! AND COMPUTE THE DIRECTIONAL DERIVATIVE. ! DO j = 1, n x(j) = wa(j) + stp*s(j) END DO info=-1 RETURN ! 45 info=0 nfev = nfev + 1 dg = zero DO j = 1, n dg = dg + g(j)*s(j) END DO ftest1 = finit + stp*dgtest ! ! TEST FOR CONVERGENCE. ! IF ((brackt .AND. (stp <= stmin .OR. stp >= stmax)) .OR. infoc == 0) info = 6 IF (stp == stpmax .AND. f <= ftest1 .AND. dg <= dgtest) info = 5 IF (stp == stpmin .AND. (f > ftest1 .OR. dg >= dgtest)) info = 4 IF (nfev >= maxfev) info = 3 IF (brackt .AND. stmax-stmin <= xtol*stmax) info = 2 IF (f <= ftest1 .AND. ABS(dg) <= gtol*(-dginit)) info = 1 ! ! CHECK FOR TERMINATION. ! IF (info /= 0) RETURN ! ! IN THE FIRST STAGE WE SEEK A STEP FOR WHICH THE MODIFIED ! FUNCTION HAS A NONPOSITIVE VALUE AND NONNEGATIVE DERIVATIVE. ! IF (stage1 .AND. f <= ftest1 .AND. & dg >= MIN(ftol,gtol)*dginit) stage1 = .false. ! ! A MODIFIED FUNCTION IS USED TO PREDICT THE STEP ONLY IF ! WE HAVE NOT OBTAINED A STEP FOR WHICH THE MODIFIED ! FUNCTION HAS A NONPOSITIVE FUNCTION VALUE AND NONNEGATIVE ! DERIVATIVE, AND IF A LOWER FUNCTION VALUE HAS BEEN ! OBTAINED BUT THE DECREASE IS NOT SUFFICIENT. ! IF (stage1 .AND. f <= fx .AND. f > ftest1) THEN ! ! DEFINE THE MODIFIED FUNCTION AND DERIVATIVE VALUES. ! fm = f - stp*dgtest fxm = fx - stx*dgtest fym = fy - sty*dgtest dgm = dg - dgtest dgxm = dgx - dgtest dgym = dgy - dgtest ! ! CALL CSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY ! AND TO COMPUTE THE NEW STEP. ! CALL vd05bd(stx,fxm,dgxm,sty,fym,dgym,stp,fm,dgm, & brackt,stmin,stmax,infoc) ! ! RESET THE FUNCTION AND GRADIENT VALUES FOR F. ! fx = fxm + stx*dgtest fy = fym + sty*dgtest dgx = dgxm + dgtest dgy = dgym + dgtest ELSE ! ! CALL VD05BD TO UPDATE THE INTERVAL OF UNCERTAINTY ! AND TO COMPUTE THE NEW STEP. ! CALL vd05bd(stx,fx,dgx,sty,fy,dgy,stp,f,dg, & brackt,stmin,stmax,infoc) END IF ! ! FORCE A SUFFICIENT DECREASE IN THE SIZE OF THE ! INTERVAL OF UNCERTAINTY. ! IF (brackt) THEN IF (ABS(sty-stx) >= p66*width1) stp = stx + p5*(sty - stx) width1 = width width = ABS(sty-stx) END IF ! ! END OF ITERATION. ! GO TO 30 ! ! LAST CARD OF SUBROUTINE VD05AD. ! END SUBROUTINE vd05ad ! ! ! ! SUBROUTINE vd05bd(stx,fx,dx,sty,fy,dy,stp,fp,dp,brackt, & 2 stpmin,stpmax,info) INTEGER :: info REAL :: stx,fx,dx,sty,fy,dy,stp,fp,dp,stpmin,stpmax LOGICAL :: brackt,bound ! ********** ! ! SUBROUTINE VD05BD ! ! THE PURPOSE OF VD05BD IS TO COMPUTE A SAFEGUARDED STEP FOR ! A LINESEARCH AND TO UPDATE AN INTERVAL OF UNCERTAINTY FOR ! A MINIMIZER OF THE FUNCTION. ! ! THE PARAMETER STX CONTAINS THE STEP WITH THE LEAST FUNCTION ! VALUE. THE PARAMETER STP CONTAINS THE CURRENT STEP. IT IS ! ASSUMED THAT THE DERIVATIVE AT STX IS NEGATIVE IN THE ! DIRECTION OF THE STEP. IF BRACKT IS SET TRUE THEN A ! MINIMIZER HAS BEEN BRACKETED IN AN INTERVAL OF UNCERTAINTY ! WITH ENDPOINTS STX AND STY. ! ! THE SUBROUTINE STATEMENT IS ! ! SUBROUTINE VD05BD(STX,FX,DX,STY,FY,DY,STP,FP,DP,BRACKT, ! STPMIN,STPMAX,INFO) ! ! WHERE ! ! STX, FX, AND DX ARE VARIABLES WHICH SPECIFY THE STEP, ! THE FUNCTION, AND THE DERIVATIVE AT THE BEST STEP OBTAINED ! SO FAR. THE DERIVATIVE MUST BE NEGATIVE IN THE DIRECTION ! OF THE STEP, THAT IS, DX AND STP-STX MUST HAVE OPPOSITE ! SIGNS. ON OUTPUT THESE PARAMETERS ARE UPDATED APPROPRIATELY. ! ! STY, FY, AND DY ARE VARIABLES WHICH SPECIFY THE STEP, ! THE FUNCTION, AND THE DERIVATIVE AT THE OTHER ENDPOINT OF ! THE INTERVAL OF UNCERTAINTY. ON OUTPUT THESE PARAMETERS ARE ! UPDATED APPROPRIATELY. ! ! STP, FP, AND DP ARE VARIABLES WHICH SPECIFY THE STEP, ! THE FUNCTION, AND THE DERIVATIVE AT THE CURRENT STEP. ! IF BRACKT IS SET TRUE THEN ON INPUT STP MUST BE ! BETWEEN STX AND STY. ON OUTPUT STP IS SET TO THE NEW STEP. ! ! BRACKT IS A LOGICAL VARIABLE WHICH SPECIFIES IF A MINIMIZER ! HAS BEEN BRACKETED. IF THE MINIMIZER HAS NOT BEEN BRACKETED ! THEN ON INPUT BRACKT MUST BE SET FALSE. IF THE MINIMIZER ! IS BRACKETED THEN ON OUTPUT BRACKT IS SET TRUE. ! ! STPMIN AND STPMAX ARE INPUT VARIABLES WHICH SPECIFY LOWER ! AND UPPER BOUNDS FOR THE STEP. ! ! INFO IS AN INTEGER OUTPUT VARIABLE SET AS FOLLOWS: ! IF INFO = 1,2,3,4,5, THEN THE STEP HAS BEEN COMPUTED ! ACCORDING TO ONE OF THE FIVE CASES BELOW. OTHERWISE ! INFO = 0, AND THIS INDICATES IMPROPER INPUT PARAMETERS. ! ! SUBPROGRAMS CALLED ! ! FORTRAN-SUPPLIED ... ABS,MAX,MIN,SQRT ! ! ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983 ! JORGE J. MORE', DAVID J. THUENTE ! ! ********** REAL :: gamma,p,q,r,s,sgnd,stpc,stpf,stpq,theta info = 0 ! ! CHECK THE INPUT PARAMETERS FOR ERRORS. ! IF ((brackt .AND. (stp <= MIN(stx,sty) .OR. stp >= MAX(stx,sty))) .OR. & dx*(stp-stx) >= 0.0 .OR. stpmax < stpmin) RETURN ! ! DETERMINE IF THE DERIVATIVES HAVE OPPOSITE SIGN. ! sgnd = dp*(dx/ABS(dx)) ! ! FIRST CASE. A HIGHER FUNCTION VALUE. ! THE MINIMUM IS BRACKETED. IF THE CUBIC STEP IS CLOSER ! TO STX THAN THE QUADRATIC STEP, THE CUBIC STEP IS TAKEN, ! ELSE THE AVERAGE OF THE CUBIC AND QUADRATIC STEPS IS TAKEN. ! IF (fp > fx) THEN info = 1 bound = .true. theta = 3*(fx - fp)/(stp - stx) + dx + dp s = MAX(ABS(theta),ABS(dx),ABS(dp)) gamma = s*SQRT((theta/s)**2 - (dx/s)*(dp/s)) IF (stp < stx) gamma = -gamma p = (gamma - dx) + theta q = ((gamma - dx) + gamma) + dp r = p/q stpc = stx + r*(stp - stx) stpq = stx + ((dx/((fx-fp)/(stp-stx)+dx))/2)*(stp - stx) IF (ABS(stpc-stx) < ABS(stpq-stx)) THEN stpf = stpc ELSE stpf = stpc + (stpq - stpc)/2 END IF brackt = .true. ! ! SECOND CASE. A LOWER FUNCTION VALUE AND DERIVATIVES OF ! OPPOSITE SIGN. THE MINIMUM IS BRACKETED. IF THE CUBIC ! STEP IS CLOSER TO STX THAN THE QUADRATIC (SECANT) STEP, ! THE CUBIC STEP IS TAKEN, ELSE THE QUADRATIC STEP IS TAKEN. ! ELSE IF (sgnd < 0.0) THEN info = 2 bound = .false. theta = 3*(fx - fp)/(stp - stx) + dx + dp s = MAX(ABS(theta),ABS(dx),ABS(dp)) gamma = s*SQRT((theta/s)**2 - (dx/s)*(dp/s)) IF (stp > stx) gamma = -gamma p = (gamma - dp) + theta q = ((gamma - dp) + gamma) + dx r = p/q stpc = stp + r*(stx - stp) stpq = stp + (dp/(dp-dx))*(stx - stp) IF (ABS(stpc-stp) > ABS(stpq-stp)) THEN stpf = stpc ELSE stpf = stpq END IF brackt = .true. ! ! THIRD CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE ! SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DECREASES. ! THE CUBIC STEP IS ONLY USED IF THE CUBIC TENDS TO INFINITY ! IN THE DIRECTION OF THE STEP OR IF THE MINIMUM OF THE CUBIC ! IS BEYOND STP. OTHERWISE THE CUBIC STEP IS DEFINED TO BE ! EITHER STPMIN OR STPMAX. THE QUADRATIC (SECANT) STEP IS ALSO ! COMPUTED AND IF THE MINIMUM IS BRACKETED THEN THE THE STEP ! CLOSEST TO STX IS TAKEN, ELSE THE STEP FARTHEST AWAY IS TAKEN. ! ELSE IF (ABS(dp) < ABS(dx)) THEN info = 3 bound = .true. theta = 3*(fx - fp)/(stp - stx) + dx + dp s = MAX(ABS(theta),ABS(dx),ABS(dp)) ! ! THE CASE GAMMA = 0 ONLY ARISES IF THE CUBIC DOES NOT TEND ! TO INFINITY IN THE DIRECTION OF THE STEP. ! gamma = s*SQRT(MAX(0.0,(theta/s)**2 - (dx/s)*(dp/s))) IF (stp > stx) gamma = -gamma p = (gamma - dp) + theta q = (gamma + (dx - dp)) + gamma r = p/q IF (r < 0.0 .AND. gamma /= 0.0) THEN stpc = stp + r*(stx - stp) ELSE IF (stp > stx) THEN stpc = stpmax ELSE stpc = stpmin END IF stpq = stp + (dp/(dp-dx))*(stx - stp) IF (brackt) THEN IF (ABS(stp-stpc) < ABS(stp-stpq)) THEN stpf = stpc ELSE stpf = stpq END IF ELSE IF (ABS(stp-stpc) > ABS(stp-stpq)) THEN stpf = stpc ELSE stpf = stpq END IF END IF ! ! FOURTH CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE ! SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DOES ! NOT DECREASE. IF THE MINIMUM IS NOT BRACKETED, THE STEP ! IS EITHER STPMIN OR STPMAX, ELSE THE CUBIC STEP IS TAKEN. ! ELSE info = 4 bound = .false. IF (brackt) THEN theta = 3*(fp - fy)/(sty - stp) + dy + dp s = MAX(ABS(theta),ABS(dy),ABS(dp)) gamma = s*SQRT((theta/s)**2 - (dy/s)*(dp/s)) IF (stp > sty) gamma = -gamma p = (gamma - dp) + theta q = ((gamma - dp) + gamma) + dy r = p/q stpc = stp + r*(sty - stp) stpf = stpc ELSE IF (stp > stx) THEN stpf = stpmax ELSE stpf = stpmin END IF END IF ! ! UPDATE THE INTERVAL OF UNCERTAINTY. THIS UPDATE DOES NOT ! DEPEND ON THE NEW STEP OR THE CASE ANALYSIS ABOVE. ! IF (fp > fx) THEN sty = stp fy = fp dy = dp ELSE IF (sgnd < 0.0) THEN sty = stx fy = fx dy = dx END IF stx = stp fx = fp dx = dp END IF ! ! COMPUTE THE NEW STEP AND SAFEGUARD IT. ! stpf = MIN(stpmax,stpf) stpf = MAX(stpmin,stpf) stp = stpf IF (brackt .AND. bound) THEN IF (sty > stx) THEN stp = MIN(stx+0.66*(sty-stx),stp) ELSE stp = MAX(stx+0.66*(sty-stx),stp) END IF END IF RETURN ! ! LAST CARD OF SUBROUTINE VD05BD. ! END SUBROUTINE vd05bd ! ! ! ! FUNCTION ddot(n,d,i1,s,i2) ! ! ------------------------------------------------------- ! THIS FUNCTION COMPUTES THE INNER PRODUCT OF TWO VECTORS ! ------------------------------------------------------- ! REAL :: d(n),s(n),prod INTEGER :: i1,i2 ! prod=0.0E0 DO i=1,n prod= prod+d(i)*s(i) END DO ! ddot= prod ! RETURN END FUNCTION ddot ! ! ! ################################################################## ! ################################################################## ! ###### ###### ! ###### SUBROUTINE ADWCONTRA ###### ! ###### ###### ! ###### Copyright (c) 1994 ###### ! ###### Center for the Analysis and Prediction of Storms ###### ! ###### University of Oklahoma. All rights reserved. ###### ! ###### ###### ! ################################################################## ! ################################################################## ! SUBROUTINE ADWCONTRA(nx,ny,nz,u,v,w,mapfct,j1,j2,j3,aj3z, & 1,1 rhostr,rhostru,rhostrv,rhostrw,wcont,ustr,vstr) ! !####################################################################### ! ! PURPOSE: ! ! Perform the adjoint operations on WCONTRA. WCONTRA ! calculates wcont, the contravariant vertical velocity (m/s) ! !####################################################################### ! ! AUTHOR: Jidong Gao ! 5/20/96 converted to ARPS4.0.22 ! !####################################################################### ! ! INPUT: ! ! nx Number of grid points in the x-direction (east/west) ! ny Number of grid points in the y-direction (north/south) ! nz Number of grid points in the vertical ! ! u x component of velocity at all time levels (m/s) ! v y component of velocity at all time levels (m/s) ! w Vertical component of Cartesian velocity ! at all time levels (m/s) ! ! mapfct Map factors at scalar, u and v points ! ! j1 Coordinate transform Jacobian -d(zp)/dx ! j2 Coordinate transform Jacobian -d(zp)/dy ! j3 Coordinate transform Jacobian d(zp)/dz ! aj3z Avgz of the coordinate transformation Jacobian d(zp)/dz ! ! rhostr j3 times base state density rhobar(kg/m**3). ! rhostru Average rhostr at u points (kg/m**3). ! rhostrv Average rhostr at v points (kg/m**3). ! rhostrw Average rhostr at w points (kg/m**3). ! ! OUTPUT: ! ! wcont Vertical component of contravariant velocity in ! computational coordinates (m/s) ! !####################################################################### ! ! !####################################################################### ! ! Variable Declarations. ! !####################################################################### ! IMPLICIT NONE INTEGER :: nx,ny,nz ! The number of grid points in 3 ! directions REAL :: u (nx,ny,nz) ! Total u-velocity (m/s) REAL :: v (nx,ny,nz) ! Total v-velocity (m/s) REAL :: w (nx,ny,nz) ! Total w-velocity (m/s) REAL :: mapfct(nx,ny,8) ! Map factors at scalar, u and v points REAL :: j1 (nx,ny,nz) ! Coordinate transform Jacobian ! defined as - d( zp )/d( x ). REAL :: j2 (nx,ny,nz) ! Coordinate transform Jacobian ! defined as - d( zp )/d( y ). REAL :: j3 (nx,ny,nz) ! Coordinate transform Jacobian ! defined as d( zp )/d( z ). REAL :: aj3z (nx,ny,nz) ! Coordinate transformation Jacobian defined ! as d( zp )/d( z ) AVERAGED IN THE Z-DIR. REAL :: rhostr(nx,ny,nz) ! j3 times base state density rhobar ! (kg/m**3). REAL :: rhostru(nx,ny,nz) ! Average rhostr at u points (kg/m**3). REAL :: rhostrv(nx,ny,nz) ! Average rhostr at v points (kg/m**3). REAL :: rhostrw(nx,ny,nz) ! Average rhostr at w points (kg/m**3). REAL :: wcont (nx,ny,nz) ! Vertical velocity in computational ! coordinates (m/s) REAL :: ustr (nx,ny,nz) ! temporary work array REAL :: vstr (nx,ny,nz) ! temporary work array real :: tem1 (nx,ny,nz) ! temporary work array real :: tem2 (nx,ny,nz) ! temporary work array ! ! !####################################################################### ! ! Include files: ! !####################################################################### ! INCLUDE 'globcst.inc' ! !----------------------------------------------------------------------- ! ! Misc. local variables: ! !----------------------------------------------------------------------- ! INTEGER :: i,j,k integer onvf ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! CALL advbcwcont(nx,ny,nz,wcont) IF( crdtrns == 0 ) THEN ! No coord. transformation case. DO k= 2,nz-1 DO j= 1,ny-1 DO i= 1,nx-1 w(i,j,k)=w(i,j,k) + wcont(i,j,k) wcont(i,j,k)=0.0 END DO END DO END DO ELSEIF( ternopt == 0) THEN DO k= 2,nz-1 DO j= 1,ny-1 DO i= 1,nx-1 w(i,j,k)=w(i,j,k) + wcont(i,j,k)/aj3z(i,j,k) wcont(i,j,k)=0.0 END DO END DO END DO ELSE DO k= 2,nz-1 DO j= 1,ny-1 DO i= 1,nx-1 ! wcont(i,j,k)= ( & ! ((ustr(i ,j,k)+ustr(i ,j,k-1))*j1(i ,j,k) & ! +(ustr(i+1,j,k)+ustr(i+1,j,k-1))*j1(i+1,j,k) & ! +(vstr(i ,j,k)+vstr(i ,j,k-1))*j2(i ,j,k) & ! +(vstr(i,j+1,k)+vstr(i,j+1,k-1))*j2(i,j+1,k)) & ! * mapfct(i,j,8) & ! / rhostrw(i,j,k) + w(i,j,k) & ! ) /aj3z(i,j,k) ! ustr(i,j,k )=ustr(i,j,k ) + wcont(i,j,k)*j1(i,j,k) & *mapfct(i,j,8)/rhostrw(i,j,k)/aj3z(i,j,k) ustr(i,j,k-1)=ustr(i,j,k-1) + wcont(i,j,k)*j1(i,j,k) & *mapfct(i,j,8)/rhostrw(i,j,k)/aj3z(i,j,k) ustr(i+1,j,k )=ustr(i+1,j,k ) + wcont(i,j,k)*j1(i+1,j,k) & *mapfct(i,j,8)/rhostrw(i,j,k)/aj3z(i,j,k) ustr(i+1,j,k-1)=ustr(i+1,j,k-1) + wcont(i,j,k)*j1(i+1,j,k) & *mapfct(i,j,8)/rhostrw(i,j,k)/aj3z(i,j,k) vstr(i ,j,k )=vstr(i ,j,k ) + wcont(i,j,k)*j2(i,j ,k) & *mapfct(i,j,8)/rhostrw(i,j,k)/aj3z(i,j,k) vstr(i ,j,k-1)=vstr(i ,j,k-1) + wcont(i,j,k)*j2(i,j ,k) & *mapfct(i,j,8)/rhostrw(i,j,k)/aj3z(i,j,k) vstr(i,j+1,k )=vstr(i,j+1,k ) + wcont(i,j,k)*j2(i,j+1,k) & *mapfct(i,j,8)/rhostrw(i,j,k)/aj3z(i,j,k) vstr(i,j+1,k-1)=vstr(i,j+1,k-1) + wcont(i,j,k)*j2(i,j+1,k) & *mapfct(i,j,8)/rhostrw(i,j,k)/aj3z(i,j,k) w(i,j,k)=w(i,j,k) + wcont(i,j,k)/aj3z(i,j,k) wcont(i,j,k) = 0.0 END DO END DO END DO DO k= 1,nz-1 DO j= 1,ny DO i= 1,nx-1 ! vstr(i,j,k)=v(i,j,k)*rhostrv(i,j,k) v(i,j,k)=v(i,j,k)+vstr(i,j,k)*rhostrv(i,j,k) vstr(i,j,k) = 0.0 END DO END DO END DO ! DO k= 1,nz-1 DO j= 1,ny-1 DO i= 1,nx ! ustr(i,j,k)=u(i,j,k)*rhostru(i,j,k) u(i,j,k)=u(i,j,k)+ustr(i,j,k)*rhostru(i,j,k) ustr(i,j,k)=0.0 END DO END DO END DO ! ENDIF RETURN END ! ! ! ################################################################## ! ################################################################## ! ###### ###### ! ###### SUBROUTINE ADVBCWCONT ###### ! ###### ###### ! ###### Copyright (c) 1992-1994 ###### ! ###### Center for the Analysis and Prediction of Storms ###### ! ###### University of Oklahoma. All rights reserved. ###### ! ###### ###### ! ################################################################## ! ################################################################## ! SUBROUTINE ADVBCWCONT(nx,ny,nz,wcont) 1,1 ! !----------------------------------------------------------------------- ! ! PURPOSE: ! ! Perform the adjoint of ! Set the top and bottom boundary conditions for wcont. ! !----------------------------------------------------------------------- ! ! AUTHOR: ! 5/22/96 Jidong Gao ! ! MODIFICATION HISTORY: ! !----------------------------------------------------------------------- ! ! INPUT : ! ! nx Number of grid points in the x-direction (east/west) ! ny Number of grid points in the y-direction (north/south) ! nz Number of grid points in the vertical ! ! wcont Contravariant vertical velocity (m/s) ! ! OUTPUT: ! ! wcont Top and bottom values of wcont. ! !----------------------------------------------------------------------- ! ! Variable Declarations: ! !----------------------------------------------------------------------- ! implicit none ! Force explicit declarations integer nx,ny,nz ! Number of grid points in x, y and z ! directions real wcont (nx,ny,nz) ! Contravariant vertical velocity (m/s) ! !----------------------------------------------------------------------- ! ! Misc. local variables: ! !----------------------------------------------------------------------- ! integer i, j, k ! !----------------------------------------------------------------------- ! ! Include files: ! !----------------------------------------------------------------------- ! include 'bndry.inc' ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! !----------------------------------------------------------------------- ! ! Set the top boundary condition ! !----------------------------------------------------------------------- ! IF(tbc == 1) THEN ! Rigid lid boundary condition DO j=1,ny-1 DO i=1,nx-1 ! wcont(i,j,nz)=-wcont(i,j,nz-2) ! wcont(i,j,nz-1)=0.0 wcont(i,j,nz-2)=wcont(i,j,nz-2)-wcont(i,j,nz) wcont(i,j,nz)=0.0 wcont(i,j,nz-1)=0.0 END DO END DO ELSEIF(tbc == 2) THEN ! Periodic boundary condition. DO j=1,ny-1 DO i=1,nx-1 ! wcont(i,j,nz)=wcont(i,j,3) wcont(i,j,3)=wcont(i,j,3)+wcont(i,j,nz) wcont(i,j,nz)=0.0 END DO END DO ELSEIF(tbc == 3.OR.tbc == 4) THEN ! Zero normal gradient condition. DO j=1,ny-1 DO i=1,nx-1 ! wcont(i,j,nz)=wcont(i,j,nz-1) wcont(i,j,nz-1)=wcont(i,j,nz-1)+wcont(i,j,nz) wcont(i,j,nz) = 0.0 END DO END DO ELSE WRITE(6,900) 'VBCWCONT', tbc CALL arpsstop ("",1) stop ENDIF ! ! !----------------------------------------------------------------------- ! ! Set the bottom boundary condition ! !----------------------------------------------------------------------- ! IF(bbc == 1) THEN ! Non-penetrative ground condition DO j=1,ny-1 DO i=1,nx-1 ! wcont(i,j,1)=-wcont(i,j,3) ! wcont(i,j,2)=0.0 wcont(i,j,3)=wcont(i,j,3)-wcont(i,j,1) wcont(i,j,1)=0.0 wcont(i,j,2)=0.0 END DO END DO ELSEIF(bbc == 2) THEN ! Periodic boundary condition. DO j=1,ny-1 DO i=1,nx-1 ! wcont(i,j,1)=wcont(i,j,nz-2) wcont(i,j,nz-2)=wcont(i,j,nz-2)+wcont(i,j,1) wcont(i,j,1) = 0.0 END DO END DO ELSEIF(bbc.eq.3) THEN ! Zero normal gradient condition. DO j=1,ny-1 DO i=1,nx-1 ! wcont(i,j,1)=wcont(i,j,2) wcont(i,j,2)=wcont(i,j,2)+wcont(i,j,1) wcont(i,j,1)= 0.0 END DO END DO ELSE write(6,900) 'VBCWCONT', bbc STOP ENDIF 900 format(1x,'Invalid boundary condition option found in ',a, & /1x,'The option was ',i3,' Job stopped.') RETURN END