SUBROUTINE n2gb(n, p, x, b, calcr, calcj, iv, liv, lv, v) ! *** VERSION OF NL2SOL THAT HANDLES SIMPLE BOUNDS ON X *** USE nlsol IMPLICIT NONE ! *** PARAMETERS *** INTEGER, INTENT(IN) :: n, p REAL (dp), INTENT(IN OUT) :: x(:) REAL (dp), INTENT(IN) :: b(:,:) ! b(2,p) INTEGER, INTENT(IN OUT) :: iv(:) INTEGER, INTENT(IN) :: liv, lv REAL (dp), INTENT(IN OUT) :: v(:) INTERFACE SUBROUTINE calcr(n, p, x, nf, r) USE nlsol IMPLICIT NONE INTEGER, INTENT(IN) :: n, p INTEGER, INTENT(IN OUT) :: nf REAL (dp), INTENT(IN) :: x(:) REAL (dp), INTENT(OUT) :: r(:) END SUBROUTINE calcr SUBROUTINE calcj(n, p, x, nf, j) USE nlsol IMPLICIT NONE INTEGER, INTENT(IN) :: n, p INTEGER, INTENT(IN OUT) :: nf REAL (dp), INTENT(IN) :: x(:) REAL (dp), INTENT(OUT) :: j(:,:) ! j(n,p) END SUBROUTINE calcj SUBROUTINE rn2gb(b, d, dr, iv, liv, lv, n, nd, n1, n2, p, r, rd, v, x) USE nlsol IMPLICIT NONE REAL (dp), INTENT(IN) :: b(:,:) ! b(2,p) REAL (dp), INTENT(IN OUT) :: d(:) REAL (dp), INTENT(IN OUT) :: dr(:,:) ! dr(nd,p) INTEGER, INTENT(IN OUT) :: iv(:) INTEGER, INTENT(IN) :: liv INTEGER, INTENT(IN) :: lv INTEGER, INTENT(IN) :: n INTEGER, INTENT(IN) :: nd INTEGER, INTENT(IN OUT) :: n1 INTEGER, INTENT(IN OUT) :: n2 INTEGER, INTENT(IN) :: p REAL (dp), INTENT(IN OUT) :: r(:) REAL (dp), INTENT(IN OUT) :: rd(:) REAL (dp), INTENT(OUT) :: v(:) REAL (dp), INTENT(IN OUT) :: x(:) END SUBROUTINE rn2gb END INTERFACE ! *** DISCUSSION *** ! NOTE... NL2SOL (MENTIONED BELOW) IS A CODE FOR SOLVING ! NONLINEAR LEAST-SQUARES PROBLEMS. IT IS DESCRIBED IN ! ACM TRANS. MATH. SOFTWARE, VOL. 7 (1981), PP. 369-383 ! (AN ADAPTIVE NONLINEAR LEAST-SQUARES ALGORITHM, BY J.E. DENNIS, ! D.M. GAY, AND R.E. WELSCH). ! LIV GIVES THE LENGTH OF IV. IT MUST BE AT LEAST 82 + 4*P. ! IF NOT, THEN N2GB RETURNS WITH IV(1) = 15. WHEN N2GB ! RETURNS, THE MINIMUM ACCEPTABLE VALUE OF LIV IS STORED IN ! IV(LASTIV) = IV(44), (PROVIDED THAT LIV .GE. 44). ! LV GIVES THE LENGTH OF V. THE MINIMUM VALUE FOR LV IS ! LV0 = 105 + P*(N + 2*P + 21) + 2*N. IF LV IS SMALLER THAN THIS, ! THEN N2GB RETURNS WITH IV(1) = 16. WHEN N2GB RETURNS, THE ! MINIMUM ACCEPTABLE VALUE OF LV IS STORED IN IV(LASTV) = IV(45) ! (PROVIDED LIV .GE. 45). ! RETURN CODES AND CONVERGENCE TOLERANCES ARE THE SAME AS FOR ! NL2SOL, WITH SOME SMALL EXTENSIONS... IV(1) = 15 MEANS LIV WAS ! TOO SMALL. IV(1) = 16 MEANS LV WAS TOO SMALL. ! THERE ARE TWO NEW V INPUT COMPONENTS... V(LMAXS) = V(36) AND ! V(SCTOL) = V(37) SERVE WHERE V(LMAX0) AND V(RFCTOL) FORMERLY DID ! IN THE SINGULAR CONVERGENCE TEST -- SEE THE NL2SOL DOCUMENTATION. ! *** BOUNDS *** ! THE BOUNDS B(1,I) .LE. X(I) .LE. B(2,I), I = 1(1)P, ARE ENFORCED. ! *** DEFAULT VALUES *** ! DEFAULT VALUES ARE PROVIDED BY SUBROUTINE IVSET, RATHER THAN ! DFAULT. THE CALLING SEQUENCE IS... ! CALL IVSET(1, IV, LIV, LV, V) ! THE FIRST PARAMETER IS AN INTEGER 1. IF LIV AND LV ARE LARGE ! ENOUGH FOR IVSET, THEN IVSET SETS IV(1) TO 12. OTHERWISE IT ! SETS IV(1) TO 15 OR 16. CALLING N2GB WITH IV(1) = 0 CAUSES ALL ! DEFAULT VALUES TO BE USED FOR THE INPUT COMPONENTS OF IV AND V. ! IF YOU FIRST CALL IVSET, THEN SET IV(1) TO 13 AND CALL N2GB, ! THEN STORAGE ALLOCATION ONLY WILL BE PERFORMED. IN PARTICULAR, ! IV(D) = IV(27), IV(J) = IV(70), AND IV(R) = IV(61) WILL BE SET ! TO THE FIRST SUBSCRIPT IN V OF THE SCALE VECTOR, THE JACOBIAN ! MATRIX, AND THE RESIDUAL VECTOR RESPECTIVELY, PROVIDED LIV AND LV ! ARE LARGE ENOUGH. IF SO, THEN N2GB RETURNS WITH IV(1) = 14. ! WHEN CALLED WITH IV(1) = 14, N2GB ASSUMES THAT STORAGE HAS ! BEEN ALLOCATED, AND IT BEGINS THE MINIMIZATION ALGORITHM. ! *** SCALE VECTOR *** ! ONE DIFFERENCE WITH NL2SOL IS THAT THE SCALE VECTOR D IS ! STORED IN V, STARTING AT A DIFFERENT SUBSCRIPT. THE STARTING ! SUBSCRIPT VALUE IS STILL STORED IN IV(D) = IV(27). THE ! DISCUSSION OF DEFAULT VALUES ABOVE TELLS HOW TO HAVE IV(D) SET ! BEFORE THE ALGORITHM IS STARTED. ! *** GENERAL *** ! CODED BY DAVID M. GAY. ! *** EXTERNAL SUBROUTINES *** ! EXTERNAL ivset, rn2gb ! IVSET.... PROVIDES DEFAULT IV AND V INPUT COMPONENTS. ! RN2GB... CARRIES OUT OPTIMIZATION ITERATIONS. ! *** LOCAL VARIABLES *** INTEGER :: d1, iv1, n1, n2, nf, r1, rd1 REAL (dp), ALLOCATABLE :: dr(:,:) ! *** IV COMPONENTS *** INTEGER, PARAMETER :: d=27, j=70, r=61, regd0=82 !--------------------------------- BODY ------------------------------ IF (iv(1) == 0) CALL ivset(1, iv, liv, lv, v) iv1 = iv(1) IF (iv1 == 14) GO TO 10 IF (iv1 > 2 .AND. iv1 < 12) GO TO 10 IF (iv1 == 12) iv(1) = 13 IF (iv(1) == 13) iv(vneed) = iv(vneed) + p + n*(p+2) ALLOCATE( dr(n,p) ) CALL rn2gb(b, x, dr, iv, liv, lv, n, n, n1, n2, p, v, v, v, x) IF (iv(1) /= 14) GO TO 999 ! *** STORAGE ALLOCATION *** iv(d) = iv(nextv) iv(r) = iv(d) + p iv(regd0) = iv(r) + n iv(j) = iv(regd0) + n iv(nextv) = iv(j) + n*p IF (iv1 == 13) GO TO 999 10 d1 = iv(d) r1 = iv(r) rd1 = iv(regd0) 20 CALL rn2gb(b, v(d1:), dr, iv, liv, lv, n, n, n1, n2, p, v(r1:), & v(rd1:), v, x) IF (iv(1) == 2) THEN GO TO 50 ELSE IF (iv(1) > 2) THEN GO TO 999 END IF ! *** NEW FUNCTION VALUE (R VALUE) NEEDED *** nf = iv(nfcall) CALL calcr(n, p, x, nf, v(r1:)) IF (nf > 0) GO TO 40 iv(toobig) = 1 GO TO 20 40 IF (iv(1) > 0) GO TO 20 ! *** COMPUTE DR = GRADIENT OF R COMPONENTS *** 50 CALL calcj(n, p, x, iv(nfgcal), dr) IF (iv(nfgcal) == 0) iv(toobig) = 1 GO TO 20 999 RETURN ! *** LAST CARD OF N2GB FOLLOWS *** END SUBROUTINE n2gb