Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : !******************************************************************************
9 : MODULE powell
10 : USE kinds, ONLY: dp
11 : USE mathconstants, ONLY: twopi
12 : #include "../base/base_uses.f90"
13 :
14 : IMPLICIT NONE
15 :
16 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'powell'
17 :
18 : TYPE opt_state_type
19 : INTEGER :: state = -1
20 : INTEGER :: nvar = -1
21 : INTEGER :: iprint = -1
22 : INTEGER :: unit = -1
23 : INTEGER :: maxfun = -1
24 : REAL(dp) :: rhobeg = 0.0_dp, rhoend = 0.0_dp
25 : REAL(dp), DIMENSION(:), POINTER :: w => NULL()
26 : REAL(dp), DIMENSION(:), POINTER :: xopt => NULL()
27 : ! local variables
28 : INTEGER :: np = -1, nh = -1, nptm = -1, nftest = -1, idz = -1, itest = -1, nf = -1, nfm = -1, nfmm = -1, &
29 : nfsav = -1, knew = -1, kopt = -1, ksave = -1, ktemp = -1
30 : REAL(dp) :: rhosq = 0.0_dp, recip = 0.0_dp, reciq = 0.0_dp, fbeg = 0.0_dp, &
31 : fopt = 0.0_dp, diffa = 0.0_dp, xoptsq = 0.0_dp, &
32 : rho = 0.0_dp, delta = 0.0_dp, dsq = 0.0_dp, dnorm = 0.0_dp, &
33 : ratio = 0.0_dp, temp = 0.0_dp, tempq = 0.0_dp, beta = 0.0_dp, &
34 : dx = 0.0_dp, vquad = 0.0_dp, diff = 0.0_dp, diffc = 0.0_dp, &
35 : diffb = 0.0_dp, fsave = 0.0_dp, detrat = 0.0_dp, hdiag = 0.0_dp, &
36 : distsq = 0.0_dp, gisq = 0.0_dp, gqsq = 0.0_dp, f = 0.0_dp, &
37 : bstep = 0.0_dp, alpha = 0.0_dp, dstep = 0.0_dp
38 : END TYPE opt_state_type
39 :
40 : PRIVATE
41 : PUBLIC :: powell_optimize, opt_state_type
42 :
43 : !******************************************************************************
44 :
45 : CONTAINS
46 :
47 : !******************************************************************************
48 : ! **************************************************************************************************
49 : !> \brief ...
50 : !> \param n ...
51 : !> \param x ...
52 : !> \param optstate ...
53 : ! **************************************************************************************************
54 53736191 : SUBROUTINE powell_optimize(n, x, optstate)
55 : INTEGER, INTENT(IN) :: n
56 : REAL(dp), DIMENSION(*), INTENT(INOUT) :: x
57 : TYPE(opt_state_type), INTENT(INOUT) :: optstate
58 :
59 : CHARACTER(len=*), PARAMETER :: routineN = 'powell_optimize'
60 :
61 : INTEGER :: handle, npt
62 :
63 53736191 : CALL timeset(routineN, handle)
64 :
65 54417091 : SELECT CASE (optstate%state)
66 : CASE (0)
67 680900 : npt = 2*n + 1
68 2042700 : ALLOCATE (optstate%w((npt + 13)*(npt + n) + 3*n*(n + 3)/2))
69 2042700 : ALLOCATE (optstate%xopt(n))
70 : ! Initialize w
71 96825491 : optstate%w = 0.0_dp
72 680900 : optstate%state = 1
73 680900 : CALL newuoa(n, x, optstate)
74 : CASE (1, 2)
75 51693493 : CALL newuoa(n, x, optstate)
76 : CASE (3)
77 9 : IF (optstate%unit > 0) THEN
78 6 : WRITE (optstate%unit, *) "POWELL| Exceeding maximum number of steps"
79 : END IF
80 9 : optstate%state = -1
81 : CASE (4)
82 4 : IF (optstate%unit > 0) THEN
83 4 : WRITE (optstate%unit, *) "POWELL| Error in trust region"
84 : END IF
85 4 : optstate%state = -1
86 : CASE (5)
87 0 : IF (optstate%unit > 0) THEN
88 0 : WRITE (optstate%unit, *) "POWELL| N out of range"
89 : END IF
90 0 : optstate%state = -1
91 : CASE (6, 7)
92 680885 : optstate%state = -1
93 : CASE (8)
94 2043021 : x(1:n) = optstate%xopt(1:n)
95 680900 : DEALLOCATE (optstate%w)
96 680900 : DEALLOCATE (optstate%xopt)
97 680900 : optstate%state = -1
98 : CASE DEFAULT
99 53736191 : CPABORT("")
100 : END SELECT
101 :
102 53736191 : CALL timestop(handle)
103 :
104 53736191 : END SUBROUTINE powell_optimize
105 : !******************************************************************************
106 : ! **************************************************************************************************
107 : !> \brief ...
108 : !> \param n ...
109 : !> \param x ...
110 : !> \param optstate ...
111 : ! **************************************************************************************************
112 52374393 : SUBROUTINE newuoa(n, x, optstate)
113 :
114 : INTEGER, INTENT(IN) :: n
115 : REAL(dp), DIMENSION(*), INTENT(INOUT) :: x
116 : TYPE(opt_state_type), INTENT(INOUT) :: optstate
117 :
118 : INTEGER :: ibmat, id, ifv, igq, ihq, ipq, ivl, iw, &
119 : ixb, ixn, ixo, ixp, izmat, maxfun, &
120 : ndim, np, npt, nptm
121 : REAL(dp) :: rhobeg, rhoend
122 :
123 52374393 : maxfun = optstate%maxfun
124 52374393 : rhobeg = optstate%rhobeg
125 52374393 : rhoend = optstate%rhoend
126 :
127 : !
128 : ! This subroutine seeks the least value of a function of many variab
129 : ! by a trust region method that forms quadratic models by interpolat
130 : ! There can be some freedom in the interpolation conditions, which i
131 : ! taken up by minimizing the Frobenius norm of the change to the sec
132 : ! derivative of the quadratic model, beginning with a zero matrix. T
133 : ! arguments of the subroutine are as follows.
134 : !
135 : ! N must be set to the number of variables and must be at least two.
136 : ! NPT is the number of interpolation conditions. Its value must be i
137 : ! interval [N+2,(N+1)(N+2)/2].
138 : ! Initial values of the variables must be set in X(1),X(2),...,X(N).
139 : ! will be changed to the values that give the least calculated F.
140 : ! RHOBEG and RHOEND must be set to the initial and final values of a
141 : ! region radius, so both must be positive with RHOEND<=RHOBEG. Typ
142 : ! RHOBEG should be about one tenth of the greatest expected change
143 : ! variable, and RHOEND should indicate the accuracy that is requir
144 : ! the final values of the variables.
145 : ! The value of IPRINT should be set to 0, 1, 2 or 3, which controls
146 : ! amount of printing. Specifically, there is no output if IPRINT=0
147 : ! there is output only at the return if IPRINT=1. Otherwise, each
148 : ! value of RHO is printed, with the best vector of variables so fa
149 : ! the corresponding value of the objective function. Further, each
150 : ! value of F with its variables are output if IPRINT=3.
151 : ! MAXFUN must be set to an upper bound on the number of calls of CAL
152 : ! The array W will be used for working space. Its length must be at
153 : ! (NPT+13)*(NPT+N)+3*N*(N+3)/2.
154 : !
155 : ! SUBROUTINE CALFUN (N,X,F) must be provided by the user. It must se
156 : ! the value of the objective function for the variables X(1),X(2),..
157 : !
158 : ! Partition the working space array, so that different parts of it c
159 : ! treated separately by the subroutine that performs the main calcul
160 : !
161 52374393 : np = n + 1
162 52374393 : npt = 2*n + 1
163 52374393 : nptm = npt - np
164 52374393 : IF (npt < n + 2 .OR. npt > ((n + 2)*np)/2) THEN
165 0 : optstate%state = 5
166 0 : RETURN
167 : END IF
168 52374393 : ndim = npt + n
169 52374393 : ixb = 1
170 52374393 : ixo = ixb + n
171 52374393 : ixn = ixo + n
172 52374393 : ixp = ixn + n
173 52374393 : ifv = ixp + n*npt
174 52374393 : igq = ifv + npt
175 52374393 : ihq = igq + n
176 52374393 : ipq = ihq + (n*np)/2
177 52374393 : ibmat = ipq + npt
178 52374393 : izmat = ibmat + ndim*n
179 52374393 : id = izmat + npt*nptm
180 52374393 : ivl = id + n
181 52374393 : iw = ivl + ndim
182 : !
183 : ! The above settings provide a partition of W for subroutine NEWUOB.
184 : ! The partition requires the first NPT*(NPT+N)+5*N*(N+3)/2 elements
185 : ! W plus the space that is needed by the last array of NEWUOB.
186 : !
187 : CALL newuob(n, npt, x, rhobeg, rhoend, maxfun, optstate%w(ixb:), optstate%w(ixo:), &
188 : optstate%w(ixn:), optstate%w(ixp:), optstate%w(ifv:), optstate%w(igq:), optstate%w(ihq:), &
189 : optstate%w(ipq:), optstate%w(ibmat:), optstate%w(izmat:), ndim, optstate%w(id:), &
190 52374393 : optstate%w(ivl:), optstate%w(iw:), optstate)
191 :
192 157134903 : optstate%xopt(1:n) = optstate%w(ixb:ixb + n - 1) + optstate%w(ixo:ixo + n - 1)
193 :
194 : END SUBROUTINE newuoa
195 :
196 : !******************************************************************************
197 : ! **************************************************************************************************
198 : !> \brief ...
199 : !> \param n ...
200 : !> \param npt ...
201 : !> \param x ...
202 : !> \param rhobeg ...
203 : !> \param rhoend ...
204 : !> \param maxfun ...
205 : !> \param xbase ...
206 : !> \param xopt ...
207 : !> \param xnew ...
208 : !> \param xpt ...
209 : !> \param fval ...
210 : !> \param gq ...
211 : !> \param hq ...
212 : !> \param pq ...
213 : !> \param bmat ...
214 : !> \param zmat ...
215 : !> \param ndim ...
216 : !> \param d ...
217 : !> \param vlag ...
218 : !> \param w ...
219 : !> \param opt ...
220 : ! **************************************************************************************************
221 52374393 : SUBROUTINE newuob(n, npt, x, rhobeg, rhoend, maxfun, xbase, &
222 52374393 : xopt, xnew, xpt, fval, gq, hq, pq, bmat, zmat, ndim, d, vlag, w, opt)
223 :
224 : INTEGER, INTENT(in) :: n, npt
225 : REAL(dp), DIMENSION(1:n), INTENT(inout) :: x
226 : REAL(dp), INTENT(in) :: rhobeg, rhoend
227 : INTEGER, INTENT(in) :: maxfun
228 : REAL(dp), DIMENSION(*), INTENT(inout) :: xbase, xopt, xnew
229 : REAL(dp), DIMENSION(npt, *), &
230 : INTENT(inout) :: xpt
231 : REAL(dp), DIMENSION(*), INTENT(inout) :: fval, gq, hq, pq
232 : INTEGER, INTENT(in) :: ndim
233 : REAL(dp), DIMENSION(npt, *), &
234 : INTENT(inout) :: zmat
235 : REAL(dp), DIMENSION(ndim, *), &
236 : INTENT(inout) :: bmat
237 : REAL(dp), DIMENSION(*), INTENT(inout) :: d, vlag, w
238 : TYPE(opt_state_type) :: opt
239 :
240 : INTEGER :: i, idz, ih, ip, ipt, itemp, &
241 : itest, j, jp, jpt, k, knew, &
242 : kopt, ksave, ktemp, nf, nfm, &
243 : nfmm, nfsav, nftest, nh, np, &
244 : nptm
245 : REAL(dp) :: alpha, beta, bstep, bsum, crvmin, delta, detrat, diff, diffa, &
246 : diffb, diffc, distsq, dnorm, dsq, dstep, dx, f, fbeg, fopt, fsave, &
247 : gisq, gqsq, half, hdiag, one, ratio, recip, reciq, rho, rhosq, sum, &
248 : suma, sumb, sumz, temp, tempq, tenth, vquad, xipt, xjpt, xoptsq, zero
249 :
250 : !
251 : ! The arguments N, NPT, X, RHOBEG, RHOEND, IPRINT and MAXFUN are ide
252 : ! to the corresponding arguments in SUBROUTINE NEWUOA.
253 : ! XBASE will hold a shift of origin that should reduce the contribut
254 : ! from rounding errors to values of the model and Lagrange functio
255 : ! XOPT will be set to the displacement from XBASE of the vector of
256 : ! variables that provides the least calculated F so far.
257 : ! XNEW will be set to the displacement from XBASE of the vector of
258 : ! variables for the current calculation of F.
259 : ! XPT will contain the interpolation point coordinates relative to X
260 : ! FVAL will hold the values of F at the interpolation points.
261 : ! GQ will hold the gradient of the quadratic model at XBASE.
262 : ! HQ will hold the explicit second derivatives of the quadratic mode
263 : ! PQ will contain the parameters of the implicit second derivatives
264 : ! the quadratic model.
265 : ! BMAT will hold the last N columns of H.
266 : ! ZMAT will hold the factorization of the leading NPT by NPT submatr
267 : ! H, this factorization being ZMAT times Diag(DZ) times ZMAT^T, wh
268 : ! the elements of DZ are plus or minus one, as specified by IDZ.
269 : ! NDIM is the first dimension of BMAT and has the value NPT+N.
270 : ! D is reserved for trial steps from XOPT.
271 : ! VLAG will contain the values of the Lagrange functions at a new po
272 : ! They are part of a product that requires VLAG to be of length ND
273 : ! The array W will be used for working space. Its length must be at
274 : ! 10*NDIM = 10*(NPT+N).
275 :
276 52374393 : IF (opt%state == 1) THEN
277 : ! initialize all variable that will be stored
278 : np = 0
279 : nh = 0
280 : nptm = 0
281 : nftest = 0
282 680900 : idz = 0
283 680900 : itest = 0
284 680900 : nf = 0
285 680900 : nfm = 0
286 680900 : nfmm = 0
287 680900 : nfsav = 0
288 680900 : knew = 0
289 680900 : kopt = 0
290 680900 : ksave = 0
291 680900 : ktemp = 0
292 680900 : rhosq = 0._dp
293 680900 : recip = 0._dp
294 680900 : reciq = 0._dp
295 680900 : fbeg = 0._dp
296 680900 : fopt = 0._dp
297 680900 : diffa = 0._dp
298 680900 : xoptsq = 0._dp
299 680900 : rho = 0._dp
300 680900 : delta = 0._dp
301 680900 : dsq = 0._dp
302 680900 : dnorm = 0._dp
303 680900 : ratio = 0._dp
304 680900 : temp = 0._dp
305 680900 : tempq = 0._dp
306 680900 : beta = 0._dp
307 680900 : dx = 0._dp
308 680900 : vquad = 0._dp
309 680900 : diff = 0._dp
310 680900 : diffc = 0._dp
311 680900 : diffb = 0._dp
312 680900 : fsave = 0._dp
313 680900 : detrat = 0._dp
314 680900 : hdiag = 0._dp
315 680900 : distsq = 0._dp
316 680900 : gisq = 0._dp
317 680900 : gqsq = 0._dp
318 680900 : f = 0._dp
319 680900 : bstep = 0._dp
320 680900 : alpha = 0._dp
321 680900 : dstep = 0._dp
322 : !
323 : END IF
324 :
325 52374393 : ipt = 0
326 52374393 : jpt = 0
327 52374393 : xipt = 0._dp
328 52374393 : xjpt = 0._dp
329 :
330 52374393 : half = 0.5_dp
331 52374393 : one = 1.0_dp
332 52374393 : tenth = 0.1_dp
333 52374393 : zero = 0.0_dp
334 52374393 : np = n + 1
335 52374393 : nh = (n*np)/2
336 52374393 : nptm = npt - np
337 52374393 : nftest = MAX(maxfun, 1)
338 :
339 52374393 : IF (opt%state == 2) GOTO 1000
340 : !
341 : ! Set the initial elements of XPT, BMAT, HQ, PQ and ZMAT to zero.
342 : !
343 2043021 : DO j = 1, n
344 1362121 : xbase(j) = x(j)
345 8204008 : DO k = 1, npt
346 8204008 : xpt(k, j) = zero
347 : END DO
348 11624791 : DO i = 1, ndim
349 10943891 : bmat(i, j) = zero
350 : END DO
351 : END DO
352 2731902 : DO ih = 1, nh
353 2731902 : hq(ih) = zero
354 : END DO
355 4086042 : DO k = 1, npt
356 3405142 : pq(k) = zero
357 10927929 : DO j = 1, nptm
358 10247029 : zmat(k, j) = zero
359 : END DO
360 : END DO
361 : !
362 : ! Begin the initialization procedure. NF becomes one more than the n
363 : ! of function values so far. The coordinates of the displacement of
364 : ! next initial interpolation point from XBASE are set in XPT(NF,.).
365 : !
366 680900 : rhosq = rhobeg*rhobeg
367 680900 : recip = one/rhosq
368 680900 : reciq = SQRT(half)/rhosq
369 680900 : nf = 0
370 3404679 : 50 nfm = nf
371 3404679 : nfmm = nf - n
372 3404679 : nf = nf + 1
373 3404679 : IF (nfm <= 2*n) THEN
374 3404679 : IF (nfm >= 1 .AND. nfm <= N) THEN
375 1361926 : xpt(nf, nfm) = rhobeg
376 2042753 : ELSE IF (nfm > n) THEN
377 1361853 : xpt(nf, nfmm) = -rhobeg
378 : END IF
379 : ELSE
380 0 : itemp = (nfmm - 1)/n
381 0 : jpt = nfm - itemp*n - n
382 0 : ipt = jpt + itemp
383 0 : IF (ipt > n) THEN
384 0 : itemp = jpt
385 0 : jpt = ipt - n
386 0 : ipt = itemp
387 : END IF
388 0 : xipt = rhobeg
389 0 : IF (fval(ipt + np) < fval(ipt + 1)) xipt = -xipt
390 0 : XJPT = RHOBEG
391 0 : IF (fval(jpt + np) < fval(jpt + 1)) xjpt = -xjpt
392 0 : xpt(nf, ipt) = xipt
393 0 : xpt(nf, jpt) = xjpt
394 : END IF
395 : !
396 : ! Calculate the next value of F, label 70 being reached immediately
397 : ! after this calculation. The least function value so far and its in
398 : ! are required.
399 : !
400 10219711 : DO j = 1, n
401 10219711 : x(j) = xpt(nf, j) + xbase(j)
402 : END DO
403 3404671 : GOTO 310
404 3404671 : 70 fval(nf) = f
405 3404671 : IF (nf == 1) THEN
406 680900 : fbeg = f
407 680900 : fopt = f
408 680900 : kopt = 1
409 2723771 : ELSE IF (f < fopt) THEN
410 759861 : fopt = f
411 759861 : kopt = nf
412 : END IF
413 : !
414 : ! Set the nonzero initial elements of BMAT and the quadratic model i
415 : ! the cases when NF is at most 2*N+1.
416 : !
417 3404671 : IF (NFM <= 2*N) THEN
418 3404671 : IF (nfm >= 1 .AND. nfm <= n) THEN
419 1361918 : gq(nfm) = (f - fbeg)/rhobeg
420 1361918 : IF (npt < nf + n) THEN
421 0 : bmat(1, nfm) = -one/rhobeg
422 0 : bmat(nf, nfm) = one/rhobeg
423 0 : bmat(npt + nfm, nfm) = -half*rhosq
424 : END IF
425 2042753 : ELSE IF (nfm > n) THEN
426 1361853 : bmat(nf - n, nfmm) = half/rhobeg
427 1361853 : bmat(nf, nfmm) = -half/rhobeg
428 1361853 : zmat(1, nfmm) = -reciq - reciq
429 1361853 : zmat(nf - n, nfmm) = reciq
430 1361853 : zmat(nf, nfmm) = reciq
431 1361853 : ih = (nfmm*(nfmm + 1))/2
432 1361853 : temp = (fbeg - f)/rhobeg
433 1361853 : hq(ih) = (gq(nfmm) - temp)/rhobeg
434 1361853 : gq(nfmm) = half*(gq(nfmm) + temp)
435 : END IF
436 : !
437 : ! Set the off-diagonal second derivatives of the Lagrange functions
438 : ! the initial quadratic model.
439 : !
440 : ELSE
441 0 : ih = (ipt*(ipt - 1))/2 + jpt
442 : IF (xipt < zero) ipt = ipt + n
443 : IF (xjpt < zero) jpt = jpt + n
444 0 : zmat(1, nfmm) = recip
445 0 : zmat(nf, nfmm) = recip
446 0 : zmat(ipt + 1, nfmm) = -recip
447 : zmat(jpt + 1, nfmm) = -recip
448 0 : hq(ih) = (fbeg - fval(ipt + 1) - fval(jpt + 1) + f)/(xipt*xjpt)
449 : END IF
450 3404671 : IF (nf < npt) GOTO 50
451 : !
452 : ! Begin the iterative procedure, because the initial model is comple
453 : !
454 680892 : rho = rhobeg
455 680892 : delta = rho
456 680892 : idz = 1
457 680892 : diffa = zero
458 680892 : diffb = zero
459 680892 : itest = 0
460 680892 : xoptsq = zero
461 2042745 : DO i = 1, n
462 1361853 : xopt(i) = xpt(kopt, i)
463 2042745 : xoptsq = xoptsq + xopt(i)**2
464 : END DO
465 4085548 : 90 nfsav = nf
466 : !
467 : ! Generate the next trust region step and test its length. Set KNEW
468 : ! to -1 if the purpose of the next F will be to improve the model.
469 : !
470 40797062 : 100 knew = 0
471 40797062 : CALL trsapp(n, npt, xopt, xpt, gq, hq, pq, delta, d, w, w(np), w(np + n), w(np + 2*n), crvmin)
472 40797062 : dsq = zero
473 122395513 : DO i = 1, n
474 122395513 : dsq = dsq + d(i)**2
475 : END DO
476 40797062 : dnorm = MIN(delta, SQRT(dsq))
477 40797062 : IF (dnorm < half*rho) THEN
478 9936790 : knew = -1
479 9936790 : delta = tenth*delta
480 9936790 : ratio = -1.0_dp
481 9936790 : IF (delta <= 1.5_dp*rho) delta = rho
482 9936790 : IF (nf <= nfsav + 2) GOTO 460
483 2747420 : temp = 0.125_dp*crvmin*rho*rho
484 2747420 : IF (temp <= MAX(diffa, diffb, diffc)) GOTO 460
485 : GOTO 490
486 : END IF
487 : !
488 : ! Shift XBASE if XOPT may be too far from XBASE. First make the chan
489 : ! to BMAT that do not depend on ZMAT.
490 : !
491 47721103 : 120 IF (dsq <= 1.0e-3_dp*xoptsq) THEN
492 2925891 : tempq = 0.25_dp*xoptsq
493 17555646 : DO k = 1, npt
494 : sum = zero
495 43890967 : DO i = 1, n
496 43890967 : sum = sum + xpt(k, i)*xopt(i)
497 : END DO
498 14629755 : temp = pq(k)*sum
499 14629755 : sum = sum - half*xoptsq
500 14629755 : w(npt + k) = sum
501 46816858 : DO i = 1, n
502 29261212 : gq(i) = gq(i) + temp*xpt(k, i)
503 29261212 : xpt(k, i) = xpt(k, i) - half*xopt(i)
504 29261212 : vlag(i) = bmat(k, i)
505 29261212 : w(i) = sum*xpt(k, i) + tempq*xopt(i)
506 29261212 : ip = npt + i
507 87787261 : DO j = 1, i
508 73157506 : bmat(ip, j) = bmat(ip, j) + vlag(i)*w(j) + w(i)*vlag(j)
509 : END DO
510 : END DO
511 : END DO
512 : !
513 : ! Then the revisions of BMAT that depend on ZMAT are calculated.
514 : !
515 8777823 : DO k = 1, nptm
516 : sumz = zero
517 35113144 : DO i = 1, npt
518 29261212 : sumz = sumz + zmat(i, k)
519 35113144 : w(i) = w(npt + i)*zmat(i, k)
520 : END DO
521 17556572 : DO j = 1, n
522 11704640 : sum = tempq*sumz*xopt(j)
523 70236016 : DO i = 1, npt
524 58531376 : sum = sum + w(i)*xpt(i, j)
525 58531376 : vlag(j) = sum
526 70236016 : IF (k < idz) sum = -sum
527 : END DO
528 76087948 : DO i = 1, npt
529 70236016 : bmat(i, j) = bmat(i, j) + sum*zmat(i, k)
530 : END DO
531 : END DO
532 20482463 : DO i = 1, n
533 11704640 : ip = i + npt
534 11704640 : temp = vlag(i)
535 11704640 : IF (k < idz) temp = -temp
536 35115576 : DO j = 1, i
537 29263644 : bmat(ip, j) = bmat(ip, j) + temp*vlag(j)
538 : END DO
539 : END DO
540 : END DO
541 : !
542 : ! The following instructions complete the shift of XBASE, including
543 : ! the changes to the parameters of the quadratic model.
544 : !
545 : ih = 0
546 8777823 : DO j = 1, n
547 5851932 : w(j) = zero
548 35113144 : DO k = 1, npt
549 29261212 : w(j) = w(j) + pq(k)*xpt(k, j)
550 35113144 : xpt(k, j) = xpt(k, j) - half*xopt(j)
551 : END DO
552 17556109 : DO i = 1, j
553 8778286 : ih = ih + 1
554 8778286 : IF (i < j) gq(j) = gq(j) + hq(ih)*xopt(i)
555 8778286 : gq(i) = gq(i) + hq(ih)*xopt(j)
556 8778286 : hq(ih) = hq(ih) + w(i)*xopt(j) + xopt(i)*w(j)
557 14630218 : bmat(npt + i, j) = bmat(npt + j, i)
558 : END DO
559 : END DO
560 8777823 : DO j = 1, n
561 5851932 : xbase(j) = xbase(j) + xopt(j)
562 8777823 : xopt(j) = zero
563 : END DO
564 2925891 : xoptsq = zero
565 : END IF
566 : !
567 : ! Pick the model step if KNEW is positive. A different choice of D
568 : ! may be made later, if the choice of D by BIGLAG causes substantial
569 : ! cancellation in DENOM.
570 : !
571 47721103 : IF (knew > 0) THEN
572 : CALL biglag(n, npt, xopt, xpt, bmat, zmat, idz, ndim, knew, dstep, &
573 16860831 : d, alpha, vlag, vlag(npt + 1), w, w(np), w(np + n))
574 : END IF
575 : !
576 : ! Calculate VLAG and BETA for the current choice of D. The first NPT
577 : ! components of W_check will be held in W.
578 : !
579 286338510 : DO k = 1, npt
580 : suma = zero
581 : sumb = zero
582 : sum = zero
583 715920935 : DO j = 1, n
584 477303528 : suma = suma + xpt(k, j)*d(j)
585 477303528 : sumb = sumb + xpt(k, j)*xopt(j)
586 715920935 : sum = sum + bmat(k, j)*d(j)
587 : END DO
588 238617407 : w(k) = suma*(half*suma + sumb)
589 286338510 : vlag(k) = sum
590 : END DO
591 47721103 : beta = zero
592 143169255 : DO k = 1, nptm
593 : sum = zero
594 572751680 : DO i = 1, npt
595 572751680 : sum = sum + zmat(i, k)*w(i)
596 : END DO
597 95448152 : IF (k < idz) THEN
598 0 : beta = beta + sum*sum
599 0 : sum = -sum
600 : ELSE
601 95448152 : beta = beta - sum*sum
602 : END IF
603 620472783 : DO i = 1, npt
604 572751680 : vlag(i) = vlag(i) + sum*zmat(i, k)
605 : END DO
606 : END DO
607 47721103 : bsum = zero
608 47721103 : dx = zero
609 143169255 : DO j = 1, n
610 : sum = zero
611 572751680 : DO i = 1, npt
612 572751680 : sum = sum + w(i)*bmat(i, j)
613 : END DO
614 95448152 : bsum = bsum + sum*d(j)
615 95448152 : jp = npt + j
616 286375840 : DO k = 1, n
617 286375840 : sum = sum + bmat(jp, k)*d(k)
618 : END DO
619 95448152 : vlag(jp) = sum
620 95448152 : bsum = bsum + sum*d(j)
621 143169255 : dx = dx + d(j)*xopt(j)
622 : END DO
623 47721103 : beta = dx*dx + dsq*(xoptsq + dx + dx + half*dsq) + beta - bsum
624 47721103 : vlag(kopt) = vlag(kopt) + one
625 : !
626 : ! If KNEW is positive and if the cancellation in DENOM is unacceptab
627 : ! then BIGDEN calculates an alternative model step, XNEW being used
628 : ! working space.
629 : !
630 47721103 : IF (knew > 0) THEN
631 16860831 : temp = one + alpha*beta/vlag(knew)**2
632 16860831 : IF (ABS(temp) <= 0.8_dp) THEN
633 : CALL bigden(n, npt, xopt, xpt, bmat, zmat, idz, ndim, kopt, &
634 110 : knew, d, w, vlag, beta, xnew, w(ndim + 1), w(6*ndim + 1))
635 : END IF
636 : END IF
637 : !
638 : ! Calculate the next value of the objective function.
639 : !
640 144872461 : 290 DO i = 1, n
641 96583636 : xnew(i) = xopt(i) + d(i)
642 144872461 : x(i) = xbase(i) + xnew(i)
643 : END DO
644 48288825 : nf = nf + 1
645 51693504 : 310 IF (nf > nftest) THEN
646 : ! return to many steps
647 11 : nf = nf - 1
648 11 : opt%state = 3
649 11 : CALL get_state
650 11 : GOTO 530
651 : END IF
652 :
653 51693493 : CALL get_state
654 :
655 51693493 : opt%state = 2
656 :
657 51693493 : RETURN
658 :
659 : 1000 CONTINUE
660 :
661 51693493 : CALL set_state
662 :
663 51693493 : IF (nf <= npt) GOTO 70
664 48288822 : IF (knew == -1) THEN
665 567722 : opt%state = 6
666 567722 : CALL get_state
667 567722 : GOTO 530
668 : END IF
669 : !
670 : ! Use the quadratic model to predict the change in F due to the step
671 : ! and set DIFF to the error of this prediction.
672 : !
673 47721100 : vquad = zero
674 47721100 : ih = 0
675 143169241 : DO j = 1, n
676 95448141 : vquad = vquad + d(j)*gq(j)
677 286357127 : DO i = 1, j
678 143187886 : ih = ih + 1
679 143187886 : temp = d(i)*xnew(j) + d(j)*xopt(i)
680 143187886 : IF (i == j) temp = half*temp
681 238636027 : vquad = vquad + temp*hq(ih)
682 : END DO
683 : END DO
684 286338482 : DO k = 1, npt
685 286338482 : vquad = vquad + pq(k)*w(k)
686 : END DO
687 47721100 : diff = f - fopt - vquad
688 47721100 : diffc = diffb
689 47721100 : diffb = diffa
690 47721100 : diffa = ABS(diff)
691 47721100 : IF (dnorm > rho) nfsav = nf
692 : !
693 : ! Update FOPT and XOPT if the new F is the least value of the object
694 : ! function so far. The branch when KNEW is positive occurs if D is n
695 : ! a trust region step.
696 : !
697 47721100 : fsave = fopt
698 47721100 : IF (f < fopt) THEN
699 24425684 : fopt = f
700 24425684 : xoptsq = zero
701 73278949 : DO i = 1, n
702 48853265 : xopt(i) = xnew(i)
703 73278949 : xoptsq = xoptsq + xopt(i)**2
704 : END DO
705 : END IF
706 47721100 : ksave = knew
707 47721100 : IF (knew > 0) GOTO 410
708 : !
709 : ! Pick the next value of DELTA after a trust region step.
710 : !
711 30860271 : IF (vquad >= zero) THEN
712 : ! Return because a trust region step has failed to reduce Q
713 4 : opt%state = 4
714 4 : CALL get_state
715 4 : GOTO 530
716 : END IF
717 30860267 : ratio = (f - fsave)/vquad
718 30860267 : IF (ratio <= tenth) THEN
719 11403093 : delta = half*dnorm
720 19457174 : ELSE IF (ratio <= 0.7_dp) THEN
721 3355246 : delta = MAX(half*delta, dnorm)
722 : ELSE
723 16101928 : delta = MAX(half*delta, dnorm + dnorm)
724 : END IF
725 30860267 : IF (delta <= 1.5_dp*rho) delta = rho
726 : !
727 : ! Set KNEW to the index of the next interpolation point to be delete
728 : !
729 30860267 : rhosq = MAX(tenth*delta, rho)**2
730 30860267 : ktemp = 0
731 30860267 : detrat = zero
732 30860267 : IF (f >= fsave) THEN
733 9782163 : ktemp = kopt
734 9782163 : detrat = one
735 : END IF
736 185168784 : DO k = 1, npt
737 154308517 : hdiag = zero
738 462966812 : DO j = 1, nptm
739 308658295 : temp = one
740 308658295 : IF (j < idz) temp = -one
741 462966812 : hdiag = hdiag + temp*zmat(k, j)**2
742 : END DO
743 154308517 : temp = ABS(beta*hdiag + vlag(k)**2)
744 154308517 : distsq = zero
745 462966812 : DO j = 1, n
746 462966812 : distsq = distsq + (xpt(k, j) - xopt(j))**2
747 : END DO
748 154308517 : IF (distsq > rhosq) temp = temp*(distsq/rhosq)**3
749 185168784 : IF (temp > detrat .AND. k /= ktemp) THEN
750 66456670 : detrat = temp
751 66456670 : knew = k
752 : END IF
753 : END DO
754 30860267 : IF (knew == 0) GOTO 460
755 : !
756 : ! Update BMAT, ZMAT and IDZ, so that the KNEW-th interpolation point
757 : ! can be moved. Begin the updating of the quadratic model, starting
758 : ! with the explicit second derivative term.
759 : !
760 47320435 : 410 CALL update(n, npt, bmat, zmat, idz, ndim, vlag, beta, knew, w)
761 47320435 : fval(knew) = f
762 47320435 : ih = 0
763 141967174 : DO i = 1, n
764 94646739 : temp = pq(knew)*xpt(knew, i)
765 283952757 : DO j = 1, i
766 141985583 : ih = ih + 1
767 236632322 : hq(ih) = hq(ih) + temp*xpt(knew, j)
768 : END DO
769 : END DO
770 47320435 : pq(knew) = zero
771 : !
772 : ! Update the other second derivative parameters, and then the gradie
773 : ! vector of the model. Also include the new interpolation point.
774 : !
775 141967174 : DO j = 1, nptm
776 94646739 : temp = diff*zmat(knew, j)
777 94646739 : IF (j < idz) temp = -temp
778 615262767 : DO k = 1, npt
779 567942332 : pq(k) = pq(k) + temp*zmat(k, j)
780 : END DO
781 : END DO
782 47320435 : gqsq = zero
783 141967174 : DO i = 1, n
784 94646739 : gq(i) = gq(i) + diff*bmat(knew, i)
785 94646739 : gqsq = gqsq + gq(i)**2
786 141967174 : xpt(knew, i) = xnew(i)
787 : END DO
788 : !
789 : ! If a trust region step makes a small change to the objective funct
790 : ! then calculate the gradient of the least Frobenius norm interpolan
791 : ! XBASE, and store it in W, using VLAG for a vector of right hand si
792 : !
793 47320435 : IF (ksave == 0 .AND. delta == rho) THEN
794 6122248 : IF (ABS(ratio) > 1.0e-2_dp) THEN
795 4118161 : itest = 0
796 : ELSE
797 12024616 : DO k = 1, npt
798 12024616 : vlag(k) = fval(k) - fval(kopt)
799 : END DO
800 2004087 : gisq = zero
801 6012308 : DO i = 1, n
802 : sum = zero
803 24049840 : DO k = 1, npt
804 24049840 : sum = sum + bmat(k, i)*vlag(k)
805 : END DO
806 4008221 : gisq = gisq + sum*sum
807 6012308 : w(i) = sum
808 : END DO
809 : !
810 : ! Test whether to replace the new quadratic model by the least Frobe
811 : ! norm interpolant, making the replacement if the test is satisfied.
812 : !
813 2004087 : itest = itest + 1
814 2004087 : IF (gqsq < 1.0e2_dp*gisq) itest = 0
815 2004087 : IF (itest >= 3) THEN
816 346065 : DO i = 1, n
817 346065 : gq(i) = w(i)
818 : END DO
819 461420 : DO ih = 1, nh
820 461420 : hq(ih) = zero
821 : END DO
822 346065 : DO j = 1, nptm
823 230710 : w(j) = zero
824 1384260 : DO k = 1, npt
825 1384260 : w(j) = w(j) + vlag(k)*zmat(k, j)
826 : END DO
827 346065 : IF (j < idz) w(j) = -w(j)
828 : END DO
829 692130 : DO k = 1, npt
830 576775 : pq(k) = zero
831 1845680 : DO j = 1, nptm
832 1730325 : pq(k) = pq(k) + zmat(k, j)*w(j)
833 : END DO
834 : END DO
835 115355 : itest = 0
836 : END IF
837 : END IF
838 : END IF
839 47320435 : IF (f < fsave) kopt = knew
840 : !
841 : ! If a trust region step has provided a sufficient decrease in F, th
842 : ! branch for another trust region calculation. The case KSAVE>0 occu
843 : ! when the new function value was calculated by a model step.
844 : !
845 47320435 : IF (f <= fsave + tenth*vquad) GOTO 100
846 23751886 : IF (ksave > 0) GOTO 100
847 : !
848 : ! Alternatively, find out if the interpolation points are close enou
849 : ! to the best point so far.
850 : !
851 19920136 : knew = 0
852 19920136 : 460 distsq = 4.0_dp*delta*delta
853 119526128 : DO k = 1, npt
854 99605992 : sum = zero
855 298849188 : DO j = 1, n
856 298849188 : sum = sum + (xpt(k, j) - xopt(j))**2
857 : END DO
858 119526128 : IF (sum > distsq) THEN
859 27241559 : knew = k
860 27241559 : distsq = sum
861 : END IF
862 : END DO
863 : !
864 : ! If KNEW is positive, then set DSTEP, and branch back for the next
865 : ! iteration, which will generate a "model step".
866 : !
867 19920136 : IF (knew > 0) THEN
868 16860831 : dstep = MAX(MIN(tenth*SQRT(distsq), half*delta), rho)
869 16860831 : dsq = dstep*dstep
870 16860831 : GOTO 120
871 : END IF
872 3059305 : IF (ratio > zero) GOTO 100
873 2860706 : IF (MAX(delta, dnorm) > rho) GOTO 100
874 : !
875 : ! The calculations with the current value of RHO are complete. Pick
876 : ! next values of RHO and DELTA.
877 : !
878 4085541 : 490 IF (rho > rhoend) THEN
879 3404656 : delta = half*rho
880 3404656 : ratio = rho/rhoend
881 3404656 : IF (ratio <= 16.0_dp) THEN
882 680879 : rho = rhoend
883 2723777 : ELSE IF (ratio <= 250.0_dp) THEN
884 680879 : rho = SQRT(ratio)*rhoend
885 : ELSE
886 2042898 : rho = tenth*rho
887 : END IF
888 3404656 : delta = MAX(delta, rho)
889 3404656 : GOTO 90
890 : END IF
891 : !
892 : ! Return from the calculation, after another Newton-Raphson step, if
893 : ! it is too short to have been tried before.
894 : !
895 680885 : IF (knew == -1) GOTO 290
896 113163 : opt%state = 7
897 113163 : CALL get_state
898 680900 : 530 IF (fopt <= f) THEN
899 635599 : DO i = 1, n
900 635599 : x(i) = xbase(i) + xopt(i)
901 : END DO
902 211760 : f = fopt
903 : END IF
904 :
905 680900 : CALL get_state
906 :
907 : !******************************************************************************
908 : CONTAINS
909 : !******************************************************************************
910 : ! **************************************************************************************************
911 : !> \brief ...
912 : ! **************************************************************************************************
913 53055293 : SUBROUTINE get_state()
914 53055293 : opt%np = np
915 53055293 : opt%nh = nh
916 53055293 : opt%nptm = nptm
917 53055293 : opt%nftest = nftest
918 53055293 : opt%idz = idz
919 53055293 : opt%itest = itest
920 53055293 : opt%nf = nf
921 53055293 : opt%nfm = nfm
922 53055293 : opt%nfmm = nfmm
923 53055293 : opt%nfsav = nfsav
924 53055293 : opt%knew = knew
925 53055293 : opt%kopt = kopt
926 53055293 : opt%ksave = ksave
927 53055293 : opt%ktemp = ktemp
928 53055293 : opt%rhosq = rhosq
929 53055293 : opt%recip = recip
930 53055293 : opt%reciq = reciq
931 53055293 : opt%fbeg = fbeg
932 53055293 : opt%fopt = fopt
933 53055293 : opt%diffa = diffa
934 53055293 : opt%xoptsq = xoptsq
935 53055293 : opt%rho = rho
936 53055293 : opt%delta = delta
937 53055293 : opt%dsq = dsq
938 53055293 : opt%dnorm = dnorm
939 53055293 : opt%ratio = ratio
940 53055293 : opt%temp = temp
941 53055293 : opt%tempq = tempq
942 53055293 : opt%beta = beta
943 53055293 : opt%dx = dx
944 53055293 : opt%vquad = vquad
945 53055293 : opt%diff = diff
946 53055293 : opt%diffc = diffc
947 53055293 : opt%diffb = diffb
948 53055293 : opt%fsave = fsave
949 53055293 : opt%detrat = detrat
950 53055293 : opt%hdiag = hdiag
951 53055293 : opt%distsq = distsq
952 53055293 : opt%gisq = gisq
953 53055293 : opt%gqsq = gqsq
954 53055293 : opt%f = f
955 53055293 : opt%bstep = bstep
956 53055293 : opt%alpha = alpha
957 53055293 : opt%dstep = dstep
958 53055293 : END SUBROUTINE get_state
959 :
960 : !******************************************************************************
961 : ! **************************************************************************************************
962 : !> \brief ...
963 : ! **************************************************************************************************
964 51693493 : SUBROUTINE set_state()
965 51693493 : np = opt%np
966 51693493 : nh = opt%nh
967 51693493 : nptm = opt%nptm
968 51693493 : nftest = opt%nftest
969 51693493 : idz = opt%idz
970 51693493 : itest = opt%itest
971 51693493 : nf = opt%nf
972 51693493 : nfm = opt%nfm
973 51693493 : nfmm = opt%nfmm
974 51693493 : nfsav = opt%nfsav
975 51693493 : knew = opt%knew
976 51693493 : kopt = opt%kopt
977 51693493 : ksave = opt%ksave
978 51693493 : ktemp = opt%ktemp
979 51693493 : rhosq = opt%rhosq
980 51693493 : recip = opt%recip
981 51693493 : reciq = opt%reciq
982 51693493 : fbeg = opt%fbeg
983 51693493 : fopt = opt%fopt
984 51693493 : diffa = opt%diffa
985 51693493 : xoptsq = opt%xoptsq
986 51693493 : rho = opt%rho
987 51693493 : delta = opt%delta
988 51693493 : dsq = opt%dsq
989 51693493 : dnorm = opt%dnorm
990 51693493 : ratio = opt%ratio
991 51693493 : temp = opt%temp
992 51693493 : tempq = opt%tempq
993 51693493 : beta = opt%beta
994 51693493 : dx = opt%dx
995 51693493 : vquad = opt%vquad
996 51693493 : diff = opt%diff
997 51693493 : diffc = opt%diffc
998 51693493 : diffb = opt%diffb
999 51693493 : fsave = opt%fsave
1000 51693493 : detrat = opt%detrat
1001 51693493 : hdiag = opt%hdiag
1002 51693493 : distsq = opt%distsq
1003 51693493 : gisq = opt%gisq
1004 51693493 : gqsq = opt%gqsq
1005 51693493 : f = opt%f
1006 51693493 : bstep = opt%bstep
1007 51693493 : alpha = opt%alpha
1008 51693493 : dstep = opt%dstep
1009 51693493 : END SUBROUTINE set_state
1010 :
1011 : END SUBROUTINE newuob
1012 :
1013 : !******************************************************************************
1014 :
1015 : ! **************************************************************************************************
1016 : !> \brief ...
1017 : !> \param n ...
1018 : !> \param npt ...
1019 : !> \param xopt ...
1020 : !> \param xpt ...
1021 : !> \param bmat ...
1022 : !> \param zmat ...
1023 : !> \param idz ...
1024 : !> \param ndim ...
1025 : !> \param kopt ...
1026 : !> \param knew ...
1027 : !> \param d ...
1028 : !> \param w ...
1029 : !> \param vlag ...
1030 : !> \param beta ...
1031 : !> \param s ...
1032 : !> \param wvec ...
1033 : !> \param prod ...
1034 : ! **************************************************************************************************
1035 110 : SUBROUTINE bigden(n, npt, xopt, xpt, bmat, zmat, idz, ndim, kopt, &
1036 110 : knew, d, w, vlag, beta, s, wvec, prod)
1037 :
1038 : INTEGER, INTENT(in) :: n, npt
1039 : REAL(dp), DIMENSION(*), INTENT(in) :: xopt
1040 : REAL(dp), DIMENSION(npt, *), INTENT(in) :: xpt
1041 : INTEGER, INTENT(in) :: ndim, idz
1042 : REAL(dp), DIMENSION(npt, *), INTENT(inout) :: zmat
1043 : REAL(dp), DIMENSION(ndim, *), INTENT(inout) :: bmat
1044 : INTEGER, INTENT(inout) :: kopt, knew
1045 : REAL(dp), DIMENSION(*), INTENT(inout) :: d, w, vlag
1046 : REAL(dp), INTENT(inout) :: beta
1047 : REAL(dp), DIMENSION(*), INTENT(inout) :: s
1048 : REAL(dp), DIMENSION(ndim, *), INTENT(inout) :: wvec, prod
1049 :
1050 : REAL(dp), PARAMETER :: half = 0.5_dp, one = 1._dp, &
1051 : quart = 0.25_dp, two = 2._dp, &
1052 : zero = 0._dp
1053 :
1054 : INTEGER :: i, ip, isave, iterc, iu, j, jc, k, ksav, &
1055 : nptm, nw
1056 : REAL(dp) :: alpha, angle, dd, denmax, denold, densav, diff, ds, dstemp, dtest, ss, ssden, &
1057 : sstemp, step, sum, sumold, tau, temp, tempa, tempb, tempc, xoptd, xopts, xoptsq
1058 : REAL(dp), DIMENSION(9) :: den, denex, par
1059 :
1060 : !
1061 : ! N is the number of variables.
1062 : ! NPT is the number of interpolation equations.
1063 : ! XOPT is the best interpolation point so far.
1064 : ! XPT contains the coordinates of the current interpolation points.
1065 : ! BMAT provides the last N columns of H.
1066 : ! ZMAT and IDZ give a factorization of the first NPT by NPT submatri
1067 : ! NDIM is the first dimension of BMAT and has the value NPT+N.
1068 : ! KOPT is the index of the optimal interpolation point.
1069 : ! KNEW is the index of the interpolation point that is going to be m
1070 : ! D will be set to the step from XOPT to the new point, and on entry
1071 : ! should be the D that was calculated by the last call of BIGLAG.
1072 : ! length of the initial D provides a trust region bound on the fin
1073 : ! W will be set to Wcheck for the final choice of D.
1074 : ! VLAG will be set to Theta*Wcheck+e_b for the final choice of D.
1075 : ! BETA will be set to the value that will occur in the updating form
1076 : ! when the KNEW-th interpolation point is moved to its new positio
1077 : ! S, WVEC, PROD and the private arrays DEN, DENEX and PAR will be us
1078 : ! for working space.
1079 : !
1080 : ! D is calculated in a way that should provide a denominator with a
1081 : ! modulus in the updating formula when the KNEW-th interpolation poi
1082 : ! shifted to the new position XOPT+D.
1083 : !
1084 :
1085 110 : nptm = npt - n - 1
1086 : !
1087 : ! Store the first NPT elements of the KNEW-th column of H in W(N+1)
1088 : ! to W(N+NPT).
1089 : !
1090 660 : DO k = 1, npt
1091 660 : w(n + k) = zero
1092 : END DO
1093 330 : DO j = 1, nptm
1094 220 : temp = zmat(knew, j)
1095 220 : IF (j < idz) temp = -temp
1096 1430 : DO k = 1, npt
1097 1320 : w(n + k) = w(n + k) + temp*zmat(k, j)
1098 : END DO
1099 : END DO
1100 110 : alpha = w(n + knew)
1101 : !
1102 : ! The initial search direction D is taken from the last call of BIGL
1103 : ! and the initial S is set below, usually to the direction from X_OP
1104 : ! to X_KNEW, but a different direction to an interpolation point may
1105 : ! be chosen, in order to prevent S from being nearly parallel to D.
1106 : !
1107 110 : dd = zero
1108 110 : ds = zero
1109 110 : ss = zero
1110 110 : xoptsq = zero
1111 330 : DO i = 1, n
1112 220 : dd = dd + d(i)**2
1113 220 : s(i) = xpt(knew, i) - xopt(i)
1114 220 : ds = ds + d(i)*s(i)
1115 220 : ss = ss + s(i)**2
1116 330 : xoptsq = xoptsq + xopt(i)**2
1117 : END DO
1118 110 : IF (ds*ds > 0.99_dp*dd*ss) THEN
1119 0 : ksav = knew
1120 0 : dtest = ds*ds/ss
1121 0 : DO k = 1, npt
1122 0 : IF (k /= kopt) THEN
1123 : dstemp = zero
1124 : sstemp = zero
1125 0 : DO i = 1, n
1126 0 : diff = xpt(k, i) - xopt(i)
1127 0 : dstemp = dstemp + d(i)*diff
1128 0 : sstemp = sstemp + diff*diff
1129 : END DO
1130 0 : IF (dstemp*dstemp/sstemp < dtest) THEN
1131 0 : ksav = k
1132 0 : dtest = dstemp*dstemp/sstemp
1133 0 : ds = dstemp
1134 0 : ss = sstemp
1135 : END IF
1136 : END IF
1137 : END DO
1138 0 : DO i = 1, n
1139 0 : s(i) = xpt(ksav, i) - xopt(i)
1140 : END DO
1141 : END IF
1142 110 : ssden = dd*ss - ds*ds
1143 110 : iterc = 0
1144 110 : densav = zero
1145 : !
1146 : ! Begin the iteration by overwriting S with a vector that has the
1147 : ! required length and direction.
1148 : !
1149 : mainloop: DO
1150 176 : iterc = iterc + 1
1151 176 : temp = one/SQRT(ssden)
1152 176 : xoptd = zero
1153 176 : xopts = zero
1154 528 : DO i = 1, n
1155 352 : s(i) = temp*(dd*s(i) - ds*d(i))
1156 352 : xoptd = xoptd + xopt(i)*d(i)
1157 528 : xopts = xopts + xopt(i)*s(i)
1158 : END DO
1159 : !
1160 : ! Set the coefficients of the first two terms of BETA.
1161 : !
1162 176 : tempa = half*xoptd*xoptd
1163 176 : tempb = half*xopts*xopts
1164 176 : den(1) = dd*(xoptsq + half*dd) + tempa + tempb
1165 176 : den(2) = two*xoptd*dd
1166 176 : den(3) = two*xopts*dd
1167 176 : den(4) = tempa - tempb
1168 176 : den(5) = xoptd*xopts
1169 880 : DO i = 6, 9
1170 880 : den(i) = zero
1171 : END DO
1172 : !
1173 : ! Put the coefficients of Wcheck in WVEC.
1174 : !
1175 1056 : DO k = 1, npt
1176 : tempa = zero
1177 : tempb = zero
1178 : tempc = zero
1179 2640 : DO i = 1, n
1180 1760 : tempa = tempa + xpt(k, i)*d(i)
1181 1760 : tempb = tempb + xpt(k, i)*s(i)
1182 2640 : tempc = tempc + xpt(k, i)*xopt(i)
1183 : END DO
1184 880 : wvec(k, 1) = quart*(tempa*tempa + tempb*tempb)
1185 880 : wvec(k, 2) = tempa*tempc
1186 880 : wvec(k, 3) = tempb*tempc
1187 880 : wvec(k, 4) = quart*(tempa*tempa - tempb*tempb)
1188 1056 : wvec(k, 5) = half*tempa*tempb
1189 : END DO
1190 528 : DO i = 1, n
1191 352 : ip = i + npt
1192 352 : wvec(ip, 1) = zero
1193 352 : wvec(ip, 2) = d(i)
1194 352 : wvec(ip, 3) = s(i)
1195 352 : wvec(ip, 4) = zero
1196 528 : wvec(ip, 5) = zero
1197 : END DO
1198 : !
1199 : ! Put the coefficients of THETA*Wcheck in PROD.
1200 : !
1201 1056 : DO jc = 1, 5
1202 880 : nw = npt
1203 880 : IF (jc == 2 .OR. jc == 3) nw = ndim
1204 5280 : DO k = 1, npt
1205 5280 : prod(k, jc) = zero
1206 : END DO
1207 2640 : DO j = 1, nptm
1208 : sum = zero
1209 10560 : DO k = 1, npt
1210 10560 : sum = sum + zmat(k, j)*wvec(k, jc)
1211 : END DO
1212 1760 : IF (j < idz) sum = -sum
1213 11440 : DO k = 1, npt
1214 10560 : prod(k, jc) = prod(k, jc) + sum*zmat(k, j)
1215 : END DO
1216 : END DO
1217 880 : IF (nw == ndim) THEN
1218 2112 : DO k = 1, npt
1219 : sum = zero
1220 5280 : DO j = 1, n
1221 5280 : sum = sum + bmat(k, j)*wvec(npt + j, jc)
1222 : END DO
1223 2112 : prod(k, jc) = prod(k, jc) + sum
1224 : END DO
1225 : END IF
1226 2816 : DO j = 1, n
1227 : sum = zero
1228 11968 : DO i = 1, nw
1229 11968 : sum = sum + bmat(i, j)*wvec(i, jc)
1230 : END DO
1231 2640 : prod(npt + j, jc) = sum
1232 : END DO
1233 : END DO
1234 : !
1235 : ! Include in DEN the part of BETA that depends on THETA.
1236 : !
1237 1408 : DO k = 1, ndim
1238 : sum = zero
1239 7392 : DO I = 1, 5
1240 6160 : par(i) = half*prod(k, i)*wvec(k, i)
1241 7392 : sum = sum + par(i)
1242 : END DO
1243 1232 : den(1) = den(1) - par(1) - sum
1244 1232 : tempa = prod(k, 1)*wvec(k, 2) + prod(k, 2)*wvec(k, 1)
1245 1232 : tempb = prod(k, 2)*wvec(k, 4) + prod(k, 4)*wvec(k, 2)
1246 1232 : tempc = prod(k, 3)*wvec(k, 5) + prod(k, 5)*wvec(k, 3)
1247 1232 : den(2) = den(2) - tempa - half*(tempb + tempc)
1248 1232 : den(6) = den(6) - half*(tempb - tempc)
1249 1232 : tempa = prod(k, 1)*wvec(k, 3) + prod(k, 3)*wvec(k, 1)
1250 1232 : tempb = prod(k, 2)*wvec(k, 5) + prod(k, 5)*wvec(k, 2)
1251 1232 : tempc = prod(k, 3)*wvec(k, 4) + prod(k, 4)*wvec(k, 3)
1252 1232 : den(3) = den(3) - tempa - half*(tempb - tempc)
1253 1232 : den(7) = den(7) - half*(tempb + tempc)
1254 1232 : tempa = prod(k, 1)*wvec(k, 4) + prod(k, 4)*wvec(k, 1)
1255 1232 : den(4) = den(4) - tempa - par(2) + par(3)
1256 1232 : tempa = prod(k, 1)*wvec(k, 5) + prod(k, 5)*wvec(k, 1)
1257 1232 : tempb = prod(k, 2)*wvec(k, 3) + prod(k, 3)*wvec(k, 2)
1258 1232 : den(5) = den(5) - tempa - half*tempb
1259 1232 : den(8) = den(8) - par(4) + par(5)
1260 1232 : tempa = prod(k, 4)*wvec(k, 5) + prod(k, 5)*wvec(k, 4)
1261 1408 : den(9) = den(9) - half*tempa
1262 : END DO
1263 : !
1264 : ! Extend DEN so that it holds all the coefficients of DENOM.
1265 : !
1266 : sum = zero
1267 1056 : DO i = 1, 5
1268 880 : par(i) = half*prod(knew, i)**2
1269 1056 : sum = sum + par(i)
1270 : END DO
1271 176 : denex(1) = alpha*den(1) + par(1) + sum
1272 176 : tempa = two*prod(knew, 1)*prod(knew, 2)
1273 176 : tempb = prod(knew, 2)*prod(knew, 4)
1274 176 : tempc = prod(knew, 3)*prod(knew, 5)
1275 176 : denex(2) = alpha*den(2) + tempa + tempb + tempc
1276 176 : denex(6) = alpha*den(6) + tempb - tempc
1277 176 : tempa = two*prod(knew, 1)*prod(knew, 3)
1278 176 : tempb = prod(knew, 2)*prod(knew, 5)
1279 176 : tempc = prod(knew, 3)*prod(knew, 4)
1280 176 : denex(3) = alpha*den(3) + tempa + tempb - tempc
1281 176 : denex(7) = alpha*den(7) + tempb + tempc
1282 176 : tempa = two*prod(knew, 1)*prod(knew, 4)
1283 176 : denex(4) = alpha*den(4) + tempa + par(2) - par(3)
1284 176 : tempa = two*prod(knew, 1)*prod(knew, 5)
1285 176 : denex(5) = alpha*den(5) + tempa + prod(knew, 2)*prod(knew, 3)
1286 176 : denex(8) = alpha*den(8) + par(4) - par(5)
1287 176 : denex(9) = alpha*den(9) + prod(knew, 4)*prod(knew, 5)
1288 : !
1289 : ! Seek the value of the angle that maximizes the modulus of DENOM.
1290 : !
1291 176 : sum = denex(1) + denex(2) + denex(4) + denex(6) + denex(8)
1292 176 : denold = sum
1293 176 : denmax = sum
1294 176 : isave = 0
1295 176 : iu = 49
1296 176 : temp = twopi/REAL(IU + 1, dp)
1297 176 : par(1) = one
1298 8800 : DO i = 1, iu
1299 8624 : angle = REAL(i, dp)*temp
1300 8624 : par(2) = COS(angle)
1301 8624 : par(3) = SIN(angle)
1302 8624 : DO j = 4, 8, 2
1303 25872 : par(j) = par(2)*par(j - 2) - par(3)*par(j - 1)
1304 25872 : par(j + 1) = par(2)*par(j - 1) + par(3)*par(j - 2)
1305 : END DO
1306 : sumold = sum
1307 : sum = zero
1308 86240 : DO j = 1, 9
1309 86240 : sum = sum + denex(j)*par(j)
1310 : END DO
1311 8800 : IF (ABS(sum) > ABS(denmax)) THEN
1312 : denmax = sum
1313 : isave = i
1314 : tempa = sumold
1315 8036 : ELSE IF (i == isave + 1) THEN
1316 318 : tempb = sum
1317 : END IF
1318 : END DO
1319 176 : IF (isave == 0) tempa = sum
1320 86 : IF (isave == iu) tempb = denold
1321 176 : step = zero
1322 176 : IF (tempa /= tempb) THEN
1323 176 : tempa = tempa - denmax
1324 176 : tempb = tempb - denmax
1325 176 : step = half*(tempa - tempb)/(tempa + tempb)
1326 : END IF
1327 176 : angle = temp*(REAL(isave, dp) + step)
1328 : !
1329 : ! Calculate the new parameters of the denominator, the new VLAG vect
1330 : ! and the new D. Then test for convergence.
1331 : !
1332 176 : par(2) = COS(angle)
1333 176 : par(3) = SIN(angle)
1334 176 : DO j = 4, 8, 2
1335 528 : par(j) = par(2)*par(j - 2) - par(3)*par(j - 1)
1336 528 : par(j + 1) = par(2)*par(j - 1) + par(3)*par(j - 2)
1337 : END DO
1338 176 : beta = zero
1339 176 : denmax = zero
1340 1760 : DO j = 1, 9
1341 1584 : beta = beta + den(j)*par(j)
1342 1760 : denmax = denmax + denex(j)*par(j)
1343 : END DO
1344 1408 : DO k = 1, ndim
1345 1232 : vlag(k) = zero
1346 7568 : DO j = 1, 5
1347 7392 : vlag(k) = vlag(k) + prod(k, j)*par(j)
1348 : END DO
1349 : END DO
1350 176 : tau = vlag(knew)
1351 176 : dd = zero
1352 176 : tempa = zero
1353 176 : tempb = zero
1354 528 : DO i = 1, n
1355 352 : d(i) = par(2)*d(i) + par(3)*s(i)
1356 352 : w(i) = xopt(i) + d(i)
1357 352 : dd = dd + d(i)**2
1358 352 : tempa = tempa + d(i)*w(i)
1359 528 : tempb = tempb + w(i)*w(i)
1360 : END DO
1361 176 : IF (iterc >= n) EXIT mainloop
1362 110 : IF (iterc >= 1) densav = MAX(densav, denold)
1363 110 : IF (ABS(denmax) <= 1.1_dp*ABS(densav)) EXIT mainloop
1364 198 : densav = denmax
1365 : !
1366 : ! Set S to half the gradient of the denominator with respect to D.
1367 : ! Then branch for the next iteration.
1368 : !
1369 198 : DO i = 1, n
1370 132 : temp = tempa*xopt(i) + tempb*d(i) - vlag(npt + i)
1371 198 : s(i) = tau*bmat(knew, i) + alpha*temp
1372 : END DO
1373 396 : DO k = 1, npt
1374 : sum = zero
1375 990 : DO j = 1, n
1376 990 : sum = sum + xpt(k, j)*w(j)
1377 : END DO
1378 330 : temp = (tau*w(n + k) - alpha*vlag(k))*sum
1379 1056 : DO i = 1, n
1380 990 : s(i) = s(i) + temp*xpt(k, i)
1381 : END DO
1382 : END DO
1383 : ss = zero
1384 : ds = zero
1385 198 : DO i = 1, n
1386 132 : ss = ss + s(i)**2
1387 198 : ds = ds + d(i)*s(i)
1388 : END DO
1389 66 : ssden = dd*ss - ds*ds
1390 176 : IF (ssden < 1.0e-8_dp*dd*ss) EXIT mainloop
1391 : END DO mainloop
1392 : !
1393 : ! Set the vector W before the RETURN from the subroutine.
1394 : !
1395 880 : DO k = 1, ndim
1396 770 : w(k) = zero
1397 4730 : DO j = 1, 5
1398 4620 : w(k) = w(k) + wvec(k, j)*par(j)
1399 : END DO
1400 : END DO
1401 110 : vlag(kopt) = vlag(kopt) + one
1402 :
1403 110 : END SUBROUTINE bigden
1404 : !******************************************************************************
1405 :
1406 : ! **************************************************************************************************
1407 : !> \brief ...
1408 : !> \param n ...
1409 : !> \param npt ...
1410 : !> \param xopt ...
1411 : !> \param xpt ...
1412 : !> \param bmat ...
1413 : !> \param zmat ...
1414 : !> \param idz ...
1415 : !> \param ndim ...
1416 : !> \param knew ...
1417 : !> \param delta ...
1418 : !> \param d ...
1419 : !> \param alpha ...
1420 : !> \param hcol ...
1421 : !> \param gc ...
1422 : !> \param gd ...
1423 : !> \param s ...
1424 : !> \param w ...
1425 : ! **************************************************************************************************
1426 16860831 : SUBROUTINE biglag(n, npt, xopt, xpt, bmat, zmat, idz, ndim, knew, &
1427 : delta, d, alpha, hcol, gc, gd, s, w)
1428 : INTEGER, INTENT(in) :: n, npt
1429 : REAL(dp), DIMENSION(*), INTENT(in) :: xopt
1430 : REAL(dp), DIMENSION(npt, *), INTENT(in) :: xpt
1431 : INTEGER, INTENT(in) :: ndim, idz
1432 : REAL(dp), DIMENSION(npt, *), INTENT(inout) :: zmat
1433 : REAL(dp), DIMENSION(ndim, *), INTENT(inout) :: bmat
1434 : INTEGER, INTENT(inout) :: knew
1435 : REAL(dp), INTENT(inout) :: delta
1436 : REAL(dp), DIMENSION(*), INTENT(inout) :: d
1437 : REAL(dp), INTENT(inout) :: alpha
1438 : REAL(dp), DIMENSION(*), INTENT(inout) :: hcol, gc, gd, s, w
1439 :
1440 : REAL(dp), PARAMETER :: half = 0.5_dp, one = 1._dp, zero = 0._dp
1441 :
1442 : INTEGER :: i, isave, iterc, iu, j, k, nptm
1443 : REAL(dp) :: angle, cf1, cf2, cf3, cf4, cf5, cth, dd, &
1444 : delsq, denom, dhd, gg, scale, sp, ss, &
1445 : step, sth, sum, tau, taubeg, taumax, &
1446 : tauold, temp, tempa, tempb
1447 :
1448 : !
1449 : !
1450 : ! N is the number of variables.
1451 : ! NPT is the number of interpolation equations.
1452 : ! XOPT is the best interpolation point so far.
1453 : ! XPT contains the coordinates of the current interpolation points.
1454 : ! BMAT provides the last N columns of H.
1455 : ! ZMAT and IDZ give a factorization of the first NPT by NPT submatrix
1456 : ! NDIM is the first dimension of BMAT and has the value NPT+N.
1457 : ! KNEW is the index of the interpolation point that is going to be m
1458 : ! DELTA is the current trust region bound.
1459 : ! D will be set to the step from XOPT to the new point.
1460 : ! ALPHA will be set to the KNEW-th diagonal element of the H matrix.
1461 : ! HCOL, GC, GD, S and W will be used for working space.
1462 : !
1463 : ! The step D is calculated in a way that attempts to maximize the mo
1464 : ! of LFUNC(XOPT+D), subject to the bound ||D|| .LE. DELTA, where LFU
1465 : ! the KNEW-th Lagrange function.
1466 : !
1467 :
1468 16860831 : delsq = delta*delta
1469 16860831 : nptm = npt - n - 1
1470 : !
1471 : ! Set the first NPT components of HCOL to the leading elements of th
1472 : ! KNEW-th column of H.
1473 : !
1474 16860831 : iterc = 0
1475 101169686 : DO k = 1, npt
1476 101169686 : hcol(k) = zero
1477 : END DO
1478 50584843 : DO j = 1, nptm
1479 33724012 : temp = zmat(knew, j)
1480 33724012 : IF (j < idz) temp = -temp
1481 219229931 : DO k = 1, npt
1482 202369100 : hcol(k) = hcol(k) + temp*zmat(k, j)
1483 : END DO
1484 : END DO
1485 16860831 : alpha = hcol(knew)
1486 : !
1487 : ! Set the unscaled initial direction D. Form the gradient of LFUNC a
1488 : ! XOPT, and multiply D by the second derivative matrix of LFUNC.
1489 : !
1490 16860831 : dd = zero
1491 50584843 : DO i = 1, n
1492 33724012 : d(i) = xpt(knew, i) - xopt(i)
1493 33724012 : gc(i) = bmat(knew, i)
1494 33724012 : gd(i) = zero
1495 50584843 : dd = dd + d(i)**2
1496 : END DO
1497 101169686 : DO k = 1, npt
1498 : temp = zero
1499 : sum = zero
1500 252953943 : DO j = 1, n
1501 168645088 : temp = temp + xpt(k, j)*xopt(j)
1502 252953943 : sum = sum + xpt(k, j)*d(j)
1503 : END DO
1504 84308855 : temp = hcol(k)*temp
1505 84308855 : sum = hcol(k)*sum
1506 269814774 : DO i = 1, n
1507 168645088 : gc(i) = gc(i) + temp*xpt(k, i)
1508 252953943 : gd(i) = gd(i) + sum*xpt(k, i)
1509 : END DO
1510 : END DO
1511 : !
1512 : ! Scale D and GD, with a sign change if required. Set S to another
1513 : ! vector in the initial two dimensional subspace.
1514 : !
1515 : gg = zero
1516 : sp = zero
1517 : dhd = zero
1518 50584843 : DO i = 1, n
1519 33724012 : gg = gg + gc(i)**2
1520 33724012 : sp = sp + d(i)*gc(i)
1521 50584843 : dhd = dhd + d(i)*gd(i)
1522 : END DO
1523 16860831 : scale = delta/SQRT(dd)
1524 16860831 : IF (sp*dhd < zero) scale = -scale
1525 16860831 : temp = zero
1526 16860831 : IF (sp*sp > 0.99_dp*dd*gg) temp = one
1527 16860831 : tau = scale*(ABS(sp) + half*scale*ABS(dhd))
1528 16860831 : IF (gg*delsq < 0.01_dp*tau*tau) temp = one
1529 50584843 : DO i = 1, n
1530 33724012 : d(i) = scale*d(i)
1531 33724012 : gd(i) = scale*gd(i)
1532 50584843 : s(i) = gc(i) + temp*gd(i)
1533 : END DO
1534 : !
1535 : ! Begin the iteration by overwriting S with a vector that has the
1536 : ! required length and direction, except that termination occurs if
1537 : ! the given D and S are nearly parallel.
1538 : !
1539 : mainloop: DO
1540 23880240 : iterc = iterc + 1
1541 23880240 : dd = zero
1542 23880240 : sp = zero
1543 23880240 : ss = zero
1544 71644498 : DO i = 1, n
1545 47764258 : dd = dd + d(i)**2
1546 47764258 : sp = sp + d(i)*s(i)
1547 71644498 : ss = ss + s(i)**2
1548 : END DO
1549 23880240 : temp = dd*ss - sp*sp
1550 23880240 : IF (temp <= 1.0e-8_dp*dd*ss) EXIT mainloop
1551 22831289 : denom = SQRT(temp)
1552 68497369 : DO i = 1, n
1553 45666080 : s(i) = (dd*s(i) - sp*d(i))/denom
1554 68497369 : w(i) = zero
1555 : END DO
1556 : !
1557 : ! Calculate the coefficients of the objective function on the circle
1558 : ! beginning with the multiplication of S by the second derivative ma
1559 : !
1560 136994738 : DO k = 1, npt
1561 : sum = zero
1562 342531277 : DO j = 1, n
1563 342531277 : sum = sum + xpt(k, j)*s(j)
1564 : END DO
1565 114163449 : sum = hcol(k)*sum
1566 365362566 : DO i = 1, n
1567 342531277 : w(i) = w(i) + sum*xpt(k, i)
1568 : END DO
1569 : END DO
1570 : cf1 = zero
1571 : cf2 = zero
1572 : cf3 = zero
1573 : cf4 = zero
1574 : cf5 = zero
1575 68497369 : DO i = 1, n
1576 45666080 : cf1 = cf1 + s(i)*w(i)
1577 45666080 : cf2 = cf2 + d(i)*gc(i)
1578 45666080 : cf3 = cf3 + s(i)*gc(i)
1579 45666080 : cf4 = cf4 + d(i)*gd(i)
1580 68497369 : cf5 = cf5 + s(i)*gd(i)
1581 : END DO
1582 22831289 : cf1 = half*cf1
1583 22831289 : cf4 = half*cf4 - cf1
1584 : !
1585 : ! Seek the value of the angle that maximizes the modulus of TAU.
1586 : !
1587 22831289 : taubeg = cf1 + cf2 + cf4
1588 22831289 : taumax = taubeg
1589 22831289 : tauold = taubeg
1590 22831289 : isave = 0
1591 22831289 : iu = 49
1592 22831289 : temp = twopi/REAL(iu + 1, DP)
1593 1141564450 : DO i = 1, iu
1594 1118733161 : angle = REAL(i, dp)*temp
1595 1118733161 : cth = COS(angle)
1596 1118733161 : sth = SIN(angle)
1597 1118733161 : tau = cf1 + (cf2 + cf4*cth)*cth + (cf3 + cf5*cth)*sth
1598 1118733161 : IF (ABS(tau) > ABS(taumax)) THEN
1599 : taumax = tau
1600 : isave = i
1601 : tempa = tauold
1602 1060229768 : ELSE IF (i == isave + 1) THEN
1603 24828557 : tempb = taU
1604 : END IF
1605 1141564450 : tauold = tau
1606 : END DO
1607 22831289 : IF (isave == 0) tempa = tau
1608 13421191 : IF (isave == iu) tempb = taubeg
1609 22831289 : step = zero
1610 22831289 : IF (tempa /= tempb) THEN
1611 22831289 : tempa = tempa - taumax
1612 22831289 : tempb = tempb - taumax
1613 22831289 : step = half*(tempa - tempb)/(tempa + tempb)
1614 : END IF
1615 22831289 : angle = temp*(REAL(isave, DP) + step)
1616 : !
1617 : ! Calculate the new D and GD. Then test for convergence.
1618 : !
1619 22831289 : cth = COS(angle)
1620 22831289 : sth = SIN(angle)
1621 22831289 : tau = cf1 + (cf2 + cf4*cth)*cth + (cf3 + cf5*cth)*sth
1622 68497369 : DO i = 1, n
1623 45666080 : d(i) = cth*d(i) + sth*s(i)
1624 45666080 : gd(i) = cth*gd(i) + sth*w(i)
1625 68497369 : s(i) = gc(i) + gd(i)
1626 : END DO
1627 22831289 : IF (ABS(tau) <= 1.1_dp*ABS(taubeg)) EXIT mainloop
1628 23880240 : IF (iterc >= n) EXIT mainloop
1629 : END DO mainloop
1630 :
1631 16860831 : END SUBROUTINE biglag
1632 : !******************************************************************************
1633 :
1634 : ! **************************************************************************************************
1635 : !> \brief ...
1636 : !> \param n ...
1637 : !> \param npt ...
1638 : !> \param xopt ...
1639 : !> \param xpt ...
1640 : !> \param gq ...
1641 : !> \param hq ...
1642 : !> \param pq ...
1643 : !> \param delta ...
1644 : !> \param step ...
1645 : !> \param d ...
1646 : !> \param g ...
1647 : !> \param hd ...
1648 : !> \param hs ...
1649 : !> \param crvmin ...
1650 : ! **************************************************************************************************
1651 40797062 : SUBROUTINE trsapp(n, npt, xopt, xpt, gq, hq, pq, delta, step, d, g, hd, hs, crvmin)
1652 :
1653 : INTEGER, INTENT(IN) :: n, npt
1654 : REAL(dp), DIMENSION(*), INTENT(IN) :: xopt
1655 : REAL(dp), DIMENSION(npt, *), &
1656 : INTENT(IN) :: xpt
1657 : REAL(dp), DIMENSION(*), INTENT(INOUT) :: gq, hq, pq
1658 : REAL(dp), INTENT(IN) :: delta
1659 : REAL(dp), DIMENSION(*), INTENT(INOUT) :: step, d, g, hd, hs
1660 : REAL(dp), INTENT(INOUT) :: crvmin
1661 :
1662 : REAL(dp), PARAMETER :: half = 0.5_dp, zero = 0.0_dp
1663 :
1664 : INTEGER :: i, isave, iterc, itermax, &
1665 : itersw, iu, j
1666 : LOGICAL :: jump1, jump2
1667 : REAL(dp) :: alpha, angle, angtest, bstep, cf, cth, dd, delsq, dg, dhd, &
1668 : dhs, ds, gg, ggbeg, ggsav, qadd, qbeg, qmin, qnew, qred, qsav, ratio, &
1669 : reduc, sg, sgk, shs, ss, sth, temp, tempa, tempb
1670 :
1671 : !
1672 : ! N is the number of variables of a quadratic objective function, Q
1673 : ! The arguments NPT, XOPT, XPT, GQ, HQ and PQ have their usual meani
1674 : ! in order to define the current quadratic model Q.
1675 : ! DELTA is the trust region radius, and has to be positive.
1676 : ! STEP will be set to the calculated trial step.
1677 : ! The arrays D, G, HD and HS will be used for working space.
1678 : ! CRVMIN will be set to the least curvature of H along the conjugate
1679 : ! directions that occur, except that it is set to zero if STEP goe
1680 : ! all the way to the trust region boundary.
1681 : !
1682 : ! The calculation of STEP begins with the truncated conjugate gradient
1683 : ! method. If the boundary of the trust region is reached, then further
1684 : ! changes to STEP may be made, each one being in the 2D space spanned
1685 : ! by the current STEP and the corresponding gradient of Q. Thus STEP
1686 : ! should provide a substantial reduction to Q within the trust region
1687 : !
1688 : ! Initialization, which includes setting HD to H times XOPT.
1689 : !
1690 :
1691 40797062 : delsq = delta*delta
1692 40797062 : iterc = 0
1693 40797062 : itermax = n
1694 40797062 : itersw = itermax
1695 122395513 : DO i = 1, n
1696 122395513 : d(i) = xopt(i)
1697 : END DO
1698 40797062 : CALL updatehd
1699 : !
1700 : ! Prepare for the first line search.
1701 : !
1702 40797062 : qred = zero
1703 40797062 : dd = zero
1704 122395513 : DO i = 1, n
1705 81598451 : step(i) = zero
1706 81598451 : hs(i) = zero
1707 81598451 : g(i) = gq(i) + hd(i)
1708 81598451 : d(i) = -g(i)
1709 122395513 : dd = dd + d(i)**2
1710 : END DO
1711 40797062 : crvmin = zero
1712 40797062 : IF (dd == zero) RETURN
1713 : ds = zero
1714 : ss = zero
1715 : gg = dd
1716 : ggbeg = gg
1717 : !
1718 : ! Calculate the step to the trust region boundary and the product HD
1719 : !
1720 : jump1 = .FALSE.
1721 : jump2 = .FALSE.
1722 : mainloop: DO
1723 68823859 : IF (.NOT. jump2) THEN
1724 68822973 : IF (.NOT. jump1) THEN
1725 68822973 : iterc = iterc + 1
1726 68822973 : temp = delsq - ss
1727 68822973 : bstep = temp/(ds + SQRT(ds*ds + dd*temp))
1728 68822973 : CALL updatehd
1729 : END IF
1730 68822973 : jump1 = .FALSE.
1731 68822973 : IF (iterc <= itersw) THEN
1732 68822973 : dhd = zero
1733 206481961 : DO j = 1, n
1734 206481961 : dhd = dhd + d(j)*hd(j)
1735 : END DO
1736 : !
1737 : ! Update CRVMIN and set the step-length ALPHA.
1738 : !
1739 68822973 : alpha = bstep
1740 68822973 : IF (dhd > zero) THEN
1741 60831621 : temp = dhd/dd
1742 60831621 : IF (iterc == 1) crvmin = temp
1743 60831621 : crvmin = MIN(crvmin, temp)
1744 60831621 : alpha = MIN(alpha, gg/dhd)
1745 : END IF
1746 68822973 : qadd = alpha*(gg - half*alpha*dhd)
1747 68822973 : qred = qred + qadd
1748 : !
1749 : ! Update STEP and HS.
1750 : !
1751 68822973 : ggsav = gg
1752 68822973 : gg = zero
1753 206481961 : DO i = 1, n
1754 137658988 : step(i) = step(i) + alpha*d(i)
1755 137658988 : hs(i) = hs(i) + alpha*hd(i)
1756 206481961 : gg = gg + (g(i) + hs(i))**2
1757 : END DO
1758 : !
1759 : ! Begin another conjugate direction iteration if required.
1760 : !
1761 68822973 : IF (alpha < bstep) THEN
1762 45217315 : IF (qadd <= 0.01_dp*qred) EXIT mainloop
1763 44536873 : IF (gg <= 1.0e-4_dp*ggbeg) EXIT mainloop
1764 28026124 : IF (iterc == itermax) EXIT mainloop
1765 28026064 : temp = gg/ggsav
1766 28026064 : dd = zero
1767 28026064 : ds = zero
1768 28026064 : ss = zero
1769 84087238 : DO i = 1, n
1770 56061174 : d(i) = temp*d(i) - g(i) - hs(i)
1771 56061174 : dd = dd + d(i)**2
1772 56061174 : ds = ds + d(i)*step(I)
1773 84087238 : ss = ss + step(i)**2
1774 : END DO
1775 28026064 : IF (ds <= zero) EXIT mainloop
1776 28026064 : IF (ss < delsq) CYCLE mainloop
1777 : END IF
1778 23605658 : crvmin = zero
1779 23605658 : itersw = iterc
1780 23605658 : jump2 = .TRUE.
1781 23605658 : IF (gg <= 1.0e-4_dp*ggbeg) EXIT mainloop
1782 : ELSE
1783 : jump2 = .FALSE.
1784 : END IF
1785 : END IF
1786 : !
1787 : ! Test whether an alternative iteration is required.
1788 : !
1789 : !!!! IF (gg <= 1.0e-4_dp*ggbeg) EXIT mainloop
1790 23254503 : IF (jump2) THEN
1791 23254503 : sg = zero
1792 23254503 : shs = zero
1793 69769442 : DO i = 1, n
1794 46514939 : sg = sg + step(i)*g(i)
1795 69769442 : shs = shs + step(i)*hs(i)
1796 : END DO
1797 23254503 : sgk = sg + shs
1798 23254503 : angtest = sgk/SQRT(gg*delsq)
1799 23254503 : IF (angtest <= -0.99_dp) EXIT mainloop
1800 : !
1801 : ! Begin the alternative iteration by calculating D and HD and some
1802 : ! scalar products.
1803 : !
1804 20304276 : iterc = iterc + 1
1805 20304276 : temp = SQRT(delsq*gg - sgk*sgk)
1806 20304276 : tempa = delsq/temp
1807 20304276 : tempb = sgk/temp
1808 60918251 : DO i = 1, n
1809 60918251 : d(i) = tempa*(g(i) + hs(i)) - tempb*step(i)
1810 : END DO
1811 20304276 : CALL updatehd
1812 20304276 : IF (iterc <= itersw) THEN
1813 : jump1 = .TRUE.
1814 : CYCLE mainloop
1815 : END IF
1816 : END IF
1817 20304276 : dg = zero
1818 20304276 : dhd = zero
1819 20304276 : dhs = zero
1820 60918251 : DO i = 1, n
1821 40613975 : dg = dg + d(i)*g(i)
1822 40613975 : dhd = dhd + hd(i)*d(i)
1823 60918251 : dhs = dhs + hd(i)*step(i)
1824 : END DO
1825 : !
1826 : ! Seek the value of the angle that minimizes Q.
1827 : !
1828 20304276 : cf = half*(shs - dhd)
1829 20304276 : qbeg = sg + cf
1830 20304276 : qsav = qbeg
1831 20304276 : qmin = qbeg
1832 20304276 : isave = 0
1833 20304276 : iu = 49
1834 20304276 : temp = twopi/REAL(iu + 1, dp)
1835 1015213800 : DO i = 1, iu
1836 994909524 : angle = REAL(i, dp)*temp
1837 994909524 : cth = COS(angle)
1838 994909524 : sth = SIN(angle)
1839 994909524 : qnew = (sg + cf*cth)*cth + (dg + dhs*cth)*sth
1840 994909524 : IF (qnew < qmin) THEN
1841 : qmin = qnew
1842 : isave = i
1843 : tempa = qsav
1844 973825249 : ELSE IF (i == isave + 1) THEN
1845 25318813 : tempb = qnew
1846 : END IF
1847 1015213800 : qsav = qnew
1848 : END DO
1849 20304276 : IF (isave == zero) tempa = qnew
1850 8772710 : IF (isave == iu) tempb = qbeg
1851 20304276 : angle = zero
1852 20304276 : IF (tempa /= tempb) THEN
1853 20304276 : tempa = tempa - qmin
1854 20304276 : tempb = tempb - qmin
1855 20304276 : angle = half*(tempa - tempb)/(tempa + tempb)
1856 : END IF
1857 20304276 : angle = temp*(REAL(isave, DP) + angle)
1858 : !
1859 : ! Calculate the new STEP and HS. Then test for convergence.
1860 : !
1861 20304276 : cth = COS(angle)
1862 20304276 : sth = SIN(angle)
1863 20304276 : reduc = qbeg - (sg + cf*cth)*cth - (dg + dhs*cth)*sth
1864 20304276 : gg = zero
1865 60918251 : DO i = 1, n
1866 40613975 : step(i) = cth*step(i) + sth*d(i)
1867 40613975 : hs(i) = cth*hs(i) + sth*hd(i)
1868 60918251 : gg = gg + (g(i) + hs(i))**2
1869 : END DO
1870 20304276 : qred = qred + reduc
1871 20304276 : ratio = reduc/qred
1872 20304276 : IF (iterc < itermax .AND. ratio > 0.01_dp) THEN
1873 886 : jump2 = .TRUE.
1874 : ELSE
1875 : EXIT mainloop
1876 : END IF
1877 :
1878 40797795 : IF (gg <= 1.0e-4_dp*ggbeg) EXIT mainloop
1879 :
1880 : END DO mainloop
1881 :
1882 : !*******************************************************************************
1883 : CONTAINS
1884 : ! **************************************************************************************************
1885 : !> \brief ...
1886 : ! **************************************************************************************************
1887 129924311 : SUBROUTINE updatehd
1888 : INTEGER :: i, ih, j, k
1889 :
1890 389795725 : DO i = 1, n
1891 389795725 : hd(i) = zero
1892 : END DO
1893 779591450 : DO k = 1, npt
1894 649667139 : temp = zero
1895 1949269193 : DO j = 1, n
1896 1949269193 : temp = temp + xpt(k, j)*d(j)
1897 : END DO
1898 649667139 : temp = temp*pq(k)
1899 2079193504 : DO i = 1, n
1900 1949269193 : hd(i) = hd(i) + temp*xpt(k, i)
1901 : END DO
1902 : END DO
1903 129924311 : ih = 0
1904 389795725 : DO j = 1, n
1905 779664092 : DO i = 1, j
1906 389868367 : ih = ih + 1
1907 389868367 : IF (i < j) hd(j) = hd(j) + hq(ih)*d(i)
1908 649739781 : hd(i) = hd(i) + hq(ih)*d(j)
1909 : END DO
1910 : END DO
1911 129924311 : END SUBROUTINE updatehd
1912 :
1913 : END SUBROUTINE trsapp
1914 : !******************************************************************************
1915 :
1916 : ! **************************************************************************************************
1917 : !> \brief ...
1918 : !> \param n ...
1919 : !> \param npt ...
1920 : !> \param bmat ...
1921 : !> \param zmat ...
1922 : !> \param idz ...
1923 : !> \param ndim ...
1924 : !> \param vlag ...
1925 : !> \param beta ...
1926 : !> \param knew ...
1927 : !> \param w ...
1928 : ! **************************************************************************************************
1929 47320435 : SUBROUTINE update(n, npt, bmat, zmat, idz, ndim, vlag, beta, knew, w)
1930 :
1931 : INTEGER, INTENT(IN) :: n, npt, ndim
1932 : INTEGER, INTENT(INOUT) :: idz
1933 : REAL(dp), DIMENSION(npt, *), INTENT(INOUT) :: zmat
1934 : REAL(dp), DIMENSION(ndim, *), INTENT(INOUT) :: bmat
1935 : REAL(dp), DIMENSION(*), INTENT(INOUT) :: vlag
1936 : REAL(dp), INTENT(INOUT) :: beta
1937 : INTEGER, INTENT(INOUT) :: knew
1938 : REAL(dp), DIMENSION(*), INTENT(INOUT) :: w
1939 :
1940 : REAL(dp), PARAMETER :: one = 1.0_dp, zero = 0.0_dp
1941 :
1942 : INTEGER :: i, iflag, j, ja, jb, jl, jp, nptm
1943 : REAL(dp) :: alpha, denom, scala, scalb, tau, tausq, &
1944 : temp, tempa, tempb
1945 :
1946 : ! The arrays BMAT and ZMAT with IDZ are updated, in order to shift the
1947 : ! interpolation point that has index KNEW. On entry, VLAG contains the
1948 : ! components of the vector Theta*Wcheck+e_b of the updating formula
1949 : ! (6.11), and BETA holds the value of the parameter that has this na
1950 : ! The vector W is used for working space.
1951 : !
1952 :
1953 47320435 : nptm = npt - n - 1
1954 : !
1955 : ! Apply the rotations that put zeros in the KNEW-th row of ZMAT.
1956 : !
1957 47320435 : jl = 1
1958 94646739 : DO j = 2, nptm
1959 94646739 : IF (j == idz) THEN
1960 : jl = idz
1961 47326304 : ELSE IF (zmat(knew, j) /= zero) THEN
1962 46044745 : temp = SQRT(zmat(knew, jl)**2 + zmat(knew, j)**2)
1963 46044745 : tempa = zmat(knew, jl)/temp
1964 46044745 : tempb = zmat(knew, j)/temp
1965 276315786 : DO I = 1, NPT
1966 230271041 : temp = tempa*zmat(i, jl) + tempb*zmat(i, j)
1967 230271041 : zmat(i, j) = tempa*zmat(i, j) - tempb*zmat(i, jl)
1968 276315786 : zmat(i, jl) = temp
1969 : END DO
1970 46044745 : zmat(knew, j) = zero
1971 : END IF
1972 : END DO
1973 : !
1974 : ! Put the first NPT components of the KNEW-th column of HLAG into W,
1975 : ! and calculate the parameters of the updating formula.
1976 : !
1977 47320435 : tempa = zmat(knew, 1)
1978 47320435 : IF (idz >= 2) tempa = -tempa
1979 47320435 : IF (jl > 1) tempb = zmat(knew, jl)
1980 283934348 : DO i = 1, npt
1981 236613913 : w(i) = tempa*zmat(i, 1)
1982 283934348 : IF (jl > 1) w(i) = w(i) + tempb*zmat(i, jl)
1983 : END DO
1984 47320435 : alpha = w(knew)
1985 47320435 : tau = vlag(knew)
1986 47320435 : tausq = tau*tau
1987 47320435 : denom = alpha*beta + tausq
1988 47320435 : vlag(knew) = vlag(knew) - one
1989 : !
1990 : ! Complete the updating of ZMAT when there is only one nonzero eleme
1991 : ! in the KNEW-th row of the new matrix ZMAT, but, if IFLAG is set to
1992 : ! then the first column of ZMAT will be exchanged with another one l
1993 : !
1994 47320435 : iflag = 0
1995 47320435 : IF (JL == 1) THEN
1996 47320435 : temp = SQRT(ABS(denom))
1997 47320435 : tempb = tempa/temp
1998 47320435 : tempa = tau/temp
1999 283934348 : DO i = 1, npt
2000 283934348 : zmat(i, 1) = tempa*zmat(i, 1) - tempb*vlag(i)
2001 : END DO
2002 47320435 : IF (idz == 1 .AND. temp < zero) idz = 2
2003 47320435 : IF (idz >= 2 .AND. temp >= zero) iflag = 1
2004 : ELSE
2005 : !
2006 : ! Complete the updating of ZMAT in the alternative case.
2007 : !
2008 0 : ja = 1
2009 0 : IF (beta >= zero) ja = jl
2010 0 : jb = jl + 1 - ja
2011 0 : temp = zmat(knew, jb)/denom
2012 0 : tempa = temp*beta
2013 0 : tempb = temp*tau
2014 0 : temp = zmat(knew, ja)
2015 0 : scala = one/SQRT(ABS(beta)*temp*temp + tausq)
2016 0 : scalb = scala*SQRT(ABS(denom))
2017 0 : DO i = 1, npt
2018 0 : zmat(i, ja) = scala*(tau*zmat(i, ja) - temp*vlag(i))
2019 0 : zmat(i, jb) = scalb*(zmat(i, jb) - tempa*w(i) - tempb*vlag(i))
2020 : END DO
2021 0 : IF (denom <= zero) THEN
2022 0 : IF (beta < zero) idz = idz + 1
2023 0 : IF (beta >= zero) iflag = 1
2024 : END IF
2025 : END IF
2026 : !
2027 : ! IDZ is reduced in the following case, and usually the first column
2028 : ! of ZMAT is exchanged with a later one.
2029 : !
2030 : IF (iflag == 1) THEN
2031 0 : idz = idz - 1
2032 0 : DO i = 1, npt
2033 0 : temp = zmat(i, 1)
2034 0 : zmat(i, 1) = zmat(i, idz)
2035 0 : zmat(i, idz) = temp
2036 : END DO
2037 : END IF
2038 : !
2039 : ! Finally, update the matrix BMAT.
2040 : !
2041 141967174 : DO j = 1, n
2042 94646739 : jp = npt + j
2043 94646739 : w(jp) = bmat(knew, j)
2044 94646739 : tempa = (alpha*vlag(jp) - tau*w(jp))/denom
2045 94646739 : tempb = (-beta*w(jp) - tau*vlag(jp))/denom
2046 757248350 : DO i = 1, jp
2047 615281176 : bmat(i, j) = bmat(i, j) + tempa*vlag(i) + tempb*w(i)
2048 709927915 : IF (i > npt) bmat(jp, i - npt) = bmat(i, j)
2049 : END DO
2050 : END DO
2051 :
2052 47320435 : END SUBROUTINE update
2053 :
2054 0 : END MODULE powell
2055 :
2056 : !******************************************************************************
|