LCOV - code coverage report
Current view: top level - num/private - mod_newuoa.f (source / functions) Coverage Total Hit
Test: coverage.info Lines: 66.8 % 916 612
Test Date: 2025-05-08 18:23:42 Functions: 83.3 % 6 5

            Line data    Source code
       1              :       module mod_newuoa
       2              :       use const_def, only: dp
       3              :       use math_lib
       4              : 
       5              :       contains
       6              : 
       7            3 :       subroutine do_newuoa(N,NPT,X,RHOBEG,RHOEND,IPRINT,MAXFUN,W,CALFUN,max_valid_value)
       8              :       implicit real(dp) (A-H,O-Z)
       9              :       dimension X(*),W(*)
      10              :       interface
      11              : #include "num_newuoa_proc.dek"
      12              :       end interface
      13              :       real(dp), intent(in) :: max_valid_value
      14              : !
      15              : !     This subroutine seeks the least value of a function of many variables,
      16              : !     by a trust region method that forms quadratic models by interpolation.
      17              : !     There can be some freedom in the interpolation conditions, which is
      18              : !     taken up by minimizing the Frobenius norm of the change to the second
      19              : !     derivative of the quadratic model, beginning with a zero matrix. The
      20              : !     arguments of the subroutine are as follows.
      21              : !
      22              : !     N must be set to the number of variables and must be at least two.
      23              : !     NPT is the number of interpolation conditions. Its value must be in the
      24              : !       interval [N+2,(N+1)(N+2)/2].
      25              : !     Initial values of the variables must be set in X(1),X(2),...,X(N). They
      26              : !       will be changed to the values that give the least calculated F.
      27              : !     RHOBEG and RHOEND must be set to the initial and final values of a trust
      28              : !       region radius, so both must be positive with RHOEND<=RHOBEG. Typically
      29              : !       RHOBEG should be about one tenth of the greatest expected change to a
      30              : !       variable, and RHOEND should indicate the accuracy that is required in
      31              : !       the final values of the variables.
      32              : !     The value of IPRINT should be set to 0, 1, 2 or 3, which controls the
      33              : !       amount of printing. Specifically, there is no output if IPRINT=0 and
      34              : !       there is output only at the return if IPRINT=1. Otherwise, each new
      35              : !       value of RHO is printed, with the best vector of variables so far and
      36              : !       the corresponding value of the objective function. Further, each new
      37              : !       value of F with its variables are output if IPRINT=3.
      38              : !     MAXFUN must be set to an upper bound on the number of calls of CALFUN.
      39              : !     The array W will be used for working space. Its length must be at least
      40              : !     (NPT+13)*(NPT+N)+3*N*(N+3)/2.
      41              : !
      42              : !     subroutine CALFUN (N,X,F) must be provided by the user. It must set F to
      43              : !     the value of the objective function for the variables X(1),X(2),...,X(N).
      44              : !
      45              : !     Partition the working space array, so that different parts of it can be
      46              : !     treated separately by the subroutine that performs the main calculation.
      47              : !
      48            3 :       NP=N+1
      49            3 :       NPTM=NPT-NP
      50            3 :       if (NPT < N+2 .or. NPT > ((N+2)*NP)/2) then
      51            0 :           PRINT 10
      52              :    10     FORMAT (/4X,'Return from NEWUOA because NPT is not in the required interval')
      53            0 :           GOTO 20
      54              :       end if
      55            3 :       NDIM=NPT+N
      56            3 :       IXB=1
      57            3 :       IXO=IXB+N
      58            3 :       IXN=IXO+N
      59            3 :       IXP=IXN+N
      60            3 :       IFV=IXP+N*NPT
      61            3 :       IGQ=IFV+NPT
      62            3 :       IHQ=IGQ+N
      63            3 :       IPQ=IHQ+(N*NP)/2
      64            3 :       IBMAT=IPQ+NPT
      65            3 :       IZMAT=IBMAT+NDIM*N
      66            3 :       ID=IZMAT+NPT*NPTM
      67            3 :       IVL=ID+N
      68            3 :       IW=IVL+NDIM
      69              : !
      70              : !     The above settings provide a partition of W for subroutine NEWUOB.
      71              : !     The partition requires the first NPT*(NPT+N)+5*N*(N+3)/2 elements of
      72              : !     W plus the space that is needed by the last array of NEWUOB.
      73              : !
      74              :       CALL NEWUOB (N,NPT,X,RHOBEG,RHOEND,IPRINT,MAXFUN,W(IXB),
      75              :      &  W(IXO),W(IXN),W(IXP),W(IFV),W(IGQ),W(IHQ),W(IPQ),W(IBMAT),
      76            3 :      &  W(IZMAT),NDIM,W(ID),W(IVL),W(IW),CALFUN,max_valid_value)
      77            3 :    20 RETURN
      78              :       end subroutine do_newuoa
      79              : 
      80              : 
      81          313 :       subroutine NEWUOB (N,NPT,X,RHOBEG,RHOEND,IPRINT,MAXFUN,XBASE,
      82            3 :      &  XOPT,XNEW,XPT,FVAL,GQ,HQ,PQ,BMAT,ZMAT,NDIM,D,VLAG,W,
      83              :      &  CALFUN,max_valid_value)
      84              :       implicit real(dp) (A-H,O-Z)
      85              :       interface
      86              : #include "num_newuoa_proc.dek"
      87              :       end interface
      88              :       real(dp), intent(in) :: max_valid_value
      89              :       logical :: do_replace
      90              :       dimension X(*),XBASE(*),XOPT(*),XNEW(*),XPT(NPT,*),FVAL(*),
      91              :      &  GQ(*),HQ(*),PQ(*),BMAT(NDIM,*),ZMAT(NPT,*),D(*),VLAG(*),W(*)
      92              : !
      93              : !     The arguments N, NPT, X, RHOBEG, RHOEND, IPRINT and MAXFUN are identical
      94              : !       to the corresponding arguments in subroutine NEWUOA.
      95              : !     XBASE will hold a shift of origin that should reduce the contributions
      96              : !       from rounding errors to values of the model and Lagrange functions.
      97              : !     XOPT will be set to the displacement from XBASE of the vector of
      98              : !       variables that provides the least calculated F so far.
      99              : !     XNEW will be set to the displacement from XBASE of the vector of
     100              : !       variables for the current calculation of F.
     101              : !     XPT will contain the interpolation point coordinates relative to XBASE.
     102              : !     FVAL will hold the values of F at the interpolation points.
     103              : !     GQ will hold the gradient of the quadratic model at XBASE.
     104              : !     HQ will hold the explicit second derivatives of the quadratic model.
     105              : !     PQ will contain the parameters of the implicit second derivatives of
     106              : !       the quadratic model.
     107              : !     BMAT will hold the last N columns of H.
     108              : !     ZMAT will hold the factorization of the leading NPT by NPT submatrix of
     109              : !       H, this factorization being ZMAT times Diag(DZ) times ZMAT^T, where
     110              : !       the elements of DZ are plus or minus one, as specified by IDZ.
     111              : !     NDIM is the first dimension of BMAT and has the value NPT+N.
     112              : !     D is reserved for trial steps from XOPT.
     113              : !     VLAG will contain the values of the Lagrange functions at a new point X.
     114              : !       They are part of a product that requires VLAG to be of length NDIM.
     115              : !     The array W will be used for working space. Its length must be at least
     116              : !       10*NDIM = 10*(NPT+N).
     117              : !
     118              : !     Set some constants.
     119              : !
     120            3 :       HALF=0.5D0
     121            3 :       ONE=1.0D0
     122            3 :       TENTH=0.1D0
     123            3 :       ZERO=0.0D0
     124            3 :       NP=N+1
     125            3 :       NH=(N*NP)/2
     126            3 :       NPTM=NPT-NP
     127            3 :       NFTEST=MAX0(MAXFUN,1)
     128              : !
     129              : !     Set the initial elements of XPT, BMAT, HQ, PQ and ZMAT to zero.
     130              : !
     131           15 :       do J=1,N
     132           12 :         XBASE(J)=X(J)
     133          136 :         do K=1,NPT
     134          136 :             XPT(K,J)=ZERO
     135              :         end do
     136          195 :         do I=1,NDIM
     137          192 :             BMAT(I,J)=ZERO
     138              :         end do
     139              :       end do
     140           37 :       do IH=1,NH
     141           37 :          HQ(IH)=ZERO
     142              :       end do
     143           30 :       do K=1,NPT
     144           27 :         PQ(K)=ZERO
     145          154 :         do J=1,NPTM
     146          151 :             ZMAT(K,J)=ZERO
     147              :         end do
     148              :       end do
     149              : !
     150              : !     Begin the initialization procedure. NF becomes one more than the number
     151              : !     of function values so far. The coordinates of the displacement of the
     152              : !     next initial interpolation point from XBASE are set in XPT(NF,.).
     153              : !
     154            6 :       RHOSQ=RHOBEG*RHOBEG
     155            6 :       RECIP=ONE/RHOSQ
     156            6 :       RECIQ=DSQRT(HALF)/RHOSQ
     157            3 :       NF=0
     158           27 :    50 NFM=NF
     159           27 :       NFMM=NF-N
     160           27 :       NF=NF+1
     161           27 :       if (NFM <= 2*N) then
     162           27 :           if (NFM >= 1 .and. NFM <= N) then
     163           12 :               XPT(NF,NFM)=RHOBEG
     164           15 :           else if (NFM > N) then
     165           12 :               XPT(NF,NFMM)=-RHOBEG
     166              :           end if
     167              :       else
     168            0 :           ITEMP=(NFMM-1)/N
     169            0 :           JPT=NFM-ITEMP*N-N
     170            0 :           IPT=JPT+ITEMP
     171            0 :           if (IPT > N) then
     172            0 :               ITEMP=JPT
     173            0 :               JPT=IPT-N
     174            0 :               IPT=ITEMP
     175              :           end if
     176            3 :           XIPT=RHOBEG
     177            0 :           if (FVAL(IPT+NP) < FVAL(IPT+1)) XIPT=-XIPT
     178            3 :           XJPT=RHOBEG
     179            0 :           if (FVAL(JPT+NP) < FVAL(JPT+1)) XJPT=-XJPT
     180            0 :           XPT(NF,IPT)=XIPT
     181            0 :           XPT(NF,JPT)=XJPT
     182              :       end if
     183              : !
     184              : !     Calculate the next value of F, label 70 being reached immediately
     185              : !     after this calculation. The least function value so far and its index
     186              : !     are required.
     187              : !
     188          151 :       do J=1,N
     189          151 :          X(J)=XPT(NF,J)+XBASE(J)
     190              :       end do
     191           27 :       GOTO 310
     192           30 :    70 FVAL(NF)=F
     193           27 :       if (NF == 1) then
     194            6 :           FBEG=F
     195            6 :           FOPT=F
     196            3 :           KOPT=1
     197           24 :       else if (F < FOPT) then
     198            8 :           FOPT=F
     199            8 :           KOPT=NF
     200              :       end if
     201              : !
     202              : !     Set the nonzero initial elements of BMAT and the quadratic model in
     203              : !     the cases when NF is at most 2*N+1.
     204              : !
     205           27 :       if (NFM <= 2*N) then
     206           27 :           if (NFM >= 1 .and. NFM <= N) then
     207           12 :               GQ(NFM)=(F-FBEG)/RHOBEG
     208           12 :               if (NPT < NF+N) then
     209            0 :                   BMAT(1,NFM)=-ONE/RHOBEG
     210            0 :                   BMAT(NF,NFM)=ONE/RHOBEG
     211            0 :                   BMAT(NPT+NFM,NFM)=-HALF*RHOSQ
     212              :               end if
     213           15 :           else if (NFM > N) then
     214           12 :               BMAT(NF-N,NFMM)=HALF/RHOBEG
     215           12 :               BMAT(NF,NFMM)=-HALF/RHOBEG
     216           12 :               ZMAT(1,NFMM)=-RECIQ-RECIQ
     217           12 :               ZMAT(NF-N,NFMM)=RECIQ
     218           12 :               ZMAT(NF,NFMM)=RECIQ
     219           12 :               IH=(NFMM*(NFMM+1))/2
     220           15 :               TEMP=(FBEG-F)/RHOBEG
     221           12 :               HQ(IH)=(GQ(NFMM)-TEMP)/RHOBEG
     222           12 :               GQ(NFMM)=HALF*(GQ(NFMM)+TEMP)
     223              :           end if
     224              : !
     225              : !     Set the off-diagonal second derivatives of the Lagrange functions and
     226              : !     the initial quadratic model.
     227              : !
     228              :       else
     229            0 :           IH=(IPT*(IPT-1))/2+JPT
     230            0 :           if (XIPT < ZERO) IPT=IPT+N
     231            0 :           if (XJPT < ZERO) JPT=JPT+N
     232            0 :           ZMAT(1,NFMM)=RECIP
     233            0 :           ZMAT(NF,NFMM)=RECIP
     234            0 :           ZMAT(IPT+1,NFMM)=-RECIP
     235            0 :           ZMAT(JPT+1,NFMM)=-RECIP
     236            0 :           HQ(IH)=(FBEG-FVAL(IPT+1)-FVAL(JPT+1)+F)/(XIPT*XJPT)
     237              :       end if
     238           27 :       if (NF < NPT) GOTO 50
     239              : !
     240              : !     Begin the iterative procedure, because the initial model is complete.
     241              : !
     242            6 :       RHO=RHOBEG
     243            6 :       DELTA=RHO
     244            3 :       IDZ=1
     245            6 :       DIFFA=ZERO
     246            6 :       DIFFB=ZERO
     247            3 :       ITEST=0
     248            6 :       XOPTSQ=ZERO
     249           15 :       do I=1,N
     250           12 :          XOPT(I)=XPT(KOPT,I)
     251           15 :          XOPTSQ=XOPTSQ+XOPT(I)**2
     252              :       end do
     253           18 :    90 NFSAV=NF
     254              : !
     255              : !     Generate the next trust region step and test its length. Set KNEW
     256              : !     to -1 if the purpose of the next F will be to improve the model.
     257              : !
     258          252 :   100 KNEW=0
     259          255 :       CALL TRSAPP (N,NPT,XOPT,XPT,GQ,HQ,PQ,DELTA,D,W,W(NP),W(NP+N),W(NP+2*N),CRVMIN)
     260          255 :       DSQ=ZERO
     261         1492 :       do I=1,N
     262         1492 :          DSQ=DSQ+D(I)**2
     263              :       end do
     264          255 :       DNORM=DMIN1(DELTA,DSQRT(DSQ))
     265          252 :       if (DNORM < HALF*RHO) then
     266           91 :           KNEW=-1
     267           91 :           DELTA=TENTH*DELTA
     268           94 :           RATIO=-1.0D0
     269           91 :           if (DELTA <= 1.5D0*RHO) DELTA=RHO
     270           91 :           if (NF <= NFSAV+2) GOTO 460
     271           62 :           TEMP=0.125D0*CRVMIN*RHO*RHO
     272           62 :           if (TEMP <= DMAX1(DIFFA,DIFFB,DIFFC)) GOTO 460
     273              :           GOTO 490
     274              :       end if
     275              : !
     276              : !     Shift XBASE if XOPT may be too far from XBASE. First make the changes
     277              : !     to BMAT that do not depend on ZMAT.
     278              : !
     279          281 :   120 if (DSQ <= 1.0D-3*XOPTSQ) then
     280           12 :           TEMPQ=0.25D0*XOPTSQ
     281           98 :           do K=1,NPT
     282           92 :             SUM=ZERO
     283          529 :             do I=1,N
     284          529 :                SUM=SUM+XPT(K,I)*XOPT(I)
     285              :             end do
     286           89 :             TEMP=PQ(K)*SUM
     287           89 :             SUM=SUM-HALF*XOPTSQ
     288           89 :             W(NPT+K)=SUM
     289          538 :             do I=1,N
     290          440 :                GQ(I)=GQ(I)+TEMP*XPT(K,I)
     291          440 :                XPT(K,I)=XPT(K,I)-HALF*XOPT(I)
     292          440 :                VLAG(I)=BMAT(K,I)
     293          440 :                W(I)=SUM*XPT(K,I)+TEMPQ*XOPT(I)
     294          440 :                IP=NPT+I
     295         1921 :                do J=1,I
     296         1832 :                   BMAT(IP,J)=BMAT(IP,J)+VLAG(I)*W(J)+W(I)*VLAG(J)
     297              :                end do
     298              :             end do
     299              :           end do
     300              : !
     301              : !     Then the revisions of BMAT that depend on ZMAT are calculated.
     302              : !
     303           49 :           do K=1,NPTM
     304            3 :             SUMZ=ZERO
     305          480 :             do I=1,NPT
     306          440 :                 SUMZ=SUMZ+ZMAT(I,K)
     307          480 :                 W(I)=W(NPT+I)*ZMAT(I,K)
     308              :             end do
     309          240 :             do J=1,N
     310          200 :                 SUM=TEMPQ*SUMZ*XOPT(J)
     311         2544 :                 do I=1,NPT
     312         2544 :                 SUM=SUM+W(I)*XPT(I,J)
     313              :                 end do
     314          200 :                 VLAG(J)=SUM
     315          200 :                 if (K < IDZ) SUM=-SUM
     316         2584 :                 do I=1,NPT
     317         2544 :                    BMAT(I,J)=BMAT(I,J)+SUM*ZMAT(I,K)
     318              :                 end do
     319              :             end do
     320          249 :             do I=1,N
     321          200 :                 IP=I+NPT
     322          200 :                 TEMP=VLAG(I)
     323          200 :                 if (K < IDZ) TEMP=-TEMP
     324          876 :                 do J=1,I
     325          836 :                     BMAT(IP,J)=BMAT(IP,J)+TEMP*VLAG(J)
     326              :                 end do
     327              :             end do
     328              :           end do
     329              : !
     330              : !     The following instructions complete the shift of XBASE, including
     331              : !     the changes to the parameters of the quadratic model.
     332              : !
     333            9 :           IH=0
     334           49 :           do J=1,N
     335           40 :             W(J)=ZERO
     336          480 :             do K=1,NPT
     337          440 :                 W(J)=W(J)+PQ(K)*XPT(K,J)
     338          480 :                 XPT(K,J)=XPT(K,J)-HALF*XOPT(J)
     339              :             end do
     340          169 :             do I=1,J
     341          120 :                 IH=IH+1
     342          120 :                 if (I < J) GQ(J)=GQ(J)+HQ(IH)*XOPT(I)
     343          120 :                 GQ(I)=GQ(I)+HQ(IH)*XOPT(J)
     344          120 :                 HQ(IH)=HQ(IH)+W(I)*XOPT(J)+XOPT(I)*W(J)
     345          160 :                 BMAT(NPT+I,J)=BMAT(NPT+J,I)
     346              :             end do
     347              :           end do
     348           49 :           do J=1,N
     349           40 :              XBASE(J)=XBASE(J)+XOPT(J)
     350           49 :              XOPT(J)=ZERO
     351              :           end do
     352              :           XOPTSQ=ZERO
     353              :       end if
     354              : !
     355              : !     Pick the model step if KNEW is positive. A different choice of D
     356              : !     may be made later, if the choice of D by BIGLAG causes substantial
     357              : !     cancellation in DENOM.
     358              : !
     359          281 :       if (KNEW > 0) then
     360          120 :           CALL BIGLAG (N,NPT,XOPT,XPT,BMAT,ZMAT,IDZ,NDIM,KNEW,DSTEP,D,ALPHA,VLAG,VLAG(NPT+1),W,W(NP),W(NP+N))
     361              :       end if
     362              : !
     363              : !     Calculate VLAG and BETA for the current choice of D. The first NPT
     364              : !     components of W_check will be held in W.
     365              : !
     366         3410 :       do K=1,NPT
     367         3132 :         SUMA=ZERO
     368         3132 :         SUMB=ZERO
     369         3129 :         SUM=ZERO
     370        19945 :         do J=1,N
     371        16816 :             SUMA=SUMA+XPT(K,J)*D(J)
     372        16816 :             SUMB=SUMB+XPT(K,J)*XOPT(J)
     373        19945 :             SUM=SUM+BMAT(K,J)*D(J)
     374              :         end do
     375         3129 :         W(K)=SUMA*(HALF*SUMA+SUMB)
     376         3410 :         VLAG(K)=SUM
     377              :       end do
     378          284 :       BETA=ZERO
     379         1705 :       do K=1,NPTM
     380              :         SUM=ZERO
     381        18240 :         do I=1,NPT
     382        18240 :            SUM=SUM+ZMAT(I,K)*W(I)
     383              :         end do
     384         1424 :         if (K < IDZ) then
     385            0 :             BETA=BETA+SUM*SUM
     386            0 :             SUM=-SUM
     387              :         else
     388         1424 :             BETA=BETA-SUM*SUM
     389              :         end if
     390        18521 :         do I=1,NPT
     391        18240 :             VLAG(I)=VLAG(I)+SUM*ZMAT(I,K)
     392              :         end do
     393              :       end do
     394          284 :       BSUM=ZERO
     395          284 :       DX=ZERO
     396         1705 :       do J=1,N
     397              :         SUM=ZERO
     398        18240 :         do I=1,NPT
     399        18240 :             SUM=SUM+W(I)*BMAT(I,J)
     400              :         end do
     401         1424 :         BSUM=BSUM+SUM*D(J)
     402         1424 :         JP=NPT+J
     403         9120 :         do K=1,N
     404         9120 :             SUM=SUM+BMAT(JP,K)*D(K)
     405              :         end do
     406         1424 :         VLAG(JP)=SUM
     407         1424 :         BSUM=BSUM+SUM*D(J)
     408         1705 :         DX=DX+D(J)*XOPT(J)
     409              :       end do
     410          281 :       BETA=DX*DX+DSQ*(XOPTSQ+DX+DX+HALF*DSQ)+BETA-BSUM
     411          281 :       VLAG(KOPT)=VLAG(KOPT)+ONE
     412              : !
     413              : !     If KNEW is positive and if the cancellation in DENOM is unacceptable,
     414              : !     then BIGDEN calculates an alternative model step, XNEW being used for
     415              : !     working space.
     416              : !
     417          281 :       if (KNEW > 0) then
     418          120 :           TEMP=ONE+ALPHA*BETA/VLAG(KNEW)**2
     419          120 :           if (DABS(TEMP) <= 0.8D0) then
     420              :               CALL BIGDEN (N,NPT,XOPT,XPT,BMAT,ZMAT,IDZ,NDIM,KOPT,
     421            0 :      &          KNEW,D,W,VLAG,BETA,XNEW,W(NDIM+1),W(6*NDIM+1))
     422              :           end if
     423              :       end if
     424              : !
     425              : !     Calculate the next value of the objective function.
     426              : !
     427         1713 :   290 do I=1,N
     428         1430 :          XNEW(I)=XOPT(I)+D(I)
     429         1713 :          X(I)=XBASE(I)+XNEW(I)
     430              :       end do
     431          283 :       NF=NF+1
     432          310 :   310 if (NF > NFTEST) then
     433            0 :           NF=NF-1
     434            0 :           if (IPRINT > 0) PRINT 320
     435              :   320     FORMAT (/4X,'Return from NEWUOA because CALFUN has been called MAXFUN times.')
     436              :           GOTO 530
     437              :       end if
     438          310 :       CALL CALFUN (N,X,F)
     439          310 :       if (IPRINT == 3) then
     440            0 :          PRINT 330, NF,F,(X(I),I=1,N)
     441              :   330    FORMAT (/4X,'Function number',I6,'    F =',1PD18.10,'    The corresponding X is:'/(2X,5D15.6))
     442              :       end if
     443          310 :       if (NF <= NPT) GOTO 70
     444          283 :       if (KNEW == -1) GOTO 530
     445              : !
     446              : !     Use the quadratic model to predict the change in F due to the step D,
     447              : !     and set DIFF to the error of this prediction.
     448              : !
     449          284 :       VQUAD=ZERO
     450          281 :       IH=0
     451         1705 :       do J=1,N
     452         1424 :         VQUAD=VQUAD+D(J)*GQ(J)
     453         6265 :         do I=1,J
     454         4560 :            IH=IH+1
     455         4560 :            TEMP=D(I)*XNEW(J)+D(J)*XOPT(I)
     456         4560 :            if (I == J) TEMP=HALF*TEMP
     457         5984 :            VQUAD=VQUAD+TEMP*HQ(IH)
     458              :         end do
     459              :       end do
     460         3410 :       do K=1,NPT
     461         3410 :          VQUAD=VQUAD+PQ(K)*W(K)
     462              :       end do
     463          284 :       DIFF=F-FOPT-VQUAD
     464          281 :       DIFFC=DIFFB
     465          281 :       DIFFB=DIFFA
     466          281 :       DIFFA=DABS(DIFF)
     467          281 :       if (DNORM > RHO) NFSAV=NF
     468              : !
     469              : !     Update FOPT and XOPT if the new F is the least value of the objective
     470              : !     function so far. The branch when KNEW is positive occurs if D is not
     471              : !     a trust region step.
     472              : !
     473          284 :       FSAVE=FOPT
     474          281 :       if (F < FOPT) then
     475          131 :          FOPT=F
     476          131 :          XOPTSQ=ZERO
     477          803 :          do I=1,N
     478          672 :             XOPT(I)=XNEW(I)
     479          803 :             XOPTSQ=XOPTSQ+XOPT(I)**2
     480              :          end do
     481              :       end if
     482          281 :       KSAVE=KNEW
     483          281 :       if (KNEW > 0) GOTO 410
     484              : !
     485              : !     Pick the next value of DELTA after a trust region step.
     486              : !
     487          161 :       if (VQUAD >= ZERO) then
     488            0 :           if (IPRINT > 0) PRINT 370
     489              :   370     FORMAT (/4X,'Return from NEWUOA because a trust region step has failed to reduce Q.')
     490              :           GOTO 530
     491              :       end if
     492          161 :       RATIO=(F-FSAVE)/VQUAD
     493          161 :       if (RATIO <= TENTH) then
     494           49 :           DELTA=HALF*DNORM
     495          112 :       else if (RATIO. LE. 0.7D0) then
     496           40 :           DELTA=DMAX1(HALF*DELTA,DNORM)
     497              :       else
     498           72 :           DELTA=DMAX1(HALF*DELTA,DNORM+DNORM)
     499              :       end if
     500          161 :       if (DELTA <= 1.5D0*RHO) DELTA=RHO
     501              : !
     502              : !     Set KNEW to the index of the next interpolation point to be deleted.
     503              : !
     504          161 :       RHOSQ=DMAX1(TENTH*DELTA,RHO)**2
     505          161 :       KTEMP=0
     506          164 :       DETRAT=ZERO
     507          161 :       if (F >= FSAVE) then
     508           47 :           KTEMP=KOPT
     509           47 :           DETRAT=ONE
     510              :       end if
     511         1986 :       do K=1,NPT
     512            3 :         HDIAG=ZERO
     513        11761 :         do J=1,NPTM
     514         9936 :             TEMP=ONE
     515         9936 :             if (J < IDZ) TEMP=-ONE
     516        11761 :             HDIAG=HDIAG+TEMP*ZMAT(K,J)**2
     517              :         end do
     518         1825 :         TEMP=DABS(BETA*HDIAG+VLAG(K)**2)
     519         1828 :         DISTSQ=ZERO
     520        11761 :         do J=1,N
     521        11761 :             DISTSQ=DISTSQ+(XPT(K,J)-XOPT(J))**2
     522              :         end do
     523         1825 :         if (DISTSQ > RHOSQ) TEMP=TEMP*(DISTSQ/RHOSQ)*(DISTSQ/RHOSQ)*(DISTSQ/RHOSQ)
     524         1986 :         if (TEMP > DETRAT .and. K /= KTEMP) then
     525          478 :             DETRAT=TEMP
     526          478 :             KNEW=K
     527              :         end if
     528              :       end do
     529          161 :       if (KNEW == 0) GOTO 460
     530              : !
     531              : !     Update BMAT, ZMAT and IDZ, so that the KNEW-th interpolation point
     532              : !     can be moved. Begin the updating of the quadratic model, starting
     533              : !     with the explicit second derivative term.
     534              : !
     535          281 :   410 CALL UPDATE (N,NPT,BMAT,ZMAT,IDZ,NDIM,VLAG,BETA,KNEW,W)
     536          281 :       FVAL(KNEW)=F
     537          281 :       IH=0
     538         1705 :       do I=1,N
     539         1424 :         TEMP=PQ(KNEW)*XPT(KNEW,I)
     540         6265 :         do J=1,I
     541         4560 :             IH=IH+1
     542         5984 :             HQ(IH)=HQ(IH)+TEMP*XPT(KNEW,J)
     543              :         end do
     544              :       end do
     545          281 :       PQ(KNEW)=ZERO
     546              : !
     547              : !     Update the other second derivative parameters, and then the gradient
     548              : !     vector of the model. Also include the new interpolation point.
     549              : !
     550         1705 :       do J=1,NPTM
     551         1424 :         TEMP=DIFF*ZMAT(KNEW,J)
     552         1424 :         if (J < IDZ) TEMP=-TEMP
     553        18521 :         do K=1,NPT
     554        18240 :             PQ(K)=PQ(K)+TEMP*ZMAT(K,J)
     555              :         end do
     556              :       end do
     557            3 :       GQSQ=ZERO
     558         1705 :       do I=1,N
     559         1424 :         GQ(I)=GQ(I)+DIFF*BMAT(KNEW,I)
     560         1424 :         GQSQ=GQSQ+GQ(I)**2
     561         1705 :         XPT(KNEW,I)=XNEW(I)
     562              :       end do
     563              : !
     564              : !     If a trust region step makes a small change to the objective function,
     565              : !     then calculate the gradient of the least Frobenius norm interpolant at
     566              : !     XBASE, and store it in W, using VLAG for a vector of right hand sides.
     567              : !
     568          281 :       if (KSAVE == 0 .and. DELTA == RHO) then
     569           64 :           if (DABS(RATIO) > 1.0D-2) then
     570              :               ITEST=0
     571              :           else
     572            0 :               do K=1,NPT
     573            0 :                  VLAG(K)=FVAL(K)-FVAL(KOPT)
     574              :               end do
     575            3 :               GISQ=ZERO
     576            0 :               do I=1,N
     577              :                 SUM=ZERO
     578            0 :                 do K=1,NPT
     579            0 :                    SUM=SUM+BMAT(K,I)*VLAG(K)
     580              :                 end do
     581            0 :                 GISQ=GISQ+SUM*SUM
     582            0 :                 W(I)=SUM
     583              :               end do
     584              : !
     585              : !     Test whether to replace the new quadratic model by the least Frobenius
     586              : !     norm interpolant, making the replacement if the test is satisfied.
     587              : !
     588            0 :               ITEST=ITEST+1
     589            0 :               if (GQSQ < 1.0D2*GISQ) ITEST=0
     590            0 :               do_replace = (ITEST >= 3)
     591            0 :               if (.not. do_replace) then ! check for "invalid" value
     592            0 :                 do k=1,npt
     593            0 :                   if (fval(k) > max_valid_value) then
     594              :                      do_replace = .true.
     595              :                      !write(*,*) 'newuoa value > max valid', fval(k), max_valid_value
     596              :                      exit
     597              :                   end if
     598              :                 end do
     599              :               end if
     600            0 :               if (do_replace) then
     601            0 :                   do I=1,N
     602            0 :                      GQ(I)=W(I)
     603              :                   end do
     604            0 :                   do IH=1,NH
     605            0 :                      HQ(IH)=ZERO
     606              :                   end do
     607            0 :                   do J=1,NPTM
     608            0 :                     W(J)=ZERO
     609            0 :                     do K=1,NPT
     610            0 :                         W(J)=W(J)+VLAG(K)*ZMAT(K,J)
     611              :                     end do
     612            0 :                   if (J < IDZ) W(J)=-W(J)
     613              :                   end do
     614            0 :                   do K=1,NPT
     615            0 :                     PQ(K)=ZERO
     616            0 :                     do J=1,NPTM
     617            0 :                         PQ(K)=PQ(K)+ZMAT(K,J)*W(J)
     618              :                     end do
     619              :                   end do
     620              :                   ITEST=0
     621              :               end if
     622              :           end if
     623              :       end if
     624          281 :       if (F < FSAVE) KOPT=KNEW
     625              : !
     626              : !     If a trust region step has provided a sufficient decrease in F, then
     627              : !     branch for another trust region calculation. The case KSAVE>0 occurs
     628              : !     when the new function value was calculated by a model step.
     629              : !
     630          281 :       if (F <= FSAVE+TENTH*VQUAD) GOTO 100
     631          151 :       if (KSAVE > 0) GOTO 100
     632              : !
     633              : !     Alternatively, find out if the interpolation points are close enough
     634              : !     to the best point so far.
     635              : !
     636          135 :       KNEW=0
     637          135 :   460 DISTSQ=4.0D0*DELTA*DELTA
     638         1586 :       do K=1,NPT
     639         1451 :         SUM=ZERO
     640         9045 :         do J=1,N
     641         9045 :            SUM=SUM+(XPT(K,J)-XOPT(J))**2
     642              :         end do
     643         1586 :         if (SUM > DISTSQ) then
     644          268 :            KNEW=K
     645          268 :            DISTSQ=SUM
     646              :         end if
     647              :       end do
     648              : !
     649              : !     If KNEW is positive, then set DSTEP, and branch back for the next
     650              : !     iteration, which will generate a "model step".
     651              : !
     652          135 :       if (KNEW > 0) then
     653          120 :           DSTEP=DMAX1(DMIN1(TENTH*DSQRT(DISTSQ),HALF*DELTA),RHO)
     654          120 :           DSQ=DSTEP*DSTEP
     655          120 :           GOTO 120
     656              :       end if
     657           15 :       if (RATIO > ZERO) GOTO 100
     658           14 :       if (DMAX1(DELTA,DNORM) > RHO) GOTO 100
     659              : !
     660              : !     The calculations with the current value of RHO are complete. Pick the
     661              : !     next values of RHO and DELTA.
     662              : !
     663           18 :   490 if (RHO > RHOEND) then
     664           15 :           DELTA=HALF*RHO
     665           15 :           RATIO=RHO/RHOEND
     666           15 :           if (RATIO <= 16.0D0) then
     667            3 :               RHO=RHOEND
     668           12 :           else if (RATIO <= 250.0D0) then
     669            3 :               RHO=DSQRT(RATIO)*RHOEND
     670              :           else
     671            9 :               RHO=TENTH*RHO
     672              :           end if
     673           15 :           DELTA=DMAX1(DELTA,RHO)
     674           15 :           if (IPRINT >= 2) then
     675            0 :               if (IPRINT >= 3) PRINT 500
     676              :   500         FORMAT (5X)
     677            0 :               PRINT 510, RHO,NF
     678              :   510         FORMAT (/4X,'New RHO =',1PD11.4,5X,'Number of function values =',I6)
     679            0 :               PRINT 520, FOPT,(XBASE(I)+XOPT(I),I=1,N)
     680              :   520         FORMAT (4X,'Least value of F =',1PD23.15,9X,'The corresponding X is:'/(2X,5D15.6))
     681              :           end if
     682              :           GOTO 90
     683              :       end if
     684              : !
     685              : !     Return from the calculation, after another Newton-Raphson step, if
     686              : !     it is too short to have been tried before.
     687              : !
     688            3 :       if (KNEW == -1) GOTO 290
     689            3 :   530 if (FOPT <= F) then
     690            7 :           do I=1,N
     691            7 :             X(I)=XBASE(I)+XOPT(I)
     692              :           end do
     693            1 :           F=FOPT
     694              :       end if
     695            3 :       if (IPRINT >= 1) then
     696            0 :           PRINT 550, NF
     697              :   550     FORMAT (/4X,'At the return from NEWUOA',5X,'Number of function values =',I6)
     698            0 :           PRINT 520, F,(X(I),I=1,N)
     699              :       end if
     700            3 :       RETURN
     701              :       end subroutine NEWUOB
     702              : 
     703            0 :       subroutine BIGDEN(N,NPT,XOPT,XPT,BMAT,ZMAT,IDZ,NDIM,KOPT,KNEW,D,W,VLAG,BETA,S,WVEC,PROD)
     704              :       implicit real(dp) (A-H,O-Z)
     705              :       dimension XOPT(*),XPT(NPT,*),BMAT(NDIM,*),ZMAT(NPT,*),D(*),
     706              :      &  W(*),VLAG(*),S(*),WVEC(NDIM,*),PROD(NDIM,*)
     707            0 :       dimension DEN(9),DENEX(9),PAR(9)
     708              : !
     709              : !     N is the number of variables.
     710              : !     NPT is the number of interpolation equations.
     711              : !     XOPT is the best interpolation point so far.
     712              : !     XPT contains the coordinates of the current interpolation points.
     713              : !     BMAT provides the last N columns of H.
     714              : !     ZMAT and IDZ give a factorization of the first NPT by NPT submatrix of H.
     715              : !     NDIM is the first dimension of BMAT and has the value NPT+N.
     716              : !     KOPT is the index of the optimal interpolation point.
     717              : !     KNEW is the index of the interpolation point that is going to be moved.
     718              : !     D will be set to the step from XOPT to the new point, and on entry it
     719              : !       should be the D that was calculated by the last call of BIGLAG. The
     720              : !       length of the initial D provides a trust region bound on the final D.
     721              : !     W will be set to Wcheck for the final choice of D.
     722              : !     VLAG will be set to Theta*Wcheck+e_b for the final choice of D.
     723              : !     BETA will be set to the value that will occur in the updating formula
     724              : !       when the KNEW-th interpolation point is moved to its new position.
     725              : !     S, WVEC, PROD and the private arrays DEN, DENEX and PAR will be used
     726              : !       for working space.
     727              : !
     728              : !     D is calculated in a way that should provide a denominator with a large
     729              : !     modulus in the updating formula when the KNEW-th interpolation point is
     730              : !     shifted to the new position XOPT+D.
     731              : !
     732              : !     Set some constants.
     733              : !
     734            0 :       HALF=0.5D0
     735            0 :       ONE=1.0D0
     736            0 :       QUART=0.25D0
     737            0 :       TWO=2.0D0
     738            0 :       ZERO=0.0D0
     739            0 :       TWOPI=8.0D0*atan(ONE)
     740            0 :       NPTM=NPT-N-1
     741              : !
     742              : !     Store the first NPT elements of the KNEW-th column of H in W(N+1)
     743              : !     to W(N+NPT).
     744              : !
     745            0 :       do K=1,NPT
     746            0 :          W(N+K)=ZERO
     747              :       end do
     748            0 :       do J=1,NPTM
     749            0 :         TEMP=ZMAT(KNEW,J)
     750            0 :         if (J < IDZ) TEMP=-TEMP
     751            0 :         do K=1,NPT
     752            0 :             W(N+K)=W(N+K)+TEMP*ZMAT(K,J)
     753              :         end do
     754              :       end do
     755            0 :       ALPHA=W(N+KNEW)
     756              : !
     757              : !     The initial search direction D is taken from the last call of BIGLAG,
     758              : !     and the initial S is set below, usually to the direction from X_OPT
     759              : !     to X_KNEW, but a different direction to an interpolation point may
     760              : !     be chosen, in order to prevent S from being nearly parallel to D.
     761              : !
     762            0 :       DD=ZERO
     763            0 :       DS=ZERO
     764            0 :       SS=ZERO
     765            0 :       XOPTSQ=ZERO
     766            0 :       do I=1,N
     767            0 :         DD=DD+D(I)**2
     768            0 :         S(I)=XPT(KNEW,I)-XOPT(I)
     769            0 :         DS=DS+D(I)*S(I)
     770            0 :         SS=SS+S(I)**2
     771            0 :         XOPTSQ=XOPTSQ+XOPT(I)**2
     772              :       end do
     773            0 :       if (DS*DS > 0.99D0*DD*SS) then
     774            0 :           KSAV=KNEW
     775            0 :           DTEST=DS*DS/SS
     776            0 :           do K=1,NPT
     777            0 :             if (K /= KOPT) then
     778            0 :                 DSTEMP=ZERO
     779            0 :                 SSTEMP=ZERO
     780            0 :                 do I=1,N
     781            0 :                     DIFF=XPT(K,I)-XOPT(I)
     782            0 :                     DSTEMP=DSTEMP+D(I)*DIFF
     783            0 :                     SSTEMP=SSTEMP+DIFF*DIFF
     784              :                 end do
     785            0 :                 if (DSTEMP*DSTEMP/SSTEMP < DTEST) then
     786            0 :                     KSAV=K
     787            0 :                     DTEST=DSTEMP*DSTEMP/SSTEMP
     788            0 :                     DS=DSTEMP
     789            0 :                     SS=SSTEMP
     790              :                 end if
     791              :             end if
     792              :           end do
     793            0 :           do I=1,N
     794            0 :              S(I)=XPT(KSAV,I)-XOPT(I)
     795              :           end do
     796              :       end if
     797            0 :       SSDEN=DD*SS-DS*DS
     798            0 :       ITERC=0
     799            0 :       DENSAV=ZERO
     800              : !
     801              : !     Begin the iteration by overwriting S with a vector that has the
     802              : !     required length and direction.
     803              : !
     804            0 :    70 ITERC=ITERC+1
     805            0 :       TEMP=ONE/DSQRT(SSDEN)
     806            0 :       XOPTD=ZERO
     807            0 :       XOPTS=ZERO
     808            0 :       do I=1,N
     809            0 :         S(I)=TEMP*(DD*S(I)-DS*D(I))
     810            0 :         XOPTD=XOPTD+XOPT(I)*D(I)
     811            0 :         XOPTS=XOPTS+XOPT(I)*S(I)
     812              :       end do
     813              : !
     814              : !     Set the coefficients of the first two terms of BETA.
     815              : !
     816            0 :       TEMPA=HALF*XOPTD*XOPTD
     817            0 :       TEMPB=HALF*XOPTS*XOPTS
     818            0 :       DEN(1)=DD*(XOPTSQ+HALF*DD)+TEMPA+TEMPB
     819            0 :       DEN(2)=TWO*XOPTD*DD
     820            0 :       DEN(3)=TWO*XOPTS*DD
     821            0 :       DEN(4)=TEMPA-TEMPB
     822            0 :       DEN(5)=XOPTD*XOPTS
     823            0 :       do I=6,9
     824            0 :          DEN(I)=ZERO
     825              :       end do
     826              : !
     827              : !     Put the coefficients of Wcheck in WVEC.
     828              : !
     829            0 :       do K=1,NPT
     830              :         TEMPA=ZERO
     831              :         TEMPB=ZERO
     832            0 :         TEMPC=ZERO
     833            0 :         do I=1,N
     834            0 :             TEMPA=TEMPA+XPT(K,I)*D(I)
     835            0 :             TEMPB=TEMPB+XPT(K,I)*S(I)
     836            0 :             TEMPC=TEMPC+XPT(K,I)*XOPT(I)
     837              :         end do
     838            0 :         WVEC(K,1)=QUART*(TEMPA*TEMPA+TEMPB*TEMPB)
     839            0 :         WVEC(K,2)=TEMPA*TEMPC
     840            0 :         WVEC(K,3)=TEMPB*TEMPC
     841            0 :         WVEC(K,4)=QUART*(TEMPA*TEMPA-TEMPB*TEMPB)
     842            0 :         WVEC(K,5)=HALF*TEMPA*TEMPB
     843              :       end do
     844            0 :       do I=1,N
     845            0 :         IP=I+NPT
     846            0 :         WVEC(IP,1)=ZERO
     847            0 :         WVEC(IP,2)=D(I)
     848            0 :         WVEC(IP,3)=S(I)
     849            0 :         WVEC(IP,4)=ZERO
     850            0 :         WVEC(IP,5)=ZERO
     851              :       end do
     852              : !
     853              : !     Put the coefficients of THETA*Wcheck in PROD.
     854              : !
     855            0 :       do JC=1,5
     856            0 :         NW=NPT
     857            0 :         if (JC == 2 .or. JC == 3) NW=NDIM
     858            0 :         do K=1,NPT
     859            0 :             PROD(K,JC)=ZERO
     860              :         end do
     861            0 :         do J=1,NPTM
     862            0 :             SUM=ZERO
     863            0 :             do K=1,NPT
     864            0 :                 SUM=SUM+ZMAT(K,J)*WVEC(K,JC)
     865              :             end do
     866            0 :             if (J < IDZ) SUM=-SUM
     867            0 :             do K=1,NPT
     868            0 :             PROD(K,JC)=PROD(K,JC)+SUM*ZMAT(K,J)
     869              :             end do
     870              :         end do
     871            0 :         if (NW == NDIM) then
     872            0 :             do K=1,NPT
     873              :             SUM=ZERO
     874            0 :             do J=1,N
     875            0 :                 SUM=SUM+BMAT(K,J)*WVEC(NPT+J,JC)
     876              :             end do
     877            0 :             PROD(K,JC)=PROD(K,JC)+SUM
     878              :             end do
     879              :         end if
     880            0 :         do J=1,N
     881              :             SUM=ZERO
     882            0 :             do I=1,NW
     883            0 :                 SUM=SUM+BMAT(I,J)*WVEC(I,JC)
     884              :             end do
     885            0 :             PROD(NPT+J,JC)=SUM
     886              :         end do
     887              :       end do
     888              : !
     889              : !     Include in DEN the part of BETA that depends on THETA.
     890              : !
     891            0 :       do K=1,NDIM
     892              :         SUM=ZERO
     893            0 :         do I=1,5
     894            0 :             PAR(I)=HALF*PROD(K,I)*WVEC(K,I)
     895            0 :             SUM=SUM+PAR(I)
     896              :         end do
     897            0 :         DEN(1)=DEN(1)-PAR(1)-SUM
     898            0 :         TEMPA=PROD(K,1)*WVEC(K,2)+PROD(K,2)*WVEC(K,1)
     899            0 :         TEMPB=PROD(K,2)*WVEC(K,4)+PROD(K,4)*WVEC(K,2)
     900            0 :         TEMPC=PROD(K,3)*WVEC(K,5)+PROD(K,5)*WVEC(K,3)
     901            0 :         DEN(2)=DEN(2)-TEMPA-HALF*(TEMPB+TEMPC)
     902            0 :         DEN(6)=DEN(6)-HALF*(TEMPB-TEMPC)
     903            0 :         TEMPA=PROD(K,1)*WVEC(K,3)+PROD(K,3)*WVEC(K,1)
     904            0 :         TEMPB=PROD(K,2)*WVEC(K,5)+PROD(K,5)*WVEC(K,2)
     905            0 :         TEMPC=PROD(K,3)*WVEC(K,4)+PROD(K,4)*WVEC(K,3)
     906            0 :         DEN(3)=DEN(3)-TEMPA-HALF*(TEMPB-TEMPC)
     907            0 :         DEN(7)=DEN(7)-HALF*(TEMPB+TEMPC)
     908            0 :         TEMPA=PROD(K,1)*WVEC(K,4)+PROD(K,4)*WVEC(K,1)
     909            0 :         DEN(4)=DEN(4)-TEMPA-PAR(2)+PAR(3)
     910            0 :         TEMPA=PROD(K,1)*WVEC(K,5)+PROD(K,5)*WVEC(K,1)
     911            0 :         TEMPB=PROD(K,2)*WVEC(K,3)+PROD(K,3)*WVEC(K,2)
     912            0 :         DEN(5)=DEN(5)-TEMPA-HALF*TEMPB
     913            0 :         DEN(8)=DEN(8)-PAR(4)+PAR(5)
     914            0 :         TEMPA=PROD(K,4)*WVEC(K,5)+PROD(K,5)*WVEC(K,4)
     915            0 :         DEN(9)=DEN(9)-HALF*TEMPA
     916              :       end do
     917              : !
     918              : !     Extend DEN so that it holds all the coefficients of DENOM.
     919              : !
     920              :       SUM=ZERO
     921            0 :       do I=1,5
     922            0 :          PAR(I)=HALF*PROD(KNEW,I)**2
     923            0 :          SUM=SUM+PAR(I)
     924              :       end do
     925            0 :       DENEX(1)=ALPHA*DEN(1)+PAR(1)+SUM
     926            0 :       TEMPA=TWO*PROD(KNEW,1)*PROD(KNEW,2)
     927            0 :       TEMPB=PROD(KNEW,2)*PROD(KNEW,4)
     928            0 :       TEMPC=PROD(KNEW,3)*PROD(KNEW,5)
     929            0 :       DENEX(2)=ALPHA*DEN(2)+TEMPA+TEMPB+TEMPC
     930            0 :       DENEX(6)=ALPHA*DEN(6)+TEMPB-TEMPC
     931            0 :       TEMPA=TWO*PROD(KNEW,1)*PROD(KNEW,3)
     932            0 :       TEMPB=PROD(KNEW,2)*PROD(KNEW,5)
     933            0 :       TEMPC=PROD(KNEW,3)*PROD(KNEW,4)
     934            0 :       DENEX(3)=ALPHA*DEN(3)+TEMPA+TEMPB-TEMPC
     935            0 :       DENEX(7)=ALPHA*DEN(7)+TEMPB+TEMPC
     936            0 :       TEMPA=TWO*PROD(KNEW,1)*PROD(KNEW,4)
     937            0 :       DENEX(4)=ALPHA*DEN(4)+TEMPA+PAR(2)-PAR(3)
     938            0 :       TEMPA=TWO*PROD(KNEW,1)*PROD(KNEW,5)
     939            0 :       DENEX(5)=ALPHA*DEN(5)+TEMPA+PROD(KNEW,2)*PROD(KNEW,3)
     940            0 :       DENEX(8)=ALPHA*DEN(8)+PAR(4)-PAR(5)
     941            0 :       DENEX(9)=ALPHA*DEN(9)+PROD(KNEW,4)*PROD(KNEW,5)
     942              : !
     943              : !     Seek the value of the angle that maximizes the modulus of DENOM.
     944              : !
     945            0 :       SUM=DENEX(1)+DENEX(2)+DENEX(4)+DENEX(6)+DENEX(8)
     946            0 :       DENOLD=SUM
     947            0 :       DENMAX=SUM
     948            0 :       ISAVE=0
     949            0 :       IU=49
     950            0 :       TEMP=TWOPI/DBLE(IU+1)
     951            0 :       PAR(1)=ONE
     952            0 :       do I=1,IU
     953            0 :         ANGLE=DBLE(I)*TEMP
     954            0 :         PAR(2)=cos(ANGLE)
     955            0 :         PAR(3)=sin(ANGLE)
     956            0 :         do J=4,8,2
     957            0 :             PAR(J)=PAR(2)*PAR(J-2)-PAR(3)*PAR(J-1)
     958            0 :             PAR(J+1)=PAR(2)*PAR(J-1)+PAR(3)*PAR(J-2)
     959              :         end do
     960            0 :         SUMOLD=SUM
     961              :         SUM=ZERO
     962            0 :         do J=1,9
     963            0 :            SUM=SUM+DENEX(J)*PAR(J)
     964              :         end do
     965            0 :         if (DABS(SUM) > DABS(DENMAX)) then
     966              :             DENMAX=SUM
     967              :             ISAVE=I
     968              :             TEMPA=SUMOLD
     969            0 :         else if (I == ISAVE+1) then
     970            0 :             TEMPB=SUM
     971              :         end if
     972              :       end do
     973            0 :       if (ISAVE == 0) TEMPA=SUM
     974            0 :       if (ISAVE == IU) TEMPB=DENOLD
     975            0 :       STEP=ZERO
     976            0 :       if (TEMPA /= TEMPB) then
     977            0 :           TEMPA=TEMPA-DENMAX
     978            0 :           TEMPB=TEMPB-DENMAX
     979            0 :           STEP=HALF*(TEMPA-TEMPB)/(TEMPA+TEMPB)
     980              :       end if
     981            0 :       ANGLE=TEMP*(DBLE(ISAVE)+STEP)
     982              : !
     983              : !     Calculate the new parameters of the denominator, the new VLAG vector
     984              : !     and the new D. Then test for convergence.
     985              : !
     986            0 :       PAR(2)=cos(ANGLE)
     987            0 :       PAR(3)=sin(ANGLE)
     988            0 :       do J=4,8,2
     989            0 :         PAR(J)=PAR(2)*PAR(J-2)-PAR(3)*PAR(J-1)
     990            0 :         PAR(J+1)=PAR(2)*PAR(J-1)+PAR(3)*PAR(J-2)
     991              :       end do
     992            0 :       BETA=ZERO
     993            0 :       DENMAX=ZERO
     994            0 :       do J=1,9
     995            0 :         BETA=BETA+DEN(J)*PAR(J)
     996            0 :         DENMAX=DENMAX+DENEX(J)*PAR(J)
     997              :       end do
     998            0 :       do K=1,NDIM
     999            0 :         VLAG(K)=ZERO
    1000            0 :         do J=1,5
    1001            0 :             VLAG(K)=VLAG(K)+PROD(K,J)*PAR(J)
    1002              :         end do
    1003              :       end do
    1004            0 :       TAU=VLAG(KNEW)
    1005            0 :       DD=ZERO
    1006            0 :       TEMPA=ZERO
    1007            0 :       TEMPB=ZERO
    1008            0 :       do I=1,N
    1009            0 :         D(I)=PAR(2)*D(I)+PAR(3)*S(I)
    1010            0 :         W(I)=XOPT(I)+D(I)
    1011            0 :         DD=DD+D(I)**2
    1012            0 :         TEMPA=TEMPA+D(I)*W(I)
    1013            0 :         TEMPB=TEMPB+W(I)*W(I)
    1014              :       end do
    1015            0 :       if (ITERC >= N) GOTO 340
    1016            0 :       if (ITERC > 1) DENSAV=DMAX1(DENSAV,DENOLD)
    1017            0 :       if (DABS(DENMAX) <= 1.1D0*DABS(DENSAV)) GOTO 340
    1018            0 :       DENSAV=DENMAX
    1019              : !
    1020              : !     Set S to half the gradient of the denominator with respect to D.
    1021              : !     Then branch for the next iteration.
    1022              : !
    1023            0 :       do I=1,N
    1024            0 :         TEMP=TEMPA*XOPT(I)+TEMPB*D(I)-VLAG(NPT+I)
    1025            0 :         S(I)=TAU*BMAT(KNEW,I)+ALPHA*TEMP
    1026              :       end do
    1027            0 :       do K=1,NPT
    1028              :         SUM=ZERO
    1029            0 :         do J=1,N
    1030            0 :             SUM=SUM+XPT(K,J)*W(J)
    1031              :         end do
    1032            0 :         TEMP=(TAU*W(N+K)-ALPHA*VLAG(K))*SUM
    1033            0 :         do I=1,N
    1034            0 :             S(I)=S(I)+TEMP*XPT(K,I)
    1035              :         end do
    1036              :       end do
    1037              :       SS=ZERO
    1038              :       DS=ZERO
    1039            0 :       do I=1,N
    1040            0 :         SS=SS+S(I)**2
    1041            0 :         DS=DS+D(I)*S(I)
    1042              :       end do
    1043            0 :       SSDEN=DD*SS-DS*DS
    1044            0 :       if (SSDEN >= 1.0D-8*DD*SS) GOTO 70
    1045              : !
    1046              : !     Set the vector W before the RETURN from the subroutine.
    1047              : !
    1048            0 :   340 do K=1,NDIM
    1049            0 :       W(K)=ZERO
    1050            0 :       do J=1,5
    1051            0 :          W(K)=W(K)+WVEC(K,J)*PAR(J)
    1052              :       end do
    1053              :       end do
    1054            0 :       VLAG(KOPT)=VLAG(KOPT)+ONE
    1055            0 :       RETURN
    1056              :       end subroutine BIGDEN
    1057              : 
    1058              : 
    1059          120 :       subroutine BIGLAG (N,NPT,XOPT,XPT,BMAT,ZMAT,IDZ,NDIM,KNEW,DELTA,D,ALPHA,HCOL,GC,GD,S,W)
    1060              :       implicit real(dp) (A-H,O-Z)
    1061              :       dimension XOPT(*),XPT(NPT,*),BMAT(NDIM,*),ZMAT(NPT,*),D(*),HCOL(*),GC(*),GD(*),S(*),W(*)
    1062              : !
    1063              : !     N is the number of variables.
    1064              : !     NPT is the number of interpolation equations.
    1065              : !     XOPT is the best interpolation point so far.
    1066              : !     XPT contains the coordinates of the current interpolation points.
    1067              : !     BMAT provides the last N columns of H.
    1068              : !     ZMAT and IDZ give a factorization of the first NPT by NPT submatrix of H.
    1069              : !     NDIM is the first dimension of BMAT and has the value NPT+N.
    1070              : !     KNEW is the index of the interpolation point that is going to be moved.
    1071              : !     DELTA is the current trust region bound.
    1072              : !     D will be set to the step from XOPT to the new point.
    1073              : !     ALPHA will be set to the KNEW-th diagonal element of the H matrix.
    1074              : !     HCOL, GC, GD, S and W will be used for working space.
    1075              : !
    1076              : !     The step D is calculated in a way that attempts to maximize the modulus
    1077              : !     of LFUNC(XOPT+D), subject to the bound ||D|| <= DELTA, where LFUNC is
    1078              : !     the KNEW-th Lagrange function.
    1079              : !
    1080              : !     Set some constants.
    1081              : !
    1082          120 :       HALF=0.5D0
    1083          120 :       ONE=1.0D0
    1084          120 :       ZERO=0.0D0
    1085          120 :       TWOPI=8.0D0*atan(ONE)
    1086          120 :       DELSQ=DELTA*DELTA
    1087          120 :       NPTM=NPT-N-1
    1088              : !
    1089              : !     Set the first NPT components of HCOL to the leading elements of the
    1090              : !     KNEW-th column of H.
    1091              : !
    1092          120 :       ITERC=0
    1093         1424 :       do K=1,NPT
    1094         1424 :          HCOL(K)=ZERO
    1095              :       end do
    1096          712 :       do J=1,NPTM
    1097          712 :         TEMP=ZMAT(KNEW,J)
    1098          592 :         if (J < IDZ) TEMP=-TEMP
    1099         7592 :         do K=1,NPT
    1100         7472 :             HCOL(K)=HCOL(K)+TEMP*ZMAT(K,J)
    1101              :         end do
    1102              :       end do
    1103          120 :       ALPHA=HCOL(KNEW)
    1104              : !
    1105              : !     Set the unscaled initial direction D. Form the gradient of LFUNC at
    1106              : !     XOPT, and multiply D by the second derivative matrix of LFUNC.
    1107              : !
    1108          240 :       DD=ZERO
    1109          712 :       do I=1,N
    1110          592 :         D(I)=XPT(KNEW,I)-XOPT(I)
    1111          592 :         GC(I)=BMAT(KNEW,I)
    1112          592 :         GD(I)=ZERO
    1113          712 :         DD=DD+D(I)**2
    1114              :       end do
    1115         1424 :       do K=1,NPT
    1116              :         TEMP=ZERO
    1117          120 :         SUM=ZERO
    1118         8184 :         do J=1,N
    1119         6880 :             TEMP=TEMP+XPT(K,J)*XOPT(J)
    1120         8184 :             SUM=SUM+XPT(K,J)*D(J)
    1121              :         end do
    1122         1304 :         TEMP=HCOL(K)*TEMP
    1123         1304 :         SUM=HCOL(K)*SUM
    1124         8304 :         do I=1,N
    1125         6880 :             GC(I)=GC(I)+TEMP*XPT(K,I)
    1126         8184 :             GD(I)=GD(I)+SUM*XPT(K,I)
    1127              :         end do
    1128              :       end do
    1129              : !
    1130              : !     Scale D and GD, with a sign change if required. Set S to another
    1131              : !     vector in the initial two dimensional subspace.
    1132              : !
    1133          120 :       GG=ZERO
    1134          120 :       SP=ZERO
    1135          120 :       DHD=ZERO
    1136          712 :       do I=1,N
    1137          592 :         GG=GG+GC(I)**2
    1138          592 :         SP=SP+D(I)*GC(I)
    1139          712 :         DHD=DHD+D(I)*GD(I)
    1140              :       end do
    1141          240 :       SCALE=DELTA/DSQRT(DD)
    1142          120 :       if (SP*DHD < ZERO) SCALE=-SCALE
    1143          120 :       TEMP=ZERO
    1144          120 :       if (SP*SP > 0.99D0*DD*GG) TEMP=ONE
    1145          240 :       TAU=SCALE*(DABS(SP)+HALF*SCALE*DABS(DHD))
    1146          120 :       if (GG*DELSQ < 0.01D0*TAU*TAU) TEMP=ONE
    1147          712 :       do I=1,N
    1148          592 :         D(I)=SCALE*D(I)
    1149          592 :         GD(I)=SCALE*GD(I)
    1150          805 :         S(I)=GC(I)+TEMP*GD(I)
    1151              :       end do
    1152              : !
    1153              : !     Begin the iteration by overwriting S with a vector that has the
    1154              : !     required length and direction, except that termination occurs if
    1155              : !     the given D and S are nearly parallel.
    1156              : !
    1157          213 :    80 ITERC=ITERC+1
    1158          213 :       DD=ZERO
    1159          213 :       SP=ZERO
    1160          333 :       SS=ZERO
    1161         1299 :       do I=1,N
    1162         1086 :         DD=DD+D(I)**2
    1163         1086 :         SP=SP+D(I)*S(I)
    1164         1299 :         SS=SS+S(I)**2
    1165              :       end do
    1166          213 :       TEMP=DD*SS-SP*SP
    1167          213 :       if (TEMP <= 1.0D-8*DD*SS) GOTO 160
    1168          333 :       DENOM=DSQRT(TEMP)
    1169         1299 :       do I=1,N
    1170         1086 :          S(I)=(DD*S(I)-SP*D(I))/DENOM
    1171         1299 :          W(I)=ZERO
    1172              :       end do
    1173              : !
    1174              : !     Calculate the coefficients of the objective function on the circle,
    1175              : !     beginning with the multiplication of S by the second derivative matrix.
    1176              : !
    1177         2598 :       do K=1,NPT
    1178              :         SUM=ZERO
    1179        15239 :         do J=1,N
    1180        15239 :             SUM=SUM+XPT(K,J)*S(J)
    1181              :         end do
    1182         2385 :         SUM=HCOL(K)*SUM
    1183        15452 :         do I=1,N
    1184        15239 :             W(I)=W(I)+SUM*XPT(K,I)
    1185              :         end do
    1186              :       end do
    1187          120 :       CF1=ZERO
    1188          120 :       CF2=ZERO
    1189          120 :       CF3=ZERO
    1190          120 :       CF4=ZERO
    1191          120 :       CF5=ZERO
    1192         1299 :       do I=1,N
    1193         1086 :         CF1=CF1+S(I)*W(I)
    1194         1086 :         CF2=CF2+D(I)*GC(I)
    1195         1086 :         CF3=CF3+S(I)*GC(I)
    1196         1086 :         CF4=CF4+D(I)*GD(I)
    1197         1299 :         CF5=CF5+S(I)*GD(I)
    1198              :       end do
    1199          213 :       CF1=HALF*CF1
    1200          213 :       CF4=HALF*CF4-CF1
    1201              : !
    1202              : !     Seek the value of the angle that maximizes the modulus of TAU.
    1203              : !
    1204          333 :       TAUBEG=CF1+CF2+CF4
    1205          333 :       TAUMAX=TAUBEG
    1206          333 :       TAUOLD=TAUBEG
    1207          213 :       ISAVE=0
    1208          213 :       IU=49
    1209          213 :       TEMP=TWOPI/DBLE(IU+1)
    1210        10650 :       do I=1,IU
    1211        10557 :         ANGLE=DBLE(I)*TEMP
    1212        10557 :         CTH=cos(ANGLE)
    1213        10557 :         STH=sin(ANGLE)
    1214        10437 :         TAU=CF1+(CF2+CF4*CTH)*CTH+(CF3+CF5*CTH)*STH
    1215        10437 :         if (DABS(TAU) > DABS(TAUMAX)) then
    1216              :             TAUMAX=TAU
    1217              :             ISAVE=I
    1218          120 :             TEMPA=TAUOLD
    1219         9621 :         else if (I == ISAVE+1) then
    1220          235 :             TEMPB=TAU
    1221              :         end if
    1222        10650 :         TAUOLD=TAU
    1223              :       end do
    1224          213 :       if (ISAVE == 0) TEMPA=TAU
    1225          184 :       if (ISAVE == IU) TEMPB=TAUBEG
    1226          120 :       STEP=ZERO
    1227          213 :       if (TEMPA /= TEMPB) then
    1228          213 :           TEMPA=TEMPA-TAUMAX
    1229          213 :           TEMPB=TEMPB-TAUMAX
    1230          213 :           STEP=HALF*(TEMPA-TEMPB)/(TEMPA+TEMPB)
    1231              :       end if
    1232          213 :       ANGLE=TEMP*(DBLE(ISAVE)+STEP)
    1233              : !
    1234              : !     Calculate the new D and GD. Then test for convergence.
    1235              : !
    1236          213 :       CTH=cos(ANGLE)
    1237          213 :       STH=sin(ANGLE)
    1238          213 :       TAU=CF1+(CF2+CF4*CTH)*CTH+(CF3+CF5*CTH)*STH
    1239         1299 :       do I=1,N
    1240         1086 :         D(I)=CTH*D(I)+STH*S(I)
    1241         1086 :         GD(I)=CTH*GD(I)+STH*W(I)
    1242         1299 :         S(I)=GC(I)+GD(I)
    1243              :       end do
    1244          213 :       if (DABS(TAU) <= 1.1D0*DABS(TAUBEG)) GOTO 160
    1245           93 :       if (ITERC < N) GOTO 80
    1246          120 :   160 RETURN
    1247              :       end subroutine BIGLAG
    1248              : 
    1249          252 :       subroutine TRSAPP (N,NPT,XOPT,XPT,GQ,HQ,PQ,DELTA,STEP,D,G,HD,HS,CRVMIN)
    1250              :       implicit real(dp) (A-H,O-Z)
    1251              :       dimension XOPT(*),XPT(NPT,*),GQ(*),HQ(*),PQ(*),STEP(*),D(*),G(*),HD(*),HS(*)
    1252              : !
    1253              : !     N is the number of variables of a quadratic objective function, Q say.
    1254              : !     The arguments NPT, XOPT, XPT, GQ, HQ and PQ have their usual meanings,
    1255              : !       in order to define the current quadratic model Q.
    1256              : !     DELTA is the trust region radius, and has to be positive.
    1257              : !     STEP will be set to the calculated trial step.
    1258              : !     The arrays D, G, HD and HS will be used for working space.
    1259              : !     CRVMIN will be set to the least curvature of H along the conjugate
    1260              : !       directions that occur, except that it is set to zero if STEP goes
    1261              : !       all the way to the trust region boundary.
    1262              : !
    1263              : !     The calculation of STEP begins with the truncated conjugate gradient
    1264              : !     method. If the boundary of the trust region is reached, then further
    1265              : !     changes to STEP may be made, each one being in the 2D space spanned
    1266              : !     by the current STEP and the corresponding gradient of Q. Thus STEP
    1267              : !     should provide a substantial reduction to Q within the trust region.
    1268              : !
    1269              : !     Initialization, which includes setting HD to H times XOPT.
    1270              : !
    1271          252 :       HALF=0.5D0
    1272          252 :       ZERO=0.0D0
    1273          252 :       TWOPI=8.0D0*atan(1.0D0)
    1274          252 :       DELSQ=DELTA*DELTA
    1275          252 :       ITERC=0
    1276          252 :       ITERMAX=N
    1277          252 :       ITERSW=ITERMAX
    1278         1492 :       do I=1,N
    1279         1492 :          D(I)=XOPT(I)
    1280              :       end do
    1281          252 :       GOTO 170
    1282              : !
    1283              : !     Prepare for the first line search.
    1284              : !
    1285          504 :    20 QRED=ZERO
    1286          504 :       DD=ZERO
    1287         1492 :       do I=1,N
    1288         1240 :         STEP(I)=ZERO
    1289         1240 :         HS(I)=ZERO
    1290         1240 :         G(I)=GQ(I)+HD(I)
    1291         1240 :         D(I)=-G(I)
    1292         1492 :         DD=DD+D(I)**2
    1293              :       end do
    1294          252 :       CRVMIN=ZERO
    1295          252 :       if (DD == ZERO) GOTO 160
    1296          252 :       DS=ZERO
    1297          252 :       SS=ZERO
    1298          252 :       GG=DD
    1299          629 :       GGBEG=GG
    1300              : !
    1301              : !     Calculate the step to the trust region boundary and the product HD.
    1302              : !
    1303          881 :    40 ITERC=ITERC+1
    1304         1133 :       TEMP=DELSQ-SS
    1305         1133 :       BSTEP=TEMP/(DS+DSQRT(DS*DS+DD*TEMP))
    1306         1762 :       GOTO 170
    1307         1133 :    50 DHD=ZERO
    1308         5445 :       do J=1,N
    1309         5445 :          DHD=DHD+D(J)*HD(J)
    1310              :       end do
    1311              : !
    1312              : !     Update CRVMIN and set the step-length ALPHA.
    1313              : !
    1314         1133 :       ALPHA=BSTEP
    1315          881 :       if (DHD > ZERO) then
    1316          879 :           TEMP=DHD/DD
    1317          879 :           if (ITERC == 1) CRVMIN=TEMP
    1318          879 :           CRVMIN=DMIN1(CRVMIN,TEMP)
    1319          879 :           ALPHA=DMIN1(ALPHA,GG/DHD)
    1320              :       end if
    1321         1133 :       QADD=ALPHA*(GG-HALF*ALPHA*DHD)
    1322          881 :       QRED=QRED+QADD
    1323              : !
    1324              : !     Update STEP and HS.
    1325              : !
    1326         1133 :       GGSAV=GG
    1327          881 :       GG=ZERO
    1328         5445 :       do I=1,N
    1329         4564 :         STEP(I)=STEP(I)+ALPHA*D(I)
    1330         4564 :         HS(I)=HS(I)+ALPHA*HD(I)
    1331         5445 :         GG=GG+(G(I)+HS(I))**2
    1332              :       end do
    1333              : !
    1334              : !     Begin another conjugate direction iteration if required.
    1335              : !
    1336          881 :       if (ALPHA < BSTEP) then
    1337          782 :           if (QADD <= 0.01D0*QRED) GOTO 160
    1338          704 :           if (GG <= 1.0D-4*GGBEG) GOTO 160
    1339          629 :           if (ITERC == ITERMAX) GOTO 160
    1340          629 :           TEMP=GG/GGSAV
    1341          629 :           DD=ZERO
    1342          629 :           DS=ZERO
    1343          629 :           SS=ZERO
    1344         3953 :           do I=1,N
    1345         3324 :             D(I)=TEMP*D(I)-G(I)-HS(I)
    1346         3324 :             DD=DD+D(I)**2
    1347         3324 :             DS=DS+D(I)*STEP(I)
    1348         3953 :             SS=SS+STEP(I)**2
    1349              :           end do
    1350          629 :           if (DS <= ZERO) GOTO 160
    1351          629 :           if (SS < DELSQ) GOTO 40
    1352              :       end if
    1353           99 :       CRVMIN=ZERO
    1354           99 :       ITERSW=ITERC
    1355              : !
    1356              : !     Test whether an alternative iteration is required.
    1357              : !
    1358          204 :    90 if (GG <= 1.0D-4*GGBEG) GOTO 160
    1359          456 :       SG=ZERO
    1360          456 :       SHS=ZERO
    1361         1336 :       do I=1,N
    1362         1132 :          SG=SG+STEP(I)*G(I)
    1363         1336 :          SHS=SHS+STEP(I)*HS(I)
    1364              :       end do
    1365          456 :       SGK=SG+SHS
    1366          456 :       ANGTEST=SGK/DSQRT(GG*DELSQ)
    1367          204 :       if (ANGTEST <= -0.99D0) GOTO 160
    1368              : !
    1369              : !     Begin the alternative iteration by calculating D and HD and some
    1370              : !     scalar products.
    1371              : !
    1372          186 :       ITERC=ITERC+1
    1373          186 :       TEMP=DSQRT(DELSQ*GG-SGK*SGK)
    1374          438 :       TEMPA=DELSQ/TEMP
    1375          438 :       TEMPB=SGK/TEMP
    1376         1226 :       do I=1,N
    1377         1226 :          D(I)=TEMPA*(G(I)+HS(I))-TEMPB*STEP(I)
    1378              :       end do
    1379              :       GOTO 170
    1380          252 :   120 DG=ZERO
    1381              :       DHD=ZERO
    1382          252 :       DHS=ZERO
    1383         1226 :       do I=1,N
    1384         1040 :         DG=DG+D(I)*G(I)
    1385         1040 :         DHD=DHD+HD(I)*D(I)
    1386         1226 :         DHS=DHS+HD(I)*STEP(I)
    1387              :       end do
    1388              : !
    1389              : !     Seek the value of the angle that minimizes Q.
    1390              : !
    1391          438 :       CF=HALF*(SHS-DHD)
    1392          438 :       QBEG=SG+CF
    1393          438 :       QSAV=QBEG
    1394          438 :       QMIN=QBEG
    1395          186 :       ISAVE=0
    1396          186 :       IU=49
    1397          186 :       TEMP=TWOPI/DBLE(IU+1)
    1398         9300 :       do I=1,IU
    1399         9366 :         ANGLE=DBLE(I)*TEMP
    1400         9366 :         CTH=cos(ANGLE)
    1401         9366 :         STH=sin(ANGLE)
    1402         9366 :         QNEW=(SG+CF*CTH)*CTH+(DG+DHS*CTH)*STH
    1403         9114 :         if (QNEW < QMIN) then
    1404              :             QMIN=QNEW
    1405              :             ISAVE=I
    1406              :             TEMPA=QSAV
    1407         8886 :         else if (I == ISAVE+1) then
    1408          233 :             TEMPB=QNEW
    1409              :         end if
    1410         9300 :         QSAV=QNEW
    1411              :       end do
    1412          186 :       if (ISAVE == ZERO) TEMPA=QNEW
    1413          131 :       if (ISAVE == IU) TEMPB=QBEG
    1414          186 :       ANGLE=ZERO
    1415          186 :       if (TEMPA /= TEMPB) then
    1416          186 :           TEMPA=TEMPA-QMIN
    1417          186 :           TEMPB=TEMPB-QMIN
    1418          186 :           ANGLE=HALF*(TEMPA-TEMPB)/(TEMPA+TEMPB)
    1419              :       end if
    1420          186 :       ANGLE=TEMP*(DBLE(ISAVE)+ANGLE)
    1421              : !
    1422              : !     Calculate the new STEP and HS. Then test for convergence.
    1423              : !
    1424          186 :       CTH=cos(ANGLE)
    1425          186 :       STH=sin(ANGLE)
    1426          438 :       REDUC=QBEG-(SG+CF*CTH)*CTH-(DG+DHS*CTH)*STH
    1427          186 :       GG=ZERO
    1428         1226 :       do I=1,N
    1429         1040 :         STEP(I)=CTH*STEP(I)+STH*D(I)
    1430         1040 :         HS(I)=CTH*HS(I)+STH*HD(I)
    1431         1226 :         GG=GG+(G(I)+HS(I))**2
    1432              :       end do
    1433          186 :       QRED=QRED+REDUC
    1434          252 :       RATIO=REDUC/QRED
    1435          186 :       if (ITERC < ITERMAX .and. RATIO > 0.01D0) GOTO 90
    1436          252 :   160 RETURN
    1437              : !
    1438              : !     The following instructions act as a subroutine for setting the vector
    1439              : !     HD to the vector D multiplied by the second derivative matrix of Q.
    1440              : !     They are called from three different places, which are distinguished
    1441              : !     by the value of ITERC.
    1442              : !
    1443         8163 :   170 do I=1,N
    1444         8163 :          HD(I)=ZERO
    1445              :       end do
    1446        16326 :       do K=1,NPT
    1447              :         TEMP=ZERO
    1448        96859 :         do J=1,N
    1449        96859 :            TEMP=TEMP+XPT(K,J)*D(J)
    1450              :         end do
    1451        15007 :         TEMP=TEMP*PQ(K)
    1452        98178 :         do I=1,N
    1453        96859 :            HD(I)=HD(I)+TEMP*XPT(K,I)
    1454              :         end do
    1455              :       end do
    1456              :       IH=0
    1457         8163 :       do J=1,N
    1458        30337 :         do I=1,J
    1459        22174 :         IH=IH+1
    1460        22174 :         if (I < J) HD(J)=HD(J)+HQ(IH)*D(I)
    1461        29018 :            HD(I)=HD(I)+HQ(IH)*D(J)
    1462              :         end do
    1463              :       end do
    1464         1319 :       if (ITERC == 0) GOTO 20
    1465         1067 :       if (ITERC <= ITERSW) GOTO 50
    1466              :       GOTO 120
    1467              :       end subroutine TRSAPP
    1468              : 
    1469          281 :       subroutine UPDATE (N,NPT,BMAT,ZMAT,IDZ,NDIM,VLAG,BETA,KNEW,W)
    1470              :       implicit real(dp) (A-H,O-Z)
    1471              :       dimension BMAT(NDIM,*),ZMAT(NPT,*),VLAG(*),W(*)
    1472              : !
    1473              : !     The arrays BMAT and ZMAT with IDZ are updated, in order to shift the
    1474              : !     interpolation point that has index KNEW. On entry, VLAG contains the
    1475              : !     components of the vector Theta*Wcheck+e_b of the updating formula
    1476              : !     (6.11), and BETA holds the value of the parameter that has this name.
    1477              : !     The vector W is used for working space.
    1478              : !
    1479              : !     Set some constants.
    1480              : !
    1481          281 :       ONE=1.0D0
    1482          281 :       ZERO=0.0D0
    1483          281 :       NPTM=NPT-N-1
    1484              : !
    1485              : !     Apply the rotations that put zeros in the KNEW-th row of ZMAT.
    1486              : !
    1487          281 :       JL=1
    1488         1424 :       do J=2,NPTM
    1489         1424 :         if (J == IDZ) then
    1490              :             JL=IDZ
    1491         1143 :         else if (ZMAT(KNEW,J) /= ZERO) then
    1492         1410 :             TEMP=DSQRT(ZMAT(KNEW,JL)**2+ZMAT(KNEW,J)**2)
    1493         1410 :             TEMPA=ZMAT(KNEW,JL)/TEMP
    1494         1410 :             TEMPB=ZMAT(KNEW,J)/TEMP
    1495        14654 :             do I=1,NPT
    1496        13525 :                TEMP=TEMPA*ZMAT(I,JL)+TEMPB*ZMAT(I,J)
    1497        13525 :                ZMAT(I,J)=TEMPA*ZMAT(I,J)-TEMPB*ZMAT(I,JL)
    1498        14654 :                ZMAT(I,JL)=TEMP
    1499              :             end do
    1500         1129 :             ZMAT(KNEW,J)=ZERO
    1501              :         end if
    1502              :       end do
    1503              : !
    1504              : !     Put the first NPT components of the KNEW-th column of HLAG into W,
    1505              : !     and calculate the parameters of the updating formula.
    1506              : !
    1507          281 :       TEMPA=ZMAT(KNEW,1)
    1508          281 :       if (IDZ >= 2) TEMPA=-TEMPA
    1509          281 :       if (JL > 1) TEMPB=ZMAT(KNEW,JL)
    1510         3410 :       do I=1,NPT
    1511         3129 :         W(I)=TEMPA*ZMAT(I,1)
    1512         3410 :         if (JL > 1) W(I)=W(I)+TEMPB*ZMAT(I,JL)
    1513              :       end do
    1514          562 :       ALPHA=W(KNEW)
    1515          562 :       TAU=VLAG(KNEW)
    1516          562 :       TAUSQ=TAU*TAU
    1517          562 :       DENOM=ALPHA*BETA+TAUSQ
    1518          281 :       VLAG(KNEW)=VLAG(KNEW)-ONE
    1519              : !
    1520              : !     Complete the updating of ZMAT when there is only one nonzero element
    1521              : !     in the KNEW-th row of the new matrix ZMAT, but, if IFLAG is set to one,
    1522              : !     then the first column of ZMAT will be exchanged with another one later.
    1523              : !
    1524          281 :       IFLAG=0
    1525          281 :       if (JL == 1) then
    1526          281 :           TEMP=DSQRT(DABS(DENOM))
    1527          281 :           TEMPB=TEMPA/TEMP
    1528          281 :           TEMPA=TAU/TEMP
    1529         3410 :           do I=1,NPT
    1530         3410 :              ZMAT(I,1)=TEMPA*ZMAT(I,1)-TEMPB*VLAG(I)
    1531              :           end do
    1532              :           if (IDZ == 1 .and. TEMP < ZERO) IDZ=2
    1533          281 :           if (IDZ >= 2 .and. TEMP >= ZERO) IFLAG=1
    1534              :       else
    1535              : !
    1536              : !     Complete the updating of ZMAT in the alternative case.
    1537              : !
    1538            0 :           JA=1
    1539            0 :           if (BETA >= ZERO) JA=JL
    1540            0 :           JB=JL+1-JA
    1541            0 :           TEMP=ZMAT(KNEW,JB)/DENOM
    1542            0 :           TEMPA=TEMP*BETA
    1543            0 :           TEMPB=TEMP*TAU
    1544            0 :           TEMP=ZMAT(KNEW,JA)
    1545          281 :           SCALA=ONE/DSQRT(DABS(BETA)*TEMP*TEMP+TAUSQ)
    1546          281 :           SCALB=SCALA*DSQRT(DABS(DENOM))
    1547            0 :           do I=1,NPT
    1548            0 :              ZMAT(I,JA)=SCALA*(TAU*ZMAT(I,JA)-TEMP*VLAG(I))
    1549            0 :              ZMAT(I,JB)=SCALB*(ZMAT(I,JB)-TEMPA*W(I)-TEMPB*VLAG(I))
    1550              :           end do
    1551            0 :           if (DENOM <= ZERO) then
    1552            0 :               if (BETA < ZERO) IDZ=IDZ+1
    1553            0 :               if (BETA >= ZERO) IFLAG=1
    1554              :           end if
    1555              :       end if
    1556              : !
    1557              : !     IDZ is reduced in the following case, and usually the first column
    1558              : !     of ZMAT is exchanged with a later one.
    1559              : !
    1560              :       if (IFLAG == 1) then
    1561            0 :           IDZ=IDZ-1
    1562            0 :           do I=1,NPT
    1563            0 :             TEMP=ZMAT(I,1)
    1564            0 :             ZMAT(I,1)=ZMAT(I,IDZ)
    1565            0 :             ZMAT(I,IDZ)=TEMP
    1566              :           end do
    1567              :       end if
    1568              : !
    1569              : !     Finally, update the matrix BMAT.
    1570              : !
    1571         1705 :       do J=1,N
    1572         1424 :         JP=NPT+J
    1573         1424 :         W(JP)=BMAT(KNEW,J)
    1574         1424 :         TEMPA=(ALPHA*VLAG(JP)-TAU*W(JP))/DENOM
    1575         1424 :         TEMPB=(-BETA*W(JP)-TAU*VLAG(JP))/DENOM
    1576        23081 :         do I=1,JP
    1577        21376 :             BMAT(I,J)=BMAT(I,J)+TEMPA*VLAG(I)+TEMPB*W(I)
    1578        22800 :             if (I > NPT) BMAT(JP,I-NPT)=BMAT(I,J)
    1579              :         end do
    1580              :       end do
    1581          281 :       end subroutine UPDATE
    1582              : 
    1583              :       end module mod_newuoa
        

Generated by: LCOV version 2.0-1