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 55638231 : 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 55638231 : CALL timeset(routineN, handle)
64 :
65 56342707 : SELECT CASE (optstate%state)
66 : CASE (0)
67 704476 : npt = 2*n + 1
68 2113428 : ALLOCATE (optstate%w((npt + 13)*(npt + n) + 3*n*(n + 3)/2))
69 2113428 : ALLOCATE (optstate%xopt(n))
70 : ! Initialize w
71 100173283 : optstate%w = 0.0_dp
72 704476 : optstate%state = 1
73 704476 : CALL newuoa(n, x, optstate)
74 : CASE (1, 2)
75 53524805 : 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 704461 : optstate%state = -1
93 : CASE (8)
94 2113749 : x(1:n) = optstate%xopt(1:n)
95 704476 : DEALLOCATE (optstate%w)
96 704476 : DEALLOCATE (optstate%xopt)
97 704476 : optstate%state = -1
98 : CASE DEFAULT
99 55638231 : CPABORT("")
100 : END SELECT
101 :
102 55638231 : CALL timestop(handle)
103 :
104 55638231 : END SUBROUTINE powell_optimize
105 : !******************************************************************************
106 : ! **************************************************************************************************
107 : !> \brief ...
108 : !> \param n ...
109 : !> \param x ...
110 : !> \param optstate ...
111 : ! **************************************************************************************************
112 54229281 : 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 54229281 : maxfun = optstate%maxfun
124 54229281 : rhobeg = optstate%rhobeg
125 54229281 : 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 54229281 : np = n + 1
162 54229281 : npt = 2*n + 1
163 54229281 : nptm = npt - np
164 54229281 : IF (npt < n + 2 .OR. npt > ((n + 2)*np)/2) THEN
165 0 : optstate%state = 5
166 0 : RETURN
167 : END IF
168 54229281 : ndim = npt + n
169 54229281 : ixb = 1
170 54229281 : ixo = ixb + n
171 54229281 : ixn = ixo + n
172 54229281 : ixp = ixn + n
173 54229281 : ifv = ixp + n*npt
174 54229281 : igq = ifv + npt
175 54229281 : ihq = igq + n
176 54229281 : ipq = ihq + (n*np)/2
177 54229281 : ibmat = ipq + npt
178 54229281 : izmat = ibmat + ndim*n
179 54229281 : id = izmat + npt*nptm
180 54229281 : ivl = id + n
181 54229281 : 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 54229281 : optstate%w(ivl:), optstate%w(iw:), optstate)
191 :
192 162699567 : 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 54229281 : SUBROUTINE newuob(n, npt, x, rhobeg, rhoend, maxfun, xbase, &
222 54229281 : 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 54229281 : 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 704476 : idz = 0
283 704476 : itest = 0
284 704476 : nf = 0
285 704476 : nfm = 0
286 704476 : nfmm = 0
287 704476 : nfsav = 0
288 704476 : knew = 0
289 704476 : kopt = 0
290 704476 : ksave = 0
291 704476 : ktemp = 0
292 704476 : rhosq = 0._dp
293 704476 : recip = 0._dp
294 704476 : reciq = 0._dp
295 704476 : fbeg = 0._dp
296 704476 : fopt = 0._dp
297 704476 : diffa = 0._dp
298 704476 : xoptsq = 0._dp
299 704476 : rho = 0._dp
300 704476 : delta = 0._dp
301 704476 : dsq = 0._dp
302 704476 : dnorm = 0._dp
303 704476 : ratio = 0._dp
304 704476 : temp = 0._dp
305 704476 : tempq = 0._dp
306 704476 : beta = 0._dp
307 704476 : dx = 0._dp
308 704476 : vquad = 0._dp
309 704476 : diff = 0._dp
310 704476 : diffc = 0._dp
311 704476 : diffb = 0._dp
312 704476 : fsave = 0._dp
313 704476 : detrat = 0._dp
314 704476 : hdiag = 0._dp
315 704476 : distsq = 0._dp
316 704476 : gisq = 0._dp
317 704476 : gqsq = 0._dp
318 704476 : f = 0._dp
319 704476 : bstep = 0._dp
320 704476 : alpha = 0._dp
321 704476 : dstep = 0._dp
322 : !
323 : END IF
324 :
325 54229281 : ipt = 0
326 54229281 : jpt = 0
327 54229281 : xipt = 0._dp
328 54229281 : xjpt = 0._dp
329 :
330 54229281 : half = 0.5_dp
331 54229281 : one = 1.0_dp
332 54229281 : tenth = 0.1_dp
333 54229281 : zero = 0.0_dp
334 54229281 : np = n + 1
335 54229281 : nh = (n*np)/2
336 54229281 : nptm = npt - np
337 54229281 : nftest = MAX(maxfun, 1)
338 :
339 54229281 : IF (opt%state == 2) GOTO 1000
340 : !
341 : ! Set the initial elements of XPT, BMAT, HQ, PQ and ZMAT to zero.
342 : !
343 2113749 : DO j = 1, n
344 1409273 : xbase(j) = x(j)
345 8486920 : DO k = 1, npt
346 8486920 : xpt(k, j) = zero
347 : END DO
348 12025583 : DO i = 1, ndim
349 11321107 : bmat(i, j) = zero
350 : END DO
351 : END DO
352 2826206 : DO ih = 1, nh
353 2826206 : hq(ih) = zero
354 : END DO
355 4227498 : DO k = 1, npt
356 3523022 : pq(k) = zero
357 11305145 : DO j = 1, nptm
358 10600669 : 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 704476 : rhosq = rhobeg*rhobeg
367 704476 : recip = one/rhosq
368 704476 : reciq = SQRT(half)/rhosq
369 704476 : nf = 0
370 3522559 : 50 nfm = nf
371 3522559 : nfmm = nf - n
372 3522559 : nf = nf + 1
373 3522559 : IF (nfm <= 2*n) THEN
374 3522559 : IF (nfm >= 1 .AND. nfm <= N) THEN
375 1409078 : xpt(nf, nfm) = rhobeg
376 2113481 : ELSE IF (nfm > n) THEN
377 1409005 : 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 10573351 : DO j = 1, n
401 10573351 : x(j) = xpt(nf, j) + xbase(j)
402 : END DO
403 3522551 : GOTO 310
404 3522551 : 70 fval(nf) = f
405 3522551 : IF (nf == 1) THEN
406 704476 : fbeg = f
407 704476 : fopt = f
408 704476 : kopt = 1
409 2818075 : ELSE IF (f < fopt) THEN
410 785937 : fopt = f
411 785937 : 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 3522551 : IF (NFM <= 2*N) THEN
418 3522551 : IF (nfm >= 1 .AND. nfm <= n) THEN
419 1409070 : gq(nfm) = (f - fbeg)/rhobeg
420 1409070 : 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 2113481 : ELSE IF (nfm > n) THEN
426 1409005 : bmat(nf - n, nfmm) = half/rhobeg
427 1409005 : bmat(nf, nfmm) = -half/rhobeg
428 1409005 : zmat(1, nfmm) = -reciq - reciq
429 1409005 : zmat(nf - n, nfmm) = reciq
430 1409005 : zmat(nf, nfmm) = reciq
431 1409005 : ih = (nfmm*(nfmm + 1))/2
432 1409005 : temp = (fbeg - f)/rhobeg
433 1409005 : hq(ih) = (gq(nfmm) - temp)/rhobeg
434 1409005 : 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 3522551 : IF (nf < npt) GOTO 50
451 : !
452 : ! Begin the iterative procedure, because the initial model is comple
453 : !
454 704468 : rho = rhobeg
455 704468 : delta = rho
456 704468 : idz = 1
457 704468 : diffa = zero
458 704468 : diffb = zero
459 704468 : itest = 0
460 704468 : xoptsq = zero
461 2113473 : DO i = 1, n
462 1409005 : xopt(i) = xpt(kopt, i)
463 2113473 : xoptsq = xoptsq + xopt(i)**2
464 : END DO
465 4227004 : 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 42235396 : 100 knew = 0
471 42235396 : CALL trsapp(n, npt, xopt, xpt, gq, hq, pq, delta, d, w, w(np), w(np + n), w(np + 2*n), crvmin)
472 42235396 : dsq = zero
473 126710515 : DO i = 1, n
474 126710515 : dsq = dsq + d(i)**2
475 : END DO
476 42235396 : dnorm = MIN(delta, SQRT(dsq))
477 42235396 : IF (dnorm < half*rho) THEN
478 10283176 : knew = -1
479 10283176 : delta = tenth*delta
480 10283176 : ratio = -1.0_dp
481 10283176 : IF (delta <= 1.5_dp*rho) delta = rho
482 10283176 : IF (nf <= nfsav + 2) GOTO 460
483 2845170 : temp = 0.125_dp*crvmin*rho*rho
484 2845170 : 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 49414887 : 120 IF (dsq <= 1.0e-3_dp*xoptsq) THEN
492 3029387 : tempq = 0.25_dp*xoptsq
493 18176622 : DO k = 1, npt
494 : sum = zero
495 45443407 : DO i = 1, n
496 45443407 : sum = sum + xpt(k, i)*xopt(i)
497 : END DO
498 15147235 : temp = pq(k)*sum
499 15147235 : sum = sum - half*xoptsq
500 15147235 : w(npt + k) = sum
501 48472794 : DO i = 1, n
502 30296172 : gq(i) = gq(i) + temp*xpt(k, i)
503 30296172 : xpt(k, i) = xpt(k, i) - half*xopt(i)
504 30296172 : vlag(i) = bmat(k, i)
505 30296172 : w(i) = sum*xpt(k, i) + tempq*xopt(i)
506 30296172 : ip = npt + i
507 90892141 : DO j = 1, i
508 75744906 : 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 9088311 : DO k = 1, nptm
516 : sumz = zero
517 36355096 : DO i = 1, npt
518 30296172 : sumz = sumz + zmat(i, k)
519 36355096 : w(i) = w(npt + i)*zmat(i, k)
520 : END DO
521 18177548 : DO j = 1, n
522 12118624 : sum = tempq*sumz*xopt(j)
523 72719920 : DO i = 1, npt
524 60601296 : sum = sum + w(i)*xpt(i, j)
525 60601296 : vlag(j) = sum
526 72719920 : IF (k < idz) sum = -sum
527 : END DO
528 78778844 : DO i = 1, npt
529 72719920 : bmat(i, j) = bmat(i, j) + sum*zmat(i, k)
530 : END DO
531 : END DO
532 21206935 : DO i = 1, n
533 12118624 : ip = i + npt
534 12118624 : temp = vlag(i)
535 12118624 : IF (k < idz) temp = -temp
536 36357528 : DO j = 1, i
537 30298604 : 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 9088311 : DO j = 1, n
547 6058924 : w(j) = zero
548 36355096 : DO k = 1, npt
549 30296172 : w(j) = w(j) + pq(k)*xpt(k, j)
550 36355096 : xpt(k, j) = xpt(k, j) - half*xopt(j)
551 : END DO
552 18177085 : DO i = 1, j
553 9088774 : ih = ih + 1
554 9088774 : IF (i < j) gq(j) = gq(j) + hq(ih)*xopt(i)
555 9088774 : gq(i) = gq(i) + hq(ih)*xopt(j)
556 9088774 : hq(ih) = hq(ih) + w(i)*xopt(j) + xopt(i)*w(j)
557 15147698 : bmat(npt + i, j) = bmat(npt + j, i)
558 : END DO
559 : END DO
560 9088311 : DO j = 1, n
561 6058924 : xbase(j) = xbase(j) + xopt(j)
562 9088311 : xopt(j) = zero
563 : END DO
564 3029387 : 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 49414887 : IF (knew > 0) THEN
572 : CALL biglag(n, npt, xopt, xpt, bmat, zmat, idz, ndim, knew, dstep, &
573 17462667 : 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 296501214 : DO k = 1, npt
580 : suma = zero
581 : sumb = zero
582 : sum = zero
583 741327695 : DO j = 1, n
584 494241368 : suma = suma + xpt(k, j)*d(j)
585 494241368 : sumb = sumb + xpt(k, j)*xopt(j)
586 741327695 : sum = sum + bmat(k, j)*d(j)
587 : END DO
588 247086327 : w(k) = suma*(half*suma + sumb)
589 296501214 : vlag(k) = sum
590 : END DO
591 49414887 : beta = zero
592 148250607 : DO k = 1, nptm
593 : sum = zero
594 593077088 : DO i = 1, npt
595 593077088 : sum = sum + zmat(i, k)*w(i)
596 : END DO
597 98835720 : IF (k < idz) THEN
598 0 : beta = beta + sum*sum
599 0 : sum = -sum
600 : ELSE
601 98835720 : beta = beta - sum*sum
602 : END IF
603 642491975 : DO i = 1, npt
604 593077088 : vlag(i) = vlag(i) + sum*zmat(i, k)
605 : END DO
606 : END DO
607 49414887 : bsum = zero
608 49414887 : dx = zero
609 148250607 : DO j = 1, n
610 : sum = zero
611 593077088 : DO i = 1, npt
612 593077088 : sum = sum + w(i)*bmat(i, j)
613 : END DO
614 98835720 : bsum = bsum + sum*d(j)
615 98835720 : jp = npt + j
616 296538544 : DO k = 1, n
617 296538544 : sum = sum + bmat(jp, k)*d(k)
618 : END DO
619 98835720 : vlag(jp) = sum
620 98835720 : bsum = bsum + sum*d(j)
621 148250607 : dx = dx + d(j)*xopt(j)
622 : END DO
623 49414887 : beta = dx*dx + dsq*(xoptsq + dx + dx + half*dsq) + beta - bsum
624 49414887 : 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 49414887 : IF (knew > 0) THEN
631 17462667 : temp = one + alpha*beta/vlag(knew)**2
632 17462667 : IF (ABS(temp) <= 0.8_dp) THEN
633 : CALL bigden(n, npt, xopt, xpt, bmat, zmat, idz, ndim, kopt, &
634 122 : 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 150012757 : 290 DO i = 1, n
641 100010500 : xnew(i) = xopt(i) + d(i)
642 150012757 : x(i) = xbase(i) + xnew(i)
643 : END DO
644 50002257 : nf = nf + 1
645 53524816 : 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 53524805 : CALL get_state
654 :
655 53524805 : opt%state = 2
656 :
657 53524805 : RETURN
658 :
659 : 1000 CONTINUE
660 :
661 53524805 : CALL set_state
662 :
663 53524805 : IF (nf <= npt) GOTO 70
664 50002254 : IF (knew == -1) THEN
665 587370 : opt%state = 6
666 587370 : CALL get_state
667 587370 : 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 49414884 : vquad = zero
674 49414884 : ih = 0
675 148250593 : DO j = 1, n
676 98835709 : vquad = vquad + d(j)*gq(j)
677 296519831 : DO i = 1, j
678 148269238 : ih = ih + 1
679 148269238 : temp = d(i)*xnew(j) + d(j)*xopt(i)
680 148269238 : IF (i == j) temp = half*temp
681 247104947 : vquad = vquad + temp*hq(ih)
682 : END DO
683 : END DO
684 296501186 : DO k = 1, npt
685 296501186 : vquad = vquad + pq(k)*w(k)
686 : END DO
687 49414884 : diff = f - fopt - vquad
688 49414884 : diffc = diffb
689 49414884 : diffb = diffa
690 49414884 : diffa = ABS(diff)
691 49414884 : 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 49414884 : fsave = fopt
698 49414884 : IF (f < fopt) THEN
699 25285496 : fopt = f
700 25285496 : xoptsq = zero
701 75858385 : DO i = 1, n
702 50572889 : xopt(i) = xnew(i)
703 75858385 : xoptsq = xoptsq + xopt(i)**2
704 : END DO
705 : END IF
706 49414884 : ksave = knew
707 49414884 : IF (knew > 0) GOTO 410
708 : !
709 : ! Pick the next value of DELTA after a trust region step.
710 : !
711 31952219 : 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 31952215 : ratio = (f - fsave)/vquad
718 31952215 : IF (ratio <= tenth) THEN
719 11813361 : delta = half*dnorm
720 20138854 : ELSE IF (ratio <= 0.7_dp) THEN
721 3481284 : delta = MAX(half*delta, dnorm)
722 : ELSE
723 16657570 : delta = MAX(half*delta, dnorm + dnorm)
724 : END IF
725 31952215 : 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 31952215 : rhosq = MAX(tenth*delta, rho)**2
730 31952215 : ktemp = 0
731 31952215 : detrat = zero
732 31952215 : IF (f >= fsave) THEN
733 10136151 : ktemp = kopt
734 10136151 : detrat = one
735 : END IF
736 191720472 : DO k = 1, npt
737 159768257 : hdiag = zero
738 479346032 : DO j = 1, nptm
739 319577775 : temp = one
740 319577775 : IF (j < idz) temp = -one
741 479346032 : hdiag = hdiag + temp*zmat(k, j)**2
742 : END DO
743 159768257 : temp = ABS(beta*hdiag + vlag(k)**2)
744 159768257 : distsq = zero
745 479346032 : DO j = 1, n
746 479346032 : distsq = distsq + (xpt(k, j) - xopt(j))**2
747 : END DO
748 159768257 : IF (distsq > rhosq) temp = temp*(distsq/rhosq)**3
749 191720472 : IF (temp > detrat .AND. k /= ktemp) THEN
750 68807196 : detrat = temp
751 68807196 : knew = k
752 : END IF
753 : END DO
754 31952215 : 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 48998433 : 410 CALL update(n, npt, bmat, zmat, idz, ndim, vlag, beta, knew, w)
761 48998433 : fval(knew) = f
762 48998433 : ih = 0
763 147001168 : DO i = 1, n
764 98002735 : temp = pq(knew)*xpt(knew, i)
765 294020745 : DO j = 1, i
766 147019577 : ih = ih + 1
767 245022312 : hq(ih) = hq(ih) + temp*xpt(knew, j)
768 : END DO
769 : END DO
770 48998433 : 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 147001168 : DO j = 1, nptm
776 98002735 : temp = diff*zmat(knew, j)
777 98002735 : IF (j < idz) temp = -temp
778 637076741 : DO k = 1, npt
779 588078308 : pq(k) = pq(k) + temp*zmat(k, j)
780 : END DO
781 : END DO
782 48998433 : gqsq = zero
783 147001168 : DO i = 1, n
784 98002735 : gq(i) = gq(i) + diff*bmat(knew, i)
785 98002735 : gqsq = gqsq + gq(i)**2
786 147001168 : 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 48998433 : IF (ksave == 0 .AND. delta == rho) THEN
794 6335018 : IF (ABS(ratio) > 1.0e-2_dp) THEN
795 4263451 : itest = 0
796 : ELSE
797 12429496 : DO k = 1, npt
798 12429496 : vlag(k) = fval(k) - fval(kopt)
799 : END DO
800 2071567 : gisq = zero
801 6214748 : DO i = 1, n
802 : sum = zero
803 24859600 : DO k = 1, npt
804 24859600 : sum = sum + bmat(k, i)*vlag(k)
805 : END DO
806 4143181 : gisq = gisq + sum*sum
807 6214748 : 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 2071567 : itest = itest + 1
814 2071567 : IF (gqsq < 1.0e2_dp*gisq) itest = 0
815 2071567 : IF (itest >= 3) THEN
816 353997 : DO i = 1, n
817 353997 : gq(i) = w(i)
818 : END DO
819 471996 : DO ih = 1, nh
820 471996 : hq(ih) = zero
821 : END DO
822 353997 : DO j = 1, nptm
823 235998 : w(j) = zero
824 1415988 : DO k = 1, npt
825 1415988 : w(j) = w(j) + vlag(k)*zmat(k, j)
826 : END DO
827 353997 : IF (j < idz) w(j) = -w(j)
828 : END DO
829 707994 : DO k = 1, npt
830 589995 : pq(k) = zero
831 1887984 : DO j = 1, nptm
832 1769985 : pq(k) = pq(k) + zmat(k, j)*w(j)
833 : END DO
834 : END DO
835 117999 : itest = 0
836 : END IF
837 : END IF
838 : END IF
839 48998433 : 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 48998433 : IF (f <= fsave + tenth*vquad) GOTO 100
846 24600028 : 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 20628602 : knew = 0
852 20628602 : 460 distsq = 4.0_dp*delta*delta
853 123776924 : DO k = 1, npt
854 103148322 : sum = zero
855 309476178 : DO j = 1, n
856 309476178 : sum = sum + (xpt(k, j) - xopt(j))**2
857 : END DO
858 123776924 : IF (sum > distsq) THEN
859 28207853 : knew = k
860 28207853 : 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 20628602 : IF (knew > 0) THEN
868 17462667 : dstep = MAX(MIN(tenth*SQRT(distsq), half*delta), rho)
869 17462667 : dsq = dstep*dstep
870 17462667 : GOTO 120
871 : END IF
872 3165935 : IF (ratio > zero) GOTO 100
873 2961268 : 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 4226997 : 490 IF (rho > rhoend) THEN
879 3522536 : delta = half*rho
880 3522536 : ratio = rho/rhoend
881 3522536 : IF (ratio <= 16.0_dp) THEN
882 704455 : rho = rhoend
883 2818081 : ELSE IF (ratio <= 250.0_dp) THEN
884 704455 : rho = SQRT(ratio)*rhoend
885 : ELSE
886 2113626 : rho = tenth*rho
887 : END IF
888 3522536 : delta = MAX(delta, rho)
889 3522536 : 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 704461 : IF (knew == -1) GOTO 290
896 117091 : opt%state = 7
897 117091 : CALL get_state
898 704476 : 530 IF (fopt <= f) THEN
899 657439 : DO i = 1, n
900 657439 : x(i) = xbase(i) + xopt(i)
901 : END DO
902 219040 : f = fopt
903 : END IF
904 :
905 704476 : CALL get_state
906 :
907 : !******************************************************************************
908 : CONTAINS
909 : !******************************************************************************
910 : ! **************************************************************************************************
911 : !> \brief ...
912 : ! **************************************************************************************************
913 54933757 : SUBROUTINE get_state()
914 54933757 : opt%np = np
915 54933757 : opt%nh = nh
916 54933757 : opt%nptm = nptm
917 54933757 : opt%nftest = nftest
918 54933757 : opt%idz = idz
919 54933757 : opt%itest = itest
920 54933757 : opt%nf = nf
921 54933757 : opt%nfm = nfm
922 54933757 : opt%nfmm = nfmm
923 54933757 : opt%nfsav = nfsav
924 54933757 : opt%knew = knew
925 54933757 : opt%kopt = kopt
926 54933757 : opt%ksave = ksave
927 54933757 : opt%ktemp = ktemp
928 54933757 : opt%rhosq = rhosq
929 54933757 : opt%recip = recip
930 54933757 : opt%reciq = reciq
931 54933757 : opt%fbeg = fbeg
932 54933757 : opt%fopt = fopt
933 54933757 : opt%diffa = diffa
934 54933757 : opt%xoptsq = xoptsq
935 54933757 : opt%rho = rho
936 54933757 : opt%delta = delta
937 54933757 : opt%dsq = dsq
938 54933757 : opt%dnorm = dnorm
939 54933757 : opt%ratio = ratio
940 54933757 : opt%temp = temp
941 54933757 : opt%tempq = tempq
942 54933757 : opt%beta = beta
943 54933757 : opt%dx = dx
944 54933757 : opt%vquad = vquad
945 54933757 : opt%diff = diff
946 54933757 : opt%diffc = diffc
947 54933757 : opt%diffb = diffb
948 54933757 : opt%fsave = fsave
949 54933757 : opt%detrat = detrat
950 54933757 : opt%hdiag = hdiag
951 54933757 : opt%distsq = distsq
952 54933757 : opt%gisq = gisq
953 54933757 : opt%gqsq = gqsq
954 54933757 : opt%f = f
955 54933757 : opt%bstep = bstep
956 54933757 : opt%alpha = alpha
957 54933757 : opt%dstep = dstep
958 54933757 : END SUBROUTINE get_state
959 :
960 : !******************************************************************************
961 : ! **************************************************************************************************
962 : !> \brief ...
963 : ! **************************************************************************************************
964 53524805 : SUBROUTINE set_state()
965 53524805 : np = opt%np
966 53524805 : nh = opt%nh
967 53524805 : nptm = opt%nptm
968 53524805 : nftest = opt%nftest
969 53524805 : idz = opt%idz
970 53524805 : itest = opt%itest
971 53524805 : nf = opt%nf
972 53524805 : nfm = opt%nfm
973 53524805 : nfmm = opt%nfmm
974 53524805 : nfsav = opt%nfsav
975 53524805 : knew = opt%knew
976 53524805 : kopt = opt%kopt
977 53524805 : ksave = opt%ksave
978 53524805 : ktemp = opt%ktemp
979 53524805 : rhosq = opt%rhosq
980 53524805 : recip = opt%recip
981 53524805 : reciq = opt%reciq
982 53524805 : fbeg = opt%fbeg
983 53524805 : fopt = opt%fopt
984 53524805 : diffa = opt%diffa
985 53524805 : xoptsq = opt%xoptsq
986 53524805 : rho = opt%rho
987 53524805 : delta = opt%delta
988 53524805 : dsq = opt%dsq
989 53524805 : dnorm = opt%dnorm
990 53524805 : ratio = opt%ratio
991 53524805 : temp = opt%temp
992 53524805 : tempq = opt%tempq
993 53524805 : beta = opt%beta
994 53524805 : dx = opt%dx
995 53524805 : vquad = opt%vquad
996 53524805 : diff = opt%diff
997 53524805 : diffc = opt%diffc
998 53524805 : diffb = opt%diffb
999 53524805 : fsave = opt%fsave
1000 53524805 : detrat = opt%detrat
1001 53524805 : hdiag = opt%hdiag
1002 53524805 : distsq = opt%distsq
1003 53524805 : gisq = opt%gisq
1004 53524805 : gqsq = opt%gqsq
1005 53524805 : f = opt%f
1006 53524805 : bstep = opt%bstep
1007 53524805 : alpha = opt%alpha
1008 53524805 : dstep = opt%dstep
1009 53524805 : 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 122 : SUBROUTINE bigden(n, npt, xopt, xpt, bmat, zmat, idz, ndim, kopt, &
1036 122 : 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 122 : 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 732 : DO k = 1, npt
1091 732 : w(n + k) = zero
1092 : END DO
1093 366 : DO j = 1, nptm
1094 244 : temp = zmat(knew, j)
1095 244 : IF (j < idz) temp = -temp
1096 1586 : DO k = 1, npt
1097 1464 : w(n + k) = w(n + k) + temp*zmat(k, j)
1098 : END DO
1099 : END DO
1100 122 : 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 122 : dd = zero
1108 122 : ds = zero
1109 122 : ss = zero
1110 122 : xoptsq = zero
1111 366 : DO i = 1, n
1112 244 : dd = dd + d(i)**2
1113 244 : s(i) = xpt(knew, i) - xopt(i)
1114 244 : ds = ds + d(i)*s(i)
1115 244 : ss = ss + s(i)**2
1116 366 : xoptsq = xoptsq + xopt(i)**2
1117 : END DO
1118 122 : 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 122 : ssden = dd*ss - ds*ds
1143 122 : iterc = 0
1144 122 : 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 192 : iterc = iterc + 1
1151 192 : temp = one/SQRT(ssden)
1152 192 : xoptd = zero
1153 192 : xopts = zero
1154 576 : DO i = 1, n
1155 384 : s(i) = temp*(dd*s(i) - ds*d(i))
1156 384 : xoptd = xoptd + xopt(i)*d(i)
1157 576 : xopts = xopts + xopt(i)*s(i)
1158 : END DO
1159 : !
1160 : ! Set the coefficients of the first two terms of BETA.
1161 : !
1162 192 : tempa = half*xoptd*xoptd
1163 192 : tempb = half*xopts*xopts
1164 192 : den(1) = dd*(xoptsq + half*dd) + tempa + tempb
1165 192 : den(2) = two*xoptd*dd
1166 192 : den(3) = two*xopts*dd
1167 192 : den(4) = tempa - tempb
1168 192 : den(5) = xoptd*xopts
1169 960 : DO i = 6, 9
1170 960 : den(i) = zero
1171 : END DO
1172 : !
1173 : ! Put the coefficients of Wcheck in WVEC.
1174 : !
1175 1152 : DO k = 1, npt
1176 : tempa = zero
1177 : tempb = zero
1178 : tempc = zero
1179 2880 : DO i = 1, n
1180 1920 : tempa = tempa + xpt(k, i)*d(i)
1181 1920 : tempb = tempb + xpt(k, i)*s(i)
1182 2880 : tempc = tempc + xpt(k, i)*xopt(i)
1183 : END DO
1184 960 : wvec(k, 1) = quart*(tempa*tempa + tempb*tempb)
1185 960 : wvec(k, 2) = tempa*tempc
1186 960 : wvec(k, 3) = tempb*tempc
1187 960 : wvec(k, 4) = quart*(tempa*tempa - tempb*tempb)
1188 1152 : wvec(k, 5) = half*tempa*tempb
1189 : END DO
1190 576 : DO i = 1, n
1191 384 : ip = i + npt
1192 384 : wvec(ip, 1) = zero
1193 384 : wvec(ip, 2) = d(i)
1194 384 : wvec(ip, 3) = s(i)
1195 384 : wvec(ip, 4) = zero
1196 576 : wvec(ip, 5) = zero
1197 : END DO
1198 : !
1199 : ! Put the coefficients of THETA*Wcheck in PROD.
1200 : !
1201 1152 : DO jc = 1, 5
1202 960 : nw = npt
1203 960 : IF (jc == 2 .OR. jc == 3) nw = ndim
1204 5760 : DO k = 1, npt
1205 5760 : prod(k, jc) = zero
1206 : END DO
1207 2880 : DO j = 1, nptm
1208 : sum = zero
1209 11520 : DO k = 1, npt
1210 11520 : sum = sum + zmat(k, j)*wvec(k, jc)
1211 : END DO
1212 1920 : IF (j < idz) sum = -sum
1213 12480 : DO k = 1, npt
1214 11520 : prod(k, jc) = prod(k, jc) + sum*zmat(k, j)
1215 : END DO
1216 : END DO
1217 960 : IF (nw == ndim) THEN
1218 2304 : DO k = 1, npt
1219 : sum = zero
1220 5760 : DO j = 1, n
1221 5760 : sum = sum + bmat(k, j)*wvec(npt + j, jc)
1222 : END DO
1223 2304 : prod(k, jc) = prod(k, jc) + sum
1224 : END DO
1225 : END IF
1226 3072 : DO j = 1, n
1227 : sum = zero
1228 13056 : DO i = 1, nw
1229 13056 : sum = sum + bmat(i, j)*wvec(i, jc)
1230 : END DO
1231 2880 : 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 1536 : DO k = 1, ndim
1238 : sum = zero
1239 8064 : DO I = 1, 5
1240 6720 : par(i) = half*prod(k, i)*wvec(k, i)
1241 8064 : sum = sum + par(i)
1242 : END DO
1243 1344 : den(1) = den(1) - par(1) - sum
1244 1344 : tempa = prod(k, 1)*wvec(k, 2) + prod(k, 2)*wvec(k, 1)
1245 1344 : tempb = prod(k, 2)*wvec(k, 4) + prod(k, 4)*wvec(k, 2)
1246 1344 : tempc = prod(k, 3)*wvec(k, 5) + prod(k, 5)*wvec(k, 3)
1247 1344 : den(2) = den(2) - tempa - half*(tempb + tempc)
1248 1344 : den(6) = den(6) - half*(tempb - tempc)
1249 1344 : tempa = prod(k, 1)*wvec(k, 3) + prod(k, 3)*wvec(k, 1)
1250 1344 : tempb = prod(k, 2)*wvec(k, 5) + prod(k, 5)*wvec(k, 2)
1251 1344 : tempc = prod(k, 3)*wvec(k, 4) + prod(k, 4)*wvec(k, 3)
1252 1344 : den(3) = den(3) - tempa - half*(tempb - tempc)
1253 1344 : den(7) = den(7) - half*(tempb + tempc)
1254 1344 : tempa = prod(k, 1)*wvec(k, 4) + prod(k, 4)*wvec(k, 1)
1255 1344 : den(4) = den(4) - tempa - par(2) + par(3)
1256 1344 : tempa = prod(k, 1)*wvec(k, 5) + prod(k, 5)*wvec(k, 1)
1257 1344 : tempb = prod(k, 2)*wvec(k, 3) + prod(k, 3)*wvec(k, 2)
1258 1344 : den(5) = den(5) - tempa - half*tempb
1259 1344 : den(8) = den(8) - par(4) + par(5)
1260 1344 : tempa = prod(k, 4)*wvec(k, 5) + prod(k, 5)*wvec(k, 4)
1261 1536 : 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 1152 : DO i = 1, 5
1268 960 : par(i) = half*prod(knew, i)**2
1269 1152 : sum = sum + par(i)
1270 : END DO
1271 192 : denex(1) = alpha*den(1) + par(1) + sum
1272 192 : tempa = two*prod(knew, 1)*prod(knew, 2)
1273 192 : tempb = prod(knew, 2)*prod(knew, 4)
1274 192 : tempc = prod(knew, 3)*prod(knew, 5)
1275 192 : denex(2) = alpha*den(2) + tempa + tempb + tempc
1276 192 : denex(6) = alpha*den(6) + tempb - tempc
1277 192 : tempa = two*prod(knew, 1)*prod(knew, 3)
1278 192 : tempb = prod(knew, 2)*prod(knew, 5)
1279 192 : tempc = prod(knew, 3)*prod(knew, 4)
1280 192 : denex(3) = alpha*den(3) + tempa + tempb - tempc
1281 192 : denex(7) = alpha*den(7) + tempb + tempc
1282 192 : tempa = two*prod(knew, 1)*prod(knew, 4)
1283 192 : denex(4) = alpha*den(4) + tempa + par(2) - par(3)
1284 192 : tempa = two*prod(knew, 1)*prod(knew, 5)
1285 192 : denex(5) = alpha*den(5) + tempa + prod(knew, 2)*prod(knew, 3)
1286 192 : denex(8) = alpha*den(8) + par(4) - par(5)
1287 192 : 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 192 : sum = denex(1) + denex(2) + denex(4) + denex(6) + denex(8)
1292 192 : denold = sum
1293 192 : denmax = sum
1294 192 : isave = 0
1295 192 : iu = 49
1296 192 : temp = twopi/REAL(IU + 1, dp)
1297 192 : par(1) = one
1298 9600 : DO i = 1, iu
1299 9408 : angle = REAL(i, dp)*temp
1300 9408 : par(2) = COS(angle)
1301 9408 : par(3) = SIN(angle)
1302 9408 : DO j = 4, 8, 2
1303 28224 : par(j) = par(2)*par(j - 2) - par(3)*par(j - 1)
1304 28224 : par(j + 1) = par(2)*par(j - 1) + par(3)*par(j - 2)
1305 : END DO
1306 : sumold = sum
1307 : sum = zero
1308 94080 : DO j = 1, 9
1309 94080 : sum = sum + denex(j)*par(j)
1310 : END DO
1311 9600 : IF (ABS(sum) > ABS(denmax)) THEN
1312 : denmax = sum
1313 : isave = i
1314 : tempa = sumold
1315 8780 : ELSE IF (i == isave + 1) THEN
1316 346 : tempb = sum
1317 : END IF
1318 : END DO
1319 192 : IF (isave == 0) tempa = sum
1320 94 : IF (isave == iu) tempb = denold
1321 192 : step = zero
1322 192 : IF (tempa /= tempb) THEN
1323 192 : tempa = tempa - denmax
1324 192 : tempb = tempb - denmax
1325 192 : step = half*(tempa - tempb)/(tempa + tempb)
1326 : END IF
1327 192 : 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 192 : par(2) = COS(angle)
1333 192 : par(3) = SIN(angle)
1334 192 : DO j = 4, 8, 2
1335 576 : par(j) = par(2)*par(j - 2) - par(3)*par(j - 1)
1336 576 : par(j + 1) = par(2)*par(j - 1) + par(3)*par(j - 2)
1337 : END DO
1338 192 : beta = zero
1339 192 : denmax = zero
1340 1920 : DO j = 1, 9
1341 1728 : beta = beta + den(j)*par(j)
1342 1920 : denmax = denmax + denex(j)*par(j)
1343 : END DO
1344 1536 : DO k = 1, ndim
1345 1344 : vlag(k) = zero
1346 8256 : DO j = 1, 5
1347 8064 : vlag(k) = vlag(k) + prod(k, j)*par(j)
1348 : END DO
1349 : END DO
1350 192 : tau = vlag(knew)
1351 192 : dd = zero
1352 192 : tempa = zero
1353 192 : tempb = zero
1354 576 : DO i = 1, n
1355 384 : d(i) = par(2)*d(i) + par(3)*s(i)
1356 384 : w(i) = xopt(i) + d(i)
1357 384 : dd = dd + d(i)**2
1358 384 : tempa = tempa + d(i)*w(i)
1359 576 : tempb = tempb + w(i)*w(i)
1360 : END DO
1361 192 : IF (iterc >= n) EXIT mainloop
1362 122 : IF (iterc >= 1) densav = MAX(densav, denold)
1363 122 : IF (ABS(denmax) <= 1.1_dp*ABS(densav)) EXIT mainloop
1364 210 : 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 210 : DO i = 1, n
1370 140 : temp = tempa*xopt(i) + tempb*d(i) - vlag(npt + i)
1371 210 : s(i) = tau*bmat(knew, i) + alpha*temp
1372 : END DO
1373 420 : DO k = 1, npt
1374 : sum = zero
1375 1050 : DO j = 1, n
1376 1050 : sum = sum + xpt(k, j)*w(j)
1377 : END DO
1378 350 : temp = (tau*w(n + k) - alpha*vlag(k))*sum
1379 1120 : DO i = 1, n
1380 1050 : s(i) = s(i) + temp*xpt(k, i)
1381 : END DO
1382 : END DO
1383 : ss = zero
1384 : ds = zero
1385 210 : DO i = 1, n
1386 140 : ss = ss + s(i)**2
1387 210 : ds = ds + d(i)*s(i)
1388 : END DO
1389 70 : ssden = dd*ss - ds*ds
1390 192 : 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 976 : DO k = 1, ndim
1396 854 : w(k) = zero
1397 5246 : DO j = 1, 5
1398 5124 : w(k) = w(k) + wvec(k, j)*par(j)
1399 : END DO
1400 : END DO
1401 122 : vlag(kopt) = vlag(kopt) + one
1402 :
1403 122 : 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 17462667 : 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|| <= DELTA, where LFU
1465 : ! the KNEW-th Lagrange function.
1466 : !
1467 :
1468 17462667 : delsq = delta*delta
1469 17462667 : 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 17462667 : iterc = 0
1475 104780702 : DO k = 1, npt
1476 104780702 : hcol(k) = zero
1477 : END DO
1478 52390351 : DO j = 1, nptm
1479 34927684 : temp = zmat(knew, j)
1480 34927684 : IF (j < idz) temp = -temp
1481 227053799 : DO k = 1, npt
1482 209591132 : hcol(k) = hcol(k) + temp*zmat(k, j)
1483 : END DO
1484 : END DO
1485 17462667 : 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 17462667 : dd = zero
1491 52390351 : DO i = 1, n
1492 34927684 : d(i) = xpt(knew, i) - xopt(i)
1493 34927684 : gc(i) = bmat(knew, i)
1494 34927684 : gd(i) = zero
1495 52390351 : dd = dd + d(i)**2
1496 : END DO
1497 104780702 : DO k = 1, npt
1498 : temp = zero
1499 : sum = zero
1500 261981483 : DO j = 1, n
1501 174663448 : temp = temp + xpt(k, j)*xopt(j)
1502 261981483 : sum = sum + xpt(k, j)*d(j)
1503 : END DO
1504 87318035 : temp = hcol(k)*temp
1505 87318035 : sum = hcol(k)*sum
1506 279444150 : DO i = 1, n
1507 174663448 : gc(i) = gc(i) + temp*xpt(k, i)
1508 261981483 : 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 52390351 : DO i = 1, n
1519 34927684 : gg = gg + gc(i)**2
1520 34927684 : sp = sp + d(i)*gc(i)
1521 52390351 : dhd = dhd + d(i)*gd(i)
1522 : END DO
1523 17462667 : scale = delta/SQRT(dd)
1524 17462667 : IF (sp*dhd < zero) scale = -scale
1525 17462667 : temp = zero
1526 17462667 : IF (sp*sp > 0.99_dp*dd*gg) temp = one
1527 17462667 : tau = scale*(ABS(sp) + half*scale*ABS(dhd))
1528 17462667 : IF (gg*delsq < 0.01_dp*tau*tau) temp = one
1529 52390351 : DO i = 1, n
1530 34927684 : d(i) = scale*d(i)
1531 34927684 : gd(i) = scale*gd(i)
1532 52390351 : 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 24733332 : iterc = iterc + 1
1541 24733332 : dd = zero
1542 24733332 : sp = zero
1543 24733332 : ss = zero
1544 74203774 : DO i = 1, n
1545 49470442 : dd = dd + d(i)**2
1546 49470442 : sp = sp + d(i)*s(i)
1547 74203774 : ss = ss + s(i)**2
1548 : END DO
1549 24733332 : temp = dd*ss - sp*sp
1550 24733332 : IF (temp <= 1.0e-8_dp*dd*ss) EXIT mainloop
1551 23650387 : denom = SQRT(temp)
1552 70954663 : DO i = 1, n
1553 47304276 : s(i) = (dd*s(i) - sp*d(i))/denom
1554 70954663 : 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 141909326 : DO k = 1, npt
1561 : sum = zero
1562 354817747 : DO j = 1, n
1563 354817747 : sum = sum + xpt(k, j)*s(j)
1564 : END DO
1565 118258939 : sum = hcol(k)*sum
1566 378468134 : DO i = 1, n
1567 354817747 : 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 70954663 : DO i = 1, n
1576 47304276 : cf1 = cf1 + s(i)*w(i)
1577 47304276 : cf2 = cf2 + d(i)*gc(i)
1578 47304276 : cf3 = cf3 + s(i)*gc(i)
1579 47304276 : cf4 = cf4 + d(i)*gd(i)
1580 70954663 : cf5 = cf5 + s(i)*gd(i)
1581 : END DO
1582 23650387 : cf1 = half*cf1
1583 23650387 : cf4 = half*cf4 - cf1
1584 : !
1585 : ! Seek the value of the angle that maximizes the modulus of TAU.
1586 : !
1587 23650387 : taubeg = cf1 + cf2 + cf4
1588 23650387 : taumax = taubeg
1589 23650387 : tauold = taubeg
1590 23650387 : isave = 0
1591 23650387 : iu = 49
1592 23650387 : temp = twopi/REAL(iu + 1, DP)
1593 1182519350 : DO i = 1, iu
1594 1158868963 : angle = REAL(i, dp)*temp
1595 1158868963 : cth = COS(angle)
1596 1158868963 : sth = SIN(angle)
1597 1158868963 : tau = cf1 + (cf2 + cf4*cth)*cth + (cf3 + cf5*cth)*sth
1598 1158868963 : IF (ABS(tau) > ABS(taumax)) THEN
1599 : taumax = tau
1600 : isave = i
1601 : tempa = tauold
1602 1098276598 : ELSE IF (i == isave + 1) THEN
1603 25717055 : tempb = taU
1604 : END IF
1605 1182519350 : tauold = tau
1606 : END DO
1607 23650387 : IF (isave == 0) tempa = tau
1608 13898765 : IF (isave == iu) tempb = taubeg
1609 23650387 : step = zero
1610 23650387 : IF (tempa /= tempb) THEN
1611 23650387 : tempa = tempa - taumax
1612 23650387 : tempb = tempb - taumax
1613 23650387 : step = half*(tempa - tempb)/(tempa + tempb)
1614 : END IF
1615 23650387 : angle = temp*(REAL(isave, DP) + step)
1616 : !
1617 : ! Calculate the new D and GD. Then test for convergence.
1618 : !
1619 23650387 : cth = COS(angle)
1620 23650387 : sth = SIN(angle)
1621 23650387 : tau = cf1 + (cf2 + cf4*cth)*cth + (cf3 + cf5*cth)*sth
1622 70954663 : DO i = 1, n
1623 47304276 : d(i) = cth*d(i) + sth*s(i)
1624 47304276 : gd(i) = cth*gd(i) + sth*w(i)
1625 70954663 : s(i) = gc(i) + gd(i)
1626 : END DO
1627 23650387 : IF (ABS(tau) <= 1.1_dp*ABS(taubeg)) EXIT mainloop
1628 24733332 : IF (iterc >= n) EXIT mainloop
1629 : END DO mainloop
1630 :
1631 17462667 : 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 42235396 : 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 42235396 : delsq = delta*delta
1692 42235396 : iterc = 0
1693 42235396 : itermax = n
1694 42235396 : itersw = itermax
1695 126710515 : DO i = 1, n
1696 126710515 : d(i) = xopt(i)
1697 : END DO
1698 42235396 : CALL updatehd
1699 : !
1700 : ! Prepare for the first line search.
1701 : !
1702 42235396 : qred = zero
1703 42235396 : dd = zero
1704 126710515 : DO i = 1, n
1705 84475119 : step(i) = zero
1706 84475119 : hs(i) = zero
1707 84475119 : g(i) = gq(i) + hd(i)
1708 84475119 : d(i) = -g(i)
1709 126710515 : dd = dd + d(i)**2
1710 : END DO
1711 42235396 : crvmin = zero
1712 42235396 : 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 71270307 : IF (.NOT. jump2) THEN
1724 71269421 : IF (.NOT. jump1) THEN
1725 71269421 : iterc = iterc + 1
1726 71269421 : temp = delsq - ss
1727 71269421 : bstep = temp/(ds + SQRT(ds*ds + dd*temp))
1728 71269421 : CALL updatehd
1729 : END IF
1730 71269421 : jump1 = .FALSE.
1731 71269421 : IF (iterc <= itersw) THEN
1732 71269421 : dhd = zero
1733 213821305 : DO j = 1, n
1734 213821305 : dhd = dhd + d(j)*hd(j)
1735 : END DO
1736 : !
1737 : ! Update CRVMIN and set the step-length ALPHA.
1738 : !
1739 71269421 : alpha = bstep
1740 71269421 : IF (dhd > zero) THEN
1741 62987753 : temp = dhd/dd
1742 62987753 : IF (iterc == 1) crvmin = temp
1743 62987753 : crvmin = MIN(crvmin, temp)
1744 62987753 : alpha = MIN(alpha, gg/dhd)
1745 : END IF
1746 71269421 : qadd = alpha*(gg - half*alpha*dhd)
1747 71269421 : qred = qred + qadd
1748 : !
1749 : ! Update STEP and HS.
1750 : !
1751 71269421 : ggsav = gg
1752 71269421 : gg = zero
1753 213821305 : DO i = 1, n
1754 142551884 : step(i) = step(i) + alpha*d(i)
1755 142551884 : hs(i) = hs(i) + alpha*hd(i)
1756 213821305 : gg = gg + (g(i) + hs(i))**2
1757 : END DO
1758 : !
1759 : ! Begin another conjugate direction iteration if required.
1760 : !
1761 71269421 : IF (alpha < bstep) THEN
1762 46830069 : IF (qadd <= 0.01_dp*qred) EXIT mainloop
1763 46123245 : IF (gg <= 1.0e-4_dp*ggbeg) EXIT mainloop
1764 29034240 : IF (iterc == itermax) EXIT mainloop
1765 29034178 : temp = gg/ggsav
1766 29034178 : dd = zero
1767 29034178 : ds = zero
1768 29034178 : ss = zero
1769 87111580 : DO i = 1, n
1770 58077402 : d(i) = temp*d(i) - g(i) - hs(i)
1771 58077402 : dd = dd + d(i)**2
1772 58077402 : ds = ds + d(i)*step(I)
1773 87111580 : ss = ss + step(i)**2
1774 : END DO
1775 29034178 : IF (ds <= zero) EXIT mainloop
1776 29034178 : IF (ss < delsq) CYCLE mainloop
1777 : END IF
1778 24439352 : crvmin = zero
1779 24439352 : itersw = iterc
1780 24439352 : jump2 = .TRUE.
1781 24439352 : 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 24076701 : IF (jump2) THEN
1791 24076701 : sg = zero
1792 24076701 : shs = zero
1793 72236036 : DO i = 1, n
1794 48159335 : sg = sg + step(i)*g(i)
1795 72236036 : shs = shs + step(i)*hs(i)
1796 : END DO
1797 24076701 : sgk = sg + shs
1798 24076701 : angtest = sgk/SQRT(gg*delsq)
1799 24076701 : 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 21023004 : iterc = iterc + 1
1805 21023004 : temp = SQRT(delsq*gg - sgk*sgk)
1806 21023004 : tempa = delsq/temp
1807 21023004 : tempb = sgk/temp
1808 63074435 : DO i = 1, n
1809 63074435 : d(i) = tempa*(g(i) + hs(i)) - tempb*step(i)
1810 : END DO
1811 21023004 : CALL updatehd
1812 21023004 : IF (iterc <= itersw) THEN
1813 : jump1 = .TRUE.
1814 : CYCLE mainloop
1815 : END IF
1816 : END IF
1817 21023004 : dg = zero
1818 21023004 : dhd = zero
1819 21023004 : dhs = zero
1820 63074435 : DO i = 1, n
1821 42051431 : dg = dg + d(i)*g(i)
1822 42051431 : dhd = dhd + hd(i)*d(i)
1823 63074435 : dhs = dhs + hd(i)*step(i)
1824 : END DO
1825 : !
1826 : ! Seek the value of the angle that minimizes Q.
1827 : !
1828 21023004 : cf = half*(shs - dhd)
1829 21023004 : qbeg = sg + cf
1830 21023004 : qsav = qbeg
1831 21023004 : qmin = qbeg
1832 21023004 : isave = 0
1833 21023004 : iu = 49
1834 21023004 : temp = twopi/REAL(iu + 1, dp)
1835 1051150200 : DO i = 1, iu
1836 1030127196 : angle = REAL(i, dp)*temp
1837 1030127196 : cth = COS(angle)
1838 1030127196 : sth = SIN(angle)
1839 1030127196 : qnew = (sg + cf*cth)*cth + (dg + dhs*cth)*sth
1840 1030127196 : IF (qnew < qmin) THEN
1841 : qmin = qnew
1842 : isave = i
1843 : tempa = qsav
1844 1008248695 : ELSE IF (i == isave + 1) THEN
1845 26226099 : tempb = qnew
1846 : END IF
1847 1051150200 : qsav = qnew
1848 : END DO
1849 21023004 : IF (isave == zero) tempa = qnew
1850 9102030 : IF (isave == iu) tempb = qbeg
1851 21023004 : angle = zero
1852 21023004 : IF (tempa /= tempb) THEN
1853 21023004 : tempa = tempa - qmin
1854 21023004 : tempb = tempb - qmin
1855 21023004 : angle = half*(tempa - tempb)/(tempa + tempb)
1856 : END IF
1857 21023004 : angle = temp*(REAL(isave, DP) + angle)
1858 : !
1859 : ! Calculate the new STEP and HS. Then test for convergence.
1860 : !
1861 21023004 : cth = COS(angle)
1862 21023004 : sth = SIN(angle)
1863 21023004 : reduc = qbeg - (sg + cf*cth)*cth - (dg + dhs*cth)*sth
1864 21023004 : gg = zero
1865 63074435 : DO i = 1, n
1866 42051431 : step(i) = cth*step(i) + sth*d(i)
1867 42051431 : hs(i) = cth*hs(i) + sth*hd(i)
1868 63074435 : gg = gg + (g(i) + hs(i))**2
1869 : END DO
1870 21023004 : qred = qred + reduc
1871 21023004 : ratio = reduc/qred
1872 21023004 : IF (iterc < itermax .AND. ratio > 0.01_dp) THEN
1873 886 : jump2 = .TRUE.
1874 : ELSE
1875 : EXIT mainloop
1876 : END IF
1877 :
1878 42236129 : IF (gg <= 1.0e-4_dp*ggbeg) EXIT mainloop
1879 :
1880 : END DO mainloop
1881 :
1882 : !*******************************************************************************
1883 : CONTAINS
1884 : ! **************************************************************************************************
1885 : !> \brief ...
1886 : ! **************************************************************************************************
1887 134527821 : SUBROUTINE updatehd
1888 : INTEGER :: i, ih, j, k
1889 :
1890 403606255 : DO i = 1, n
1891 403606255 : hd(i) = zero
1892 : END DO
1893 807212510 : DO k = 1, npt
1894 672684689 : temp = zero
1895 2018321843 : DO j = 1, n
1896 2018321843 : temp = temp + xpt(k, j)*d(j)
1897 : END DO
1898 672684689 : temp = temp*pq(k)
1899 2152849664 : DO i = 1, n
1900 2018321843 : hd(i) = hd(i) + temp*xpt(k, i)
1901 : END DO
1902 : END DO
1903 134527821 : ih = 0
1904 403606255 : DO j = 1, n
1905 807285152 : DO i = 1, j
1906 403678897 : ih = ih + 1
1907 403678897 : IF (i < j) hd(j) = hd(j) + hq(ih)*d(i)
1908 672757331 : hd(i) = hd(i) + hq(ih)*d(j)
1909 : END DO
1910 : END DO
1911 134527821 : 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 48998433 : 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 48998433 : nptm = npt - n - 1
1954 : !
1955 : ! Apply the rotations that put zeros in the KNEW-th row of ZMAT.
1956 : !
1957 48998433 : jl = 1
1958 98002735 : DO j = 2, nptm
1959 98002735 : IF (j == idz) THEN
1960 : jl = idz
1961 49004302 : ELSE IF (zmat(knew, j) /= zero) THEN
1962 47676589 : temp = SQRT(zmat(knew, jl)**2 + zmat(knew, j)**2)
1963 47676589 : tempa = zmat(knew, jl)/temp
1964 47676589 : tempb = zmat(knew, j)/temp
1965 286106850 : DO I = 1, NPT
1966 238430261 : temp = tempa*zmat(i, jl) + tempb*zmat(i, j)
1967 238430261 : zmat(i, j) = tempa*zmat(i, j) - tempb*zmat(i, jl)
1968 286106850 : zmat(i, jl) = temp
1969 : END DO
1970 47676589 : 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 48998433 : tempa = zmat(knew, 1)
1978 48998433 : IF (idz >= 2) tempa = -tempa
1979 48998433 : IF (jl > 1) tempb = zmat(knew, jl)
1980 294002336 : DO i = 1, npt
1981 245003903 : w(i) = tempa*zmat(i, 1)
1982 294002336 : IF (jl > 1) w(i) = w(i) + tempb*zmat(i, jl)
1983 : END DO
1984 48998433 : alpha = w(knew)
1985 48998433 : tau = vlag(knew)
1986 48998433 : tausq = tau*tau
1987 48998433 : denom = alpha*beta + tausq
1988 48998433 : 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 48998433 : iflag = 0
1995 48998433 : IF (JL == 1) THEN
1996 48998433 : temp = SQRT(ABS(denom))
1997 48998433 : tempb = tempa/temp
1998 48998433 : tempa = tau/temp
1999 294002336 : DO i = 1, npt
2000 294002336 : zmat(i, 1) = tempa*zmat(i, 1) - tempb*vlag(i)
2001 : END DO
2002 48998433 : IF (idz == 1 .AND. temp < zero) idz = 2
2003 48998433 : 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 147001168 : DO j = 1, n
2042 98002735 : jp = npt + j
2043 98002735 : w(jp) = bmat(knew, j)
2044 98002735 : tempa = (alpha*vlag(jp) - tau*w(jp))/denom
2045 98002735 : tempb = (-beta*w(jp) - tau*vlag(jp))/denom
2046 784096318 : DO i = 1, jp
2047 637095150 : bmat(i, j) = bmat(i, j) + tempa*vlag(i) + tempb*w(i)
2048 735097885 : IF (i > npt) bmat(jp, i - npt) = bmat(i, j)
2049 : END DO
2050 : END DO
2051 :
2052 48998433 : END SUBROUTINE update
2053 :
2054 0 : END MODULE powell
2055 :
2056 : !******************************************************************************
|