Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 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 54159777 : 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 54159777 : CALL timeset(routineN, handle)
64 :
65 54846993 : SELECT CASE (optstate%state)
66 : CASE (0)
67 687216 : npt = 2*n + 1
68 2061648 : ALLOCATE (optstate%w((npt + 13)*(npt + n) + 3*n*(n + 3)/2))
69 2061648 : ALLOCATE (optstate%xopt(n))
70 : ! Initialize w
71 97722363 : optstate%w = 0.0_dp
72 687216 : optstate%state = 1
73 687216 : CALL newuoa(n, x, optstate)
74 : CASE (1, 2)
75 52098131 : 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 687201 : optstate%state = -1
93 : CASE (8)
94 2061969 : x(1:n) = optstate%xopt(1:n)
95 687216 : DEALLOCATE (optstate%w)
96 687216 : DEALLOCATE (optstate%xopt)
97 687216 : optstate%state = -1
98 : CASE DEFAULT
99 54159777 : CPABORT("")
100 : END SELECT
101 :
102 54159777 : CALL timestop(handle)
103 :
104 54159777 : END SUBROUTINE powell_optimize
105 : !******************************************************************************
106 : ! **************************************************************************************************
107 : !> \brief ...
108 : !> \param n ...
109 : !> \param x ...
110 : !> \param optstate ...
111 : ! **************************************************************************************************
112 52785347 : 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 52785347 : maxfun = optstate%maxfun
124 52785347 : rhobeg = optstate%rhobeg
125 52785347 : 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 52785347 : np = n + 1
162 52785347 : npt = 2*n + 1
163 52785347 : nptm = npt - np
164 52785347 : IF (npt < n + 2 .OR. npt > ((n + 2)*np)/2) THEN
165 0 : optstate%state = 5
166 0 : RETURN
167 : END IF
168 52785347 : ndim = npt + n
169 52785347 : ixb = 1
170 52785347 : ixo = ixb + n
171 52785347 : ixn = ixo + n
172 52785347 : ixp = ixn + n
173 52785347 : ifv = ixp + n*npt
174 52785347 : igq = ifv + npt
175 52785347 : ihq = igq + n
176 52785347 : ipq = ihq + (n*np)/2
177 52785347 : ibmat = ipq + npt
178 52785347 : izmat = ibmat + ndim*n
179 52785347 : id = izmat + npt*nptm
180 52785347 : ivl = id + n
181 52785347 : 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 52785347 : optstate%w(ivl:), optstate%w(iw:), optstate)
191 :
192 158367765 : 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 52785347 : SUBROUTINE newuob(n, npt, x, rhobeg, rhoend, maxfun, xbase, &
222 52785347 : 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 52785347 : 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 687216 : idz = 0
283 687216 : itest = 0
284 687216 : nf = 0
285 687216 : nfm = 0
286 687216 : nfmm = 0
287 687216 : nfsav = 0
288 687216 : knew = 0
289 687216 : kopt = 0
290 687216 : ksave = 0
291 687216 : ktemp = 0
292 687216 : rhosq = 0._dp
293 687216 : recip = 0._dp
294 687216 : reciq = 0._dp
295 687216 : fbeg = 0._dp
296 687216 : fopt = 0._dp
297 687216 : diffa = 0._dp
298 687216 : xoptsq = 0._dp
299 687216 : rho = 0._dp
300 687216 : delta = 0._dp
301 687216 : dsq = 0._dp
302 687216 : dnorm = 0._dp
303 687216 : ratio = 0._dp
304 687216 : temp = 0._dp
305 687216 : tempq = 0._dp
306 687216 : beta = 0._dp
307 687216 : dx = 0._dp
308 687216 : vquad = 0._dp
309 687216 : diff = 0._dp
310 687216 : diffc = 0._dp
311 687216 : diffb = 0._dp
312 687216 : fsave = 0._dp
313 687216 : detrat = 0._dp
314 687216 : hdiag = 0._dp
315 687216 : distsq = 0._dp
316 687216 : gisq = 0._dp
317 687216 : gqsq = 0._dp
318 687216 : f = 0._dp
319 687216 : bstep = 0._dp
320 687216 : alpha = 0._dp
321 687216 : dstep = 0._dp
322 : !
323 : END IF
324 :
325 52785347 : ipt = 0
326 52785347 : jpt = 0
327 52785347 : xipt = 0._dp
328 52785347 : xjpt = 0._dp
329 :
330 52785347 : half = 0.5_dp
331 52785347 : one = 1.0_dp
332 52785347 : tenth = 0.1_dp
333 52785347 : zero = 0.0_dp
334 52785347 : np = n + 1
335 52785347 : nh = (n*np)/2
336 52785347 : nptm = npt - np
337 52785347 : nftest = MAX(maxfun, 1)
338 :
339 52785347 : IF (opt%state == 2) GOTO 1000
340 : !
341 : ! Set the initial elements of XPT, BMAT, HQ, PQ and ZMAT to zero.
342 : !
343 2061969 : DO j = 1, n
344 1374753 : xbase(j) = x(j)
345 8279800 : DO k = 1, npt
346 8279800 : xpt(k, j) = zero
347 : END DO
348 11732163 : DO i = 1, ndim
349 11044947 : bmat(i, j) = zero
350 : END DO
351 : END DO
352 2757166 : DO ih = 1, nh
353 2757166 : hq(ih) = zero
354 : END DO
355 4123938 : DO k = 1, npt
356 3436722 : pq(k) = zero
357 11028985 : DO j = 1, nptm
358 10341769 : 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 687216 : rhosq = rhobeg*rhobeg
367 687216 : recip = one/rhosq
368 687216 : reciq = SQRT(half)/rhosq
369 687216 : nf = 0
370 3436259 : 50 nfm = nf
371 3436259 : nfmm = nf - n
372 3436259 : nf = nf + 1
373 3436259 : IF (nfm <= 2*n) THEN
374 3436259 : IF (nfm >= 1 .AND. nfm <= N) THEN
375 1374558 : xpt(nf, nfm) = rhobeg
376 2061701 : ELSE IF (nfm > n) THEN
377 1374485 : 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 10314451 : DO j = 1, n
401 10314451 : x(j) = xpt(nf, j) + xbase(j)
402 : END DO
403 3436251 : GOTO 310
404 3436251 : 70 fval(nf) = f
405 3436251 : IF (nf == 1) THEN
406 687216 : fbeg = f
407 687216 : fopt = f
408 687216 : kopt = 1
409 2749035 : ELSE IF (f < fopt) THEN
410 765817 : fopt = f
411 765817 : 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 3436251 : IF (NFM <= 2*N) THEN
418 3436251 : IF (nfm >= 1 .AND. nfm <= n) THEN
419 1374550 : gq(nfm) = (f - fbeg)/rhobeg
420 1374550 : 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 2061701 : ELSE IF (nfm > n) THEN
426 1374485 : bmat(nf - n, nfmm) = half/rhobeg
427 1374485 : bmat(nf, nfmm) = -half/rhobeg
428 1374485 : zmat(1, nfmm) = -reciq - reciq
429 1374485 : zmat(nf - n, nfmm) = reciq
430 1374485 : zmat(nf, nfmm) = reciq
431 1374485 : ih = (nfmm*(nfmm + 1))/2
432 1374485 : temp = (fbeg - f)/rhobeg
433 1374485 : hq(ih) = (gq(nfmm) - temp)/rhobeg
434 1374485 : 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 3436251 : IF (nf < npt) GOTO 50
451 : !
452 : ! Begin the iterative procedure, because the initial model is comple
453 : !
454 687208 : rho = rhobeg
455 687208 : delta = rho
456 687208 : idz = 1
457 687208 : diffa = zero
458 687208 : diffb = zero
459 687208 : itest = 0
460 687208 : xoptsq = zero
461 2061693 : DO i = 1, n
462 1374485 : xopt(i) = xpt(kopt, i)
463 2061693 : xoptsq = xoptsq + xopt(i)**2
464 : END DO
465 4123444 : 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 41107066 : 100 knew = 0
471 41107066 : CALL trsapp(n, npt, xopt, xpt, gq, hq, pq, delta, d, w, w(np), w(np + n), w(np + 2*n), crvmin)
472 41107066 : dsq = zero
473 123325525 : DO i = 1, n
474 123325525 : dsq = dsq + d(i)**2
475 : END DO
476 41107066 : dnorm = MIN(delta, SQRT(dsq))
477 41107066 : IF (dnorm < half*rho) THEN
478 10022346 : knew = -1
479 10022346 : delta = tenth*delta
480 10022346 : ratio = -1.0_dp
481 10022346 : IF (delta <= 1.5_dp*rho) delta = rho
482 10022346 : IF (nf <= nfsav + 2) GOTO 460
483 2771816 : temp = 0.125_dp*crvmin*rho*rho
484 2771816 : 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 48089333 : 120 IF (dsq <= 1.0e-3_dp*xoptsq) THEN
492 2948177 : tempq = 0.25_dp*xoptsq
493 17689362 : DO k = 1, npt
494 : sum = zero
495 44225257 : DO i = 1, n
496 44225257 : sum = sum + xpt(k, i)*xopt(i)
497 : END DO
498 14741185 : temp = pq(k)*sum
499 14741185 : sum = sum - half*xoptsq
500 14741185 : w(npt + k) = sum
501 47173434 : DO i = 1, n
502 29484072 : gq(i) = gq(i) + temp*xpt(k, i)
503 29484072 : xpt(k, i) = xpt(k, i) - half*xopt(i)
504 29484072 : vlag(i) = bmat(k, i)
505 29484072 : w(i) = sum*xpt(k, i) + tempq*xopt(i)
506 29484072 : ip = npt + i
507 88455841 : DO j = 1, i
508 73714656 : 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 8844681 : DO k = 1, nptm
516 : sumz = zero
517 35380576 : DO i = 1, npt
518 29484072 : sumz = sumz + zmat(i, k)
519 35380576 : w(i) = w(npt + i)*zmat(i, k)
520 : END DO
521 17690288 : DO j = 1, n
522 11793784 : sum = tempq*sumz*xopt(j)
523 70770880 : DO i = 1, npt
524 58977096 : sum = sum + w(i)*xpt(i, j)
525 58977096 : vlag(j) = sum
526 70770880 : IF (k < idz) sum = -sum
527 : END DO
528 76667384 : DO i = 1, npt
529 70770880 : bmat(i, j) = bmat(i, j) + sum*zmat(i, k)
530 : END DO
531 : END DO
532 20638465 : DO i = 1, n
533 11793784 : ip = i + npt
534 11793784 : temp = vlag(i)
535 11793784 : IF (k < idz) temp = -temp
536 35383008 : DO j = 1, i
537 29486504 : 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 8844681 : DO j = 1, n
547 5896504 : w(j) = zero
548 35380576 : DO k = 1, npt
549 29484072 : w(j) = w(j) + pq(k)*xpt(k, j)
550 35380576 : xpt(k, j) = xpt(k, j) - half*xopt(j)
551 : END DO
552 17689825 : DO i = 1, j
553 8845144 : ih = ih + 1
554 8845144 : IF (i < j) gq(j) = gq(j) + hq(ih)*xopt(i)
555 8845144 : gq(i) = gq(i) + hq(ih)*xopt(j)
556 8845144 : hq(ih) = hq(ih) + w(i)*xopt(j) + xopt(i)*w(j)
557 14741648 : bmat(npt + i, j) = bmat(npt + j, i)
558 : END DO
559 : END DO
560 8844681 : DO j = 1, n
561 5896504 : xbase(j) = xbase(j) + xopt(j)
562 8844681 : xopt(j) = zero
563 : END DO
564 2948177 : 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 48089333 : IF (knew > 0) THEN
572 : CALL biglag(n, npt, xopt, xpt, bmat, zmat, idz, ndim, knew, dstep, &
573 17004613 : 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 288547890 : DO k = 1, npt
580 : suma = zero
581 : sumb = zero
582 : sum = zero
583 721444385 : DO j = 1, n
584 480985828 : suma = suma + xpt(k, j)*d(j)
585 480985828 : sumb = sumb + xpt(k, j)*xopt(j)
586 721444385 : sum = sum + bmat(k, j)*d(j)
587 : END DO
588 240458557 : w(k) = suma*(half*suma + sumb)
589 288547890 : vlag(k) = sum
590 : END DO
591 48089333 : beta = zero
592 144273945 : DO k = 1, nptm
593 : sum = zero
594 577170440 : DO i = 1, npt
595 577170440 : sum = sum + zmat(i, k)*w(i)
596 : END DO
597 96184612 : IF (k < idz) THEN
598 0 : beta = beta + sum*sum
599 0 : sum = -sum
600 : ELSE
601 96184612 : beta = beta - sum*sum
602 : END IF
603 625259773 : DO i = 1, npt
604 577170440 : vlag(i) = vlag(i) + sum*zmat(i, k)
605 : END DO
606 : END DO
607 48089333 : bsum = zero
608 48089333 : dx = zero
609 144273945 : DO j = 1, n
610 : sum = zero
611 577170440 : DO i = 1, npt
612 577170440 : sum = sum + w(i)*bmat(i, j)
613 : END DO
614 96184612 : bsum = bsum + sum*d(j)
615 96184612 : jp = npt + j
616 288585220 : DO k = 1, n
617 288585220 : sum = sum + bmat(jp, k)*d(k)
618 : END DO
619 96184612 : vlag(jp) = sum
620 96184612 : bsum = bsum + sum*d(j)
621 144273945 : dx = dx + d(j)*xopt(j)
622 : END DO
623 48089333 : beta = dx*dx + dsq*(xoptsq + dx + dx + half*dsq) + beta - bsum
624 48089333 : 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 48089333 : IF (knew > 0) THEN
631 17004613 : temp = one + alpha*beta/vlag(knew)**2
632 17004613 : 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 145991635 : 290 DO i = 1, n
641 97329752 : xnew(i) = xopt(i) + d(i)
642 145991635 : x(i) = xbase(i) + xnew(i)
643 : END DO
644 48661883 : nf = nf + 1
645 52098142 : 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 52098131 : CALL get_state
654 :
655 52098131 : opt%state = 2
656 :
657 52098131 : RETURN
658 :
659 : 1000 CONTINUE
660 :
661 52098131 : CALL set_state
662 :
663 52098131 : IF (nf <= npt) GOTO 70
664 48661880 : IF (knew == -1) THEN
665 572550 : opt%state = 6
666 572550 : CALL get_state
667 572550 : 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 48089330 : vquad = zero
674 48089330 : ih = 0
675 144273931 : DO j = 1, n
676 96184601 : vquad = vquad + d(j)*gq(j)
677 288566507 : DO i = 1, j
678 144292576 : ih = ih + 1
679 144292576 : temp = d(i)*xnew(j) + d(j)*xopt(i)
680 144292576 : IF (i == j) temp = half*temp
681 240477177 : vquad = vquad + temp*hq(ih)
682 : END DO
683 : END DO
684 288547862 : DO k = 1, npt
685 288547862 : vquad = vquad + pq(k)*w(k)
686 : END DO
687 48089330 : diff = f - fopt - vquad
688 48089330 : diffc = diffb
689 48089330 : diffb = diffa
690 48089330 : diffa = ABS(diff)
691 48089330 : 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 48089330 : fsave = fopt
698 48089330 : IF (f < fopt) THEN
699 24592688 : fopt = f
700 24592688 : xoptsq = zero
701 73779961 : DO i = 1, n
702 49187273 : xopt(i) = xnew(i)
703 73779961 : xoptsq = xoptsq + xopt(i)**2
704 : END DO
705 : END IF
706 48089330 : ksave = knew
707 48089330 : IF (knew > 0) GOTO 410
708 : !
709 : ! Pick the next value of DELTA after a trust region step.
710 : !
711 31084719 : 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 31084715 : ratio = (f - fsave)/vquad
718 31084715 : IF (ratio <= tenth) THEN
719 11501625 : delta = half*dnorm
720 19583090 : ELSE IF (ratio <= 0.7_dp) THEN
721 3379758 : delta = MAX(half*delta, dnorm)
722 : ELSE
723 16203332 : delta = MAX(half*delta, dnorm + dnorm)
724 : END IF
725 31084715 : 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 31084715 : rhosq = MAX(tenth*delta, rho)**2
730 31084715 : ktemp = 0
731 31084715 : detrat = zero
732 31084715 : IF (f >= fsave) THEN
733 9868053 : ktemp = kopt
734 9868053 : detrat = one
735 : END IF
736 186515472 : DO k = 1, npt
737 155430757 : hdiag = zero
738 466333532 : DO j = 1, nptm
739 310902775 : temp = one
740 310902775 : IF (j < idz) temp = -one
741 466333532 : hdiag = hdiag + temp*zmat(k, j)**2
742 : END DO
743 155430757 : temp = ABS(beta*hdiag + vlag(k)**2)
744 155430757 : distsq = zero
745 466333532 : DO j = 1, n
746 466333532 : distsq = distsq + (xpt(k, j) - xopt(j))**2
747 : END DO
748 155430757 : IF (distsq > rhosq) temp = temp*(distsq/rhosq)**3
749 186515472 : IF (temp > detrat .AND. k /= ktemp) THEN
750 66922940 : detrat = temp
751 66922940 : knew = k
752 : END IF
753 : END DO
754 31084715 : 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 47682925 : 410 CALL update(n, npt, bmat, zmat, idz, ndim, vlag, beta, knew, w)
761 47682925 : fval(knew) = f
762 47682925 : ih = 0
763 143054644 : DO i = 1, n
764 95371719 : temp = pq(knew)*xpt(knew, i)
765 286127697 : DO j = 1, i
766 143073053 : ih = ih + 1
767 238444772 : hq(ih) = hq(ih) + temp*xpt(knew, j)
768 : END DO
769 : END DO
770 47682925 : 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 143054644 : DO j = 1, nptm
776 95371719 : temp = diff*zmat(knew, j)
777 95371719 : IF (j < idz) temp = -temp
778 619975137 : DO k = 1, npt
779 572292212 : pq(k) = pq(k) + temp*zmat(k, j)
780 : END DO
781 : END DO
782 47682925 : gqsq = zero
783 143054644 : DO i = 1, n
784 95371719 : gq(i) = gq(i) + diff*bmat(knew, i)
785 95371719 : gqsq = gqsq + gq(i)**2
786 143054644 : 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 47682925 : IF (ksave == 0 .AND. delta == rho) THEN
794 6175380 : IF (ABS(ratio) > 1.0e-2_dp) THEN
795 4149005 : itest = 0
796 : ELSE
797 12158344 : DO k = 1, npt
798 12158344 : vlag(k) = fval(k) - fval(kopt)
799 : END DO
800 2026375 : gisq = zero
801 6079172 : DO i = 1, n
802 : sum = zero
803 24317296 : DO k = 1, npt
804 24317296 : sum = sum + bmat(k, i)*vlag(k)
805 : END DO
806 4052797 : gisq = gisq + sum*sum
807 6079172 : 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 2026375 : itest = itest + 1
814 2026375 : IF (gqsq < 1.0e2_dp*gisq) itest = 0
815 2026375 : IF (itest >= 3) THEN
816 347991 : DO i = 1, n
817 347991 : gq(i) = w(i)
818 : END DO
819 463988 : DO ih = 1, nh
820 463988 : hq(ih) = zero
821 : END DO
822 347991 : DO j = 1, nptm
823 231994 : w(j) = zero
824 1391964 : DO k = 1, npt
825 1391964 : w(j) = w(j) + vlag(k)*zmat(k, j)
826 : END DO
827 347991 : IF (j < idz) w(j) = -w(j)
828 : END DO
829 695982 : DO k = 1, npt
830 579985 : pq(k) = zero
831 1855952 : DO j = 1, nptm
832 1739955 : pq(k) = pq(k) + zmat(k, j)*w(j)
833 : END DO
834 : END DO
835 115997 : itest = 0
836 : END IF
837 : END IF
838 : END IF
839 47682925 : 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 47682925 : IF (f <= fsave + tenth*vquad) GOTO 100
846 23954156 : 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 20093248 : knew = 0
852 20093248 : 460 distsq = 4.0_dp*delta*delta
853 120564800 : DO k = 1, npt
854 100471552 : sum = zero
855 301445868 : DO j = 1, n
856 301445868 : sum = sum + (xpt(k, j) - xopt(j))**2
857 : END DO
858 120564800 : IF (sum > distsq) THEN
859 27468953 : knew = k
860 27468953 : 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 20093248 : IF (knew > 0) THEN
868 17004613 : dstep = MAX(MIN(tenth*SQRT(distsq), half*delta), rho)
869 17004613 : dsq = dstep*dstep
870 17004613 : GOTO 120
871 : END IF
872 3088635 : IF (ratio > zero) GOTO 100
873 2889196 : 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 4123437 : 490 IF (rho > rhoend) THEN
879 3436236 : delta = half*rho
880 3436236 : ratio = rho/rhoend
881 3436236 : IF (ratio <= 16.0_dp) THEN
882 687195 : rho = rhoend
883 2749041 : ELSE IF (ratio <= 250.0_dp) THEN
884 687195 : rho = SQRT(ratio)*rhoend
885 : ELSE
886 2061846 : rho = tenth*rho
887 : END IF
888 3436236 : delta = MAX(delta, rho)
889 3436236 : 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 687201 : IF (knew == -1) GOTO 290
896 114651 : opt%state = 7
897 114651 : CALL get_state
898 687216 : 530 IF (fopt <= f) THEN
899 642613 : DO i = 1, n
900 642613 : x(i) = xbase(i) + xopt(i)
901 : END DO
902 214098 : f = fopt
903 : END IF
904 :
905 687216 : CALL get_state
906 :
907 : !******************************************************************************
908 : CONTAINS
909 : !******************************************************************************
910 : ! **************************************************************************************************
911 : !> \brief ...
912 : ! **************************************************************************************************
913 53472563 : SUBROUTINE get_state()
914 53472563 : opt%np = np
915 53472563 : opt%nh = nh
916 53472563 : opt%nptm = nptm
917 53472563 : opt%nftest = nftest
918 53472563 : opt%idz = idz
919 53472563 : opt%itest = itest
920 53472563 : opt%nf = nf
921 53472563 : opt%nfm = nfm
922 53472563 : opt%nfmm = nfmm
923 53472563 : opt%nfsav = nfsav
924 53472563 : opt%knew = knew
925 53472563 : opt%kopt = kopt
926 53472563 : opt%ksave = ksave
927 53472563 : opt%ktemp = ktemp
928 53472563 : opt%rhosq = rhosq
929 53472563 : opt%recip = recip
930 53472563 : opt%reciq = reciq
931 53472563 : opt%fbeg = fbeg
932 53472563 : opt%fopt = fopt
933 53472563 : opt%diffa = diffa
934 53472563 : opt%xoptsq = xoptsq
935 53472563 : opt%rho = rho
936 53472563 : opt%delta = delta
937 53472563 : opt%dsq = dsq
938 53472563 : opt%dnorm = dnorm
939 53472563 : opt%ratio = ratio
940 53472563 : opt%temp = temp
941 53472563 : opt%tempq = tempq
942 53472563 : opt%beta = beta
943 53472563 : opt%dx = dx
944 53472563 : opt%vquad = vquad
945 53472563 : opt%diff = diff
946 53472563 : opt%diffc = diffc
947 53472563 : opt%diffb = diffb
948 53472563 : opt%fsave = fsave
949 53472563 : opt%detrat = detrat
950 53472563 : opt%hdiag = hdiag
951 53472563 : opt%distsq = distsq
952 53472563 : opt%gisq = gisq
953 53472563 : opt%gqsq = gqsq
954 53472563 : opt%f = f
955 53472563 : opt%bstep = bstep
956 53472563 : opt%alpha = alpha
957 53472563 : opt%dstep = dstep
958 53472563 : END SUBROUTINE get_state
959 :
960 : !******************************************************************************
961 : ! **************************************************************************************************
962 : !> \brief ...
963 : ! **************************************************************************************************
964 52098131 : SUBROUTINE set_state()
965 52098131 : np = opt%np
966 52098131 : nh = opt%nh
967 52098131 : nptm = opt%nptm
968 52098131 : nftest = opt%nftest
969 52098131 : idz = opt%idz
970 52098131 : itest = opt%itest
971 52098131 : nf = opt%nf
972 52098131 : nfm = opt%nfm
973 52098131 : nfmm = opt%nfmm
974 52098131 : nfsav = opt%nfsav
975 52098131 : knew = opt%knew
976 52098131 : kopt = opt%kopt
977 52098131 : ksave = opt%ksave
978 52098131 : ktemp = opt%ktemp
979 52098131 : rhosq = opt%rhosq
980 52098131 : recip = opt%recip
981 52098131 : reciq = opt%reciq
982 52098131 : fbeg = opt%fbeg
983 52098131 : fopt = opt%fopt
984 52098131 : diffa = opt%diffa
985 52098131 : xoptsq = opt%xoptsq
986 52098131 : rho = opt%rho
987 52098131 : delta = opt%delta
988 52098131 : dsq = opt%dsq
989 52098131 : dnorm = opt%dnorm
990 52098131 : ratio = opt%ratio
991 52098131 : temp = opt%temp
992 52098131 : tempq = opt%tempq
993 52098131 : beta = opt%beta
994 52098131 : dx = opt%dx
995 52098131 : vquad = opt%vquad
996 52098131 : diff = opt%diff
997 52098131 : diffc = opt%diffc
998 52098131 : diffb = opt%diffb
999 52098131 : fsave = opt%fsave
1000 52098131 : detrat = opt%detrat
1001 52098131 : hdiag = opt%hdiag
1002 52098131 : distsq = opt%distsq
1003 52098131 : gisq = opt%gisq
1004 52098131 : gqsq = opt%gqsq
1005 52098131 : f = opt%f
1006 52098131 : bstep = opt%bstep
1007 52098131 : alpha = opt%alpha
1008 52098131 : dstep = opt%dstep
1009 52098131 : 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 188 : iterc = iterc + 1
1151 188 : temp = one/SQRT(ssden)
1152 188 : xoptd = zero
1153 188 : xopts = zero
1154 564 : DO i = 1, n
1155 376 : s(i) = temp*(dd*s(i) - ds*d(i))
1156 376 : xoptd = xoptd + xopt(i)*d(i)
1157 564 : xopts = xopts + xopt(i)*s(i)
1158 : END DO
1159 : !
1160 : ! Set the coefficients of the first two terms of BETA.
1161 : !
1162 188 : tempa = half*xoptd*xoptd
1163 188 : tempb = half*xopts*xopts
1164 188 : den(1) = dd*(xoptsq + half*dd) + tempa + tempb
1165 188 : den(2) = two*xoptd*dd
1166 188 : den(3) = two*xopts*dd
1167 188 : den(4) = tempa - tempb
1168 188 : den(5) = xoptd*xopts
1169 940 : DO i = 6, 9
1170 940 : den(i) = zero
1171 : END DO
1172 : !
1173 : ! Put the coefficients of Wcheck in WVEC.
1174 : !
1175 1128 : DO k = 1, npt
1176 : tempa = zero
1177 : tempb = zero
1178 : tempc = zero
1179 2820 : DO i = 1, n
1180 1880 : tempa = tempa + xpt(k, i)*d(i)
1181 1880 : tempb = tempb + xpt(k, i)*s(i)
1182 2820 : tempc = tempc + xpt(k, i)*xopt(i)
1183 : END DO
1184 940 : wvec(k, 1) = quart*(tempa*tempa + tempb*tempb)
1185 940 : wvec(k, 2) = tempa*tempc
1186 940 : wvec(k, 3) = tempb*tempc
1187 940 : wvec(k, 4) = quart*(tempa*tempa - tempb*tempb)
1188 1128 : wvec(k, 5) = half*tempa*tempb
1189 : END DO
1190 564 : DO i = 1, n
1191 376 : ip = i + npt
1192 376 : wvec(ip, 1) = zero
1193 376 : wvec(ip, 2) = d(i)
1194 376 : wvec(ip, 3) = s(i)
1195 376 : wvec(ip, 4) = zero
1196 564 : wvec(ip, 5) = zero
1197 : END DO
1198 : !
1199 : ! Put the coefficients of THETA*Wcheck in PROD.
1200 : !
1201 1128 : DO jc = 1, 5
1202 940 : nw = npt
1203 940 : IF (jc == 2 .OR. jc == 3) nw = ndim
1204 5640 : DO k = 1, npt
1205 5640 : prod(k, jc) = zero
1206 : END DO
1207 2820 : DO j = 1, nptm
1208 : sum = zero
1209 11280 : DO k = 1, npt
1210 11280 : sum = sum + zmat(k, j)*wvec(k, jc)
1211 : END DO
1212 1880 : IF (j < idz) sum = -sum
1213 12220 : DO k = 1, npt
1214 11280 : prod(k, jc) = prod(k, jc) + sum*zmat(k, j)
1215 : END DO
1216 : END DO
1217 940 : IF (nw == ndim) THEN
1218 2256 : DO k = 1, npt
1219 : sum = zero
1220 5640 : DO j = 1, n
1221 5640 : sum = sum + bmat(k, j)*wvec(npt + j, jc)
1222 : END DO
1223 2256 : prod(k, jc) = prod(k, jc) + sum
1224 : END DO
1225 : END IF
1226 3008 : DO j = 1, n
1227 : sum = zero
1228 12784 : DO i = 1, nw
1229 12784 : sum = sum + bmat(i, j)*wvec(i, jc)
1230 : END DO
1231 2820 : 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 1504 : DO k = 1, ndim
1238 : sum = zero
1239 7896 : DO I = 1, 5
1240 6580 : par(i) = half*prod(k, i)*wvec(k, i)
1241 7896 : sum = sum + par(i)
1242 : END DO
1243 1316 : den(1) = den(1) - par(1) - sum
1244 1316 : tempa = prod(k, 1)*wvec(k, 2) + prod(k, 2)*wvec(k, 1)
1245 1316 : tempb = prod(k, 2)*wvec(k, 4) + prod(k, 4)*wvec(k, 2)
1246 1316 : tempc = prod(k, 3)*wvec(k, 5) + prod(k, 5)*wvec(k, 3)
1247 1316 : den(2) = den(2) - tempa - half*(tempb + tempc)
1248 1316 : den(6) = den(6) - half*(tempb - tempc)
1249 1316 : tempa = prod(k, 1)*wvec(k, 3) + prod(k, 3)*wvec(k, 1)
1250 1316 : tempb = prod(k, 2)*wvec(k, 5) + prod(k, 5)*wvec(k, 2)
1251 1316 : tempc = prod(k, 3)*wvec(k, 4) + prod(k, 4)*wvec(k, 3)
1252 1316 : den(3) = den(3) - tempa - half*(tempb - tempc)
1253 1316 : den(7) = den(7) - half*(tempb + tempc)
1254 1316 : tempa = prod(k, 1)*wvec(k, 4) + prod(k, 4)*wvec(k, 1)
1255 1316 : den(4) = den(4) - tempa - par(2) + par(3)
1256 1316 : tempa = prod(k, 1)*wvec(k, 5) + prod(k, 5)*wvec(k, 1)
1257 1316 : tempb = prod(k, 2)*wvec(k, 3) + prod(k, 3)*wvec(k, 2)
1258 1316 : den(5) = den(5) - tempa - half*tempb
1259 1316 : den(8) = den(8) - par(4) + par(5)
1260 1316 : tempa = prod(k, 4)*wvec(k, 5) + prod(k, 5)*wvec(k, 4)
1261 1504 : 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 1128 : DO i = 1, 5
1268 940 : par(i) = half*prod(knew, i)**2
1269 1128 : sum = sum + par(i)
1270 : END DO
1271 188 : denex(1) = alpha*den(1) + par(1) + sum
1272 188 : tempa = two*prod(knew, 1)*prod(knew, 2)
1273 188 : tempb = prod(knew, 2)*prod(knew, 4)
1274 188 : tempc = prod(knew, 3)*prod(knew, 5)
1275 188 : denex(2) = alpha*den(2) + tempa + tempb + tempc
1276 188 : denex(6) = alpha*den(6) + tempb - tempc
1277 188 : tempa = two*prod(knew, 1)*prod(knew, 3)
1278 188 : tempb = prod(knew, 2)*prod(knew, 5)
1279 188 : tempc = prod(knew, 3)*prod(knew, 4)
1280 188 : denex(3) = alpha*den(3) + tempa + tempb - tempc
1281 188 : denex(7) = alpha*den(7) + tempb + tempc
1282 188 : tempa = two*prod(knew, 1)*prod(knew, 4)
1283 188 : denex(4) = alpha*den(4) + tempa + par(2) - par(3)
1284 188 : tempa = two*prod(knew, 1)*prod(knew, 5)
1285 188 : denex(5) = alpha*den(5) + tempa + prod(knew, 2)*prod(knew, 3)
1286 188 : denex(8) = alpha*den(8) + par(4) - par(5)
1287 188 : 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 188 : sum = denex(1) + denex(2) + denex(4) + denex(6) + denex(8)
1292 188 : denold = sum
1293 188 : denmax = sum
1294 188 : isave = 0
1295 188 : iu = 49
1296 188 : temp = twopi/REAL(IU + 1, dp)
1297 188 : par(1) = one
1298 9400 : DO i = 1, iu
1299 9212 : angle = REAL(i, dp)*temp
1300 9212 : par(2) = COS(angle)
1301 9212 : par(3) = SIN(angle)
1302 9212 : DO j = 4, 8, 2
1303 27636 : par(j) = par(2)*par(j - 2) - par(3)*par(j - 1)
1304 27636 : par(j + 1) = par(2)*par(j - 1) + par(3)*par(j - 2)
1305 : END DO
1306 : sumold = sum
1307 : sum = zero
1308 92120 : DO j = 1, 9
1309 92120 : sum = sum + denex(j)*par(j)
1310 : END DO
1311 9400 : IF (ABS(sum) > ABS(denmax)) THEN
1312 : denmax = sum
1313 : isave = i
1314 : tempa = sumold
1315 8624 : ELSE IF (i == isave + 1) THEN
1316 330 : tempb = sum
1317 : END IF
1318 : END DO
1319 188 : IF (isave == 0) tempa = sum
1320 86 : IF (isave == iu) tempb = denold
1321 188 : step = zero
1322 188 : IF (tempa /= tempb) THEN
1323 188 : tempa = tempa - denmax
1324 188 : tempb = tempb - denmax
1325 188 : step = half*(tempa - tempb)/(tempa + tempb)
1326 : END IF
1327 188 : 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 188 : par(2) = COS(angle)
1333 188 : par(3) = SIN(angle)
1334 188 : DO j = 4, 8, 2
1335 564 : par(j) = par(2)*par(j - 2) - par(3)*par(j - 1)
1336 564 : par(j + 1) = par(2)*par(j - 1) + par(3)*par(j - 2)
1337 : END DO
1338 188 : beta = zero
1339 188 : denmax = zero
1340 1880 : DO j = 1, 9
1341 1692 : beta = beta + den(j)*par(j)
1342 1880 : denmax = denmax + denex(j)*par(j)
1343 : END DO
1344 1504 : DO k = 1, ndim
1345 1316 : vlag(k) = zero
1346 8084 : DO j = 1, 5
1347 7896 : vlag(k) = vlag(k) + prod(k, j)*par(j)
1348 : END DO
1349 : END DO
1350 188 : tau = vlag(knew)
1351 188 : dd = zero
1352 188 : tempa = zero
1353 188 : tempb = zero
1354 564 : DO i = 1, n
1355 376 : d(i) = par(2)*d(i) + par(3)*s(i)
1356 376 : w(i) = xopt(i) + d(i)
1357 376 : dd = dd + d(i)**2
1358 376 : tempa = tempa + d(i)*w(i)
1359 564 : tempb = tempb + w(i)*w(i)
1360 : END DO
1361 188 : 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 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 188 : 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 17004613 : 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 17004613 : delsq = delta*delta
1469 17004613 : 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 17004613 : iterc = 0
1475 102032378 : DO k = 1, npt
1476 102032378 : hcol(k) = zero
1477 : END DO
1478 51016189 : DO j = 1, nptm
1479 34011576 : temp = zmat(knew, j)
1480 34011576 : IF (j < idz) temp = -temp
1481 221099097 : DO k = 1, npt
1482 204094484 : hcol(k) = hcol(k) + temp*zmat(k, j)
1483 : END DO
1484 : END DO
1485 17004613 : 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 17004613 : dd = zero
1491 51016189 : DO i = 1, n
1492 34011576 : d(i) = xpt(knew, i) - xopt(i)
1493 34011576 : gc(i) = bmat(knew, i)
1494 34011576 : gd(i) = zero
1495 51016189 : dd = dd + d(i)**2
1496 : END DO
1497 102032378 : DO k = 1, npt
1498 : temp = zero
1499 : sum = zero
1500 255110673 : DO j = 1, n
1501 170082908 : temp = temp + xpt(k, j)*xopt(j)
1502 255110673 : sum = sum + xpt(k, j)*d(j)
1503 : END DO
1504 85027765 : temp = hcol(k)*temp
1505 85027765 : sum = hcol(k)*sum
1506 272115286 : DO i = 1, n
1507 170082908 : gc(i) = gc(i) + temp*xpt(k, i)
1508 255110673 : 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 51016189 : DO i = 1, n
1519 34011576 : gg = gg + gc(i)**2
1520 34011576 : sp = sp + d(i)*gc(i)
1521 51016189 : dhd = dhd + d(i)*gd(i)
1522 : END DO
1523 17004613 : scale = delta/SQRT(dd)
1524 17004613 : IF (sp*dhd < zero) scale = -scale
1525 17004613 : temp = zero
1526 17004613 : IF (sp*sp > 0.99_dp*dd*gg) temp = one
1527 17004613 : tau = scale*(ABS(sp) + half*scale*ABS(dhd))
1528 17004613 : IF (gg*delsq < 0.01_dp*tau*tau) temp = one
1529 51016189 : DO i = 1, n
1530 34011576 : d(i) = scale*d(i)
1531 34011576 : gd(i) = scale*gd(i)
1532 51016189 : 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 24079156 : iterc = iterc + 1
1541 24079156 : dd = zero
1542 24079156 : sp = zero
1543 24079156 : ss = zero
1544 72241246 : DO i = 1, n
1545 48162090 : dd = dd + d(i)**2
1546 48162090 : sp = sp + d(i)*s(i)
1547 72241246 : ss = ss + s(i)**2
1548 : END DO
1549 24079156 : temp = dd*ss - sp*sp
1550 24079156 : IF (temp <= 1.0e-8_dp*dd*ss) EXIT mainloop
1551 23022841 : denom = SQRT(temp)
1552 69072025 : DO i = 1, n
1553 46049184 : s(i) = (dd*s(i) - sp*d(i))/denom
1554 69072025 : 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 138144050 : DO k = 1, npt
1561 : sum = zero
1562 345404557 : DO j = 1, n
1563 345404557 : sum = sum + xpt(k, j)*s(j)
1564 : END DO
1565 115121209 : sum = hcol(k)*sum
1566 368427398 : DO i = 1, n
1567 345404557 : 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 69072025 : DO i = 1, n
1576 46049184 : cf1 = cf1 + s(i)*w(i)
1577 46049184 : cf2 = cf2 + d(i)*gc(i)
1578 46049184 : cf3 = cf3 + s(i)*gc(i)
1579 46049184 : cf4 = cf4 + d(i)*gd(i)
1580 69072025 : cf5 = cf5 + s(i)*gd(i)
1581 : END DO
1582 23022841 : cf1 = half*cf1
1583 23022841 : cf4 = half*cf4 - cf1
1584 : !
1585 : ! Seek the value of the angle that maximizes the modulus of TAU.
1586 : !
1587 23022841 : taubeg = cf1 + cf2 + cf4
1588 23022841 : taumax = taubeg
1589 23022841 : tauold = taubeg
1590 23022841 : isave = 0
1591 23022841 : iu = 49
1592 23022841 : temp = twopi/REAL(iu + 1, DP)
1593 1151142050 : DO i = 1, iu
1594 1128119209 : angle = REAL(i, dp)*temp
1595 1128119209 : cth = COS(angle)
1596 1128119209 : sth = SIN(angle)
1597 1128119209 : tau = cf1 + (cf2 + cf4*cth)*cth + (cf3 + cf5*cth)*sth
1598 1128119209 : IF (ABS(tau) > ABS(taumax)) THEN
1599 : taumax = tau
1600 : isave = i
1601 : tempa = tauold
1602 1069164288 : ELSE IF (i == isave + 1) THEN
1603 25033223 : tempb = taU
1604 : END IF
1605 1151142050 : tauold = tau
1606 : END DO
1607 23022841 : IF (isave == 0) tempa = tau
1608 13529385 : IF (isave == iu) tempb = taubeg
1609 23022841 : step = zero
1610 23022841 : IF (tempa /= tempb) THEN
1611 23022841 : tempa = tempa - taumax
1612 23022841 : tempb = tempb - taumax
1613 23022841 : step = half*(tempa - tempb)/(tempa + tempb)
1614 : END IF
1615 23022841 : angle = temp*(REAL(isave, DP) + step)
1616 : !
1617 : ! Calculate the new D and GD. Then test for convergence.
1618 : !
1619 23022841 : cth = COS(angle)
1620 23022841 : sth = SIN(angle)
1621 23022841 : tau = cf1 + (cf2 + cf4*cth)*cth + (cf3 + cf5*cth)*sth
1622 69072025 : DO i = 1, n
1623 46049184 : d(i) = cth*d(i) + sth*s(i)
1624 46049184 : gd(i) = cth*gd(i) + sth*w(i)
1625 69072025 : s(i) = gc(i) + gd(i)
1626 : END DO
1627 23022841 : IF (ABS(tau) <= 1.1_dp*ABS(taubeg)) EXIT mainloop
1628 24079156 : IF (iterc >= n) EXIT mainloop
1629 : END DO mainloop
1630 :
1631 17004613 : 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 41107066 : 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 41107066 : delsq = delta*delta
1692 41107066 : iterc = 0
1693 41107066 : itermax = n
1694 41107066 : itersw = itermax
1695 123325525 : DO i = 1, n
1696 123325525 : d(i) = xopt(i)
1697 : END DO
1698 41107066 : CALL updatehd
1699 : !
1700 : ! Prepare for the first line search.
1701 : !
1702 41107066 : qred = zero
1703 41107066 : dd = zero
1704 123325525 : DO i = 1, n
1705 82218459 : step(i) = zero
1706 82218459 : hs(i) = zero
1707 82218459 : g(i) = gq(i) + hd(i)
1708 82218459 : d(i) = -g(i)
1709 123325525 : dd = dd + d(i)**2
1710 : END DO
1711 41107066 : crvmin = zero
1712 41107066 : 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 69347399 : IF (.NOT. jump2) THEN
1724 69346513 : IF (.NOT. jump1) THEN
1725 69346513 : iterc = iterc + 1
1726 69346513 : temp = delsq - ss
1727 69346513 : bstep = temp/(ds + SQRT(ds*ds + dd*temp))
1728 69346513 : CALL updatehd
1729 : END IF
1730 69346513 : jump1 = .FALSE.
1731 69346513 : IF (iterc <= itersw) THEN
1732 69346513 : dhd = zero
1733 208052581 : DO j = 1, n
1734 208052581 : dhd = dhd + d(j)*hd(j)
1735 : END DO
1736 : !
1737 : ! Update CRVMIN and set the step-length ALPHA.
1738 : !
1739 69346513 : alpha = bstep
1740 69346513 : IF (dhd > zero) THEN
1741 61293011 : temp = dhd/dd
1742 61293011 : IF (iterc == 1) crvmin = temp
1743 61293011 : crvmin = MIN(crvmin, temp)
1744 61293011 : alpha = MIN(alpha, gg/dhd)
1745 : END IF
1746 69346513 : qadd = alpha*(gg - half*alpha*dhd)
1747 69346513 : qred = qred + qadd
1748 : !
1749 : ! Update STEP and HS.
1750 : !
1751 69346513 : ggsav = gg
1752 69346513 : gg = zero
1753 208052581 : DO i = 1, n
1754 138706068 : step(i) = step(i) + alpha*d(i)
1755 138706068 : hs(i) = hs(i) + alpha*hd(i)
1756 208052581 : gg = gg + (g(i) + hs(i))**2
1757 : END DO
1758 : !
1759 : ! Begin another conjugate direction iteration if required.
1760 : !
1761 69346513 : IF (alpha < bstep) THEN
1762 45570189 : IF (qadd <= 0.01_dp*qred) EXIT mainloop
1763 44883583 : IF (gg <= 1.0e-4_dp*ggbeg) EXIT mainloop
1764 28239660 : IF (iterc == itermax) EXIT mainloop
1765 28239600 : temp = gg/ggsav
1766 28239600 : dd = zero
1767 28239600 : ds = zero
1768 28239600 : ss = zero
1769 84727846 : DO i = 1, n
1770 56488246 : d(i) = temp*d(i) - g(i) - hs(i)
1771 56488246 : dd = dd + d(i)**2
1772 56488246 : ds = ds + d(i)*step(I)
1773 84727846 : ss = ss + step(i)**2
1774 : END DO
1775 28239600 : IF (ds <= zero) EXIT mainloop
1776 28239600 : IF (ss < delsq) CYCLE mainloop
1777 : END IF
1778 23776324 : crvmin = zero
1779 23776324 : itersw = iterc
1780 23776324 : jump2 = .TRUE.
1781 23776324 : 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 23422659 : IF (jump2) THEN
1791 23422659 : sg = zero
1792 23422659 : shs = zero
1793 70273910 : DO i = 1, n
1794 46851251 : sg = sg + step(i)*g(i)
1795 70273910 : shs = shs + step(i)*hs(i)
1796 : END DO
1797 23422659 : sgk = sg + shs
1798 23422659 : angtest = sgk/SQRT(gg*delsq)
1799 23422659 : 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 20450014 : iterc = iterc + 1
1805 20450014 : temp = SQRT(delsq*gg - sgk*sgk)
1806 20450014 : tempa = delsq/temp
1807 20450014 : tempb = sgk/temp
1808 61355465 : DO i = 1, n
1809 61355465 : d(i) = tempa*(g(i) + hs(i)) - tempb*step(i)
1810 : END DO
1811 20450014 : CALL updatehd
1812 20450014 : IF (iterc <= itersw) THEN
1813 : jump1 = .TRUE.
1814 : CYCLE mainloop
1815 : END IF
1816 : END IF
1817 20450014 : dg = zero
1818 20450014 : dhd = zero
1819 20450014 : dhs = zero
1820 61355465 : DO i = 1, n
1821 40905451 : dg = dg + d(i)*g(i)
1822 40905451 : dhd = dhd + hd(i)*d(i)
1823 61355465 : dhs = dhs + hd(i)*step(i)
1824 : END DO
1825 : !
1826 : ! Seek the value of the angle that minimizes Q.
1827 : !
1828 20450014 : cf = half*(shs - dhd)
1829 20450014 : qbeg = sg + cf
1830 20450014 : qsav = qbeg
1831 20450014 : qmin = qbeg
1832 20450014 : isave = 0
1833 20450014 : iu = 49
1834 20450014 : temp = twopi/REAL(iu + 1, dp)
1835 1022500700 : DO i = 1, iu
1836 1002050686 : angle = REAL(i, dp)*temp
1837 1002050686 : cth = COS(angle)
1838 1002050686 : sth = SIN(angle)
1839 1002050686 : qnew = (sg + cf*cth)*cth + (dg + dhs*cth)*sth
1840 1002050686 : IF (qnew < qmin) THEN
1841 : qmin = qnew
1842 : isave = i
1843 : tempa = qsav
1844 980765969 : ELSE IF (i == isave + 1) THEN
1845 25514563 : tempb = qnew
1846 : END IF
1847 1022500700 : qsav = qnew
1848 : END DO
1849 20450014 : IF (isave == zero) tempa = qnew
1850 8852396 : IF (isave == iu) tempb = qbeg
1851 20450014 : angle = zero
1852 20450014 : IF (tempa /= tempb) THEN
1853 20450014 : tempa = tempa - qmin
1854 20450014 : tempb = tempb - qmin
1855 20450014 : angle = half*(tempa - tempb)/(tempa + tempb)
1856 : END IF
1857 20450014 : angle = temp*(REAL(isave, DP) + angle)
1858 : !
1859 : ! Calculate the new STEP and HS. Then test for convergence.
1860 : !
1861 20450014 : cth = COS(angle)
1862 20450014 : sth = SIN(angle)
1863 20450014 : reduc = qbeg - (sg + cf*cth)*cth - (dg + dhs*cth)*sth
1864 20450014 : gg = zero
1865 61355465 : DO i = 1, n
1866 40905451 : step(i) = cth*step(i) + sth*d(i)
1867 40905451 : hs(i) = cth*hs(i) + sth*hd(i)
1868 61355465 : gg = gg + (g(i) + hs(i))**2
1869 : END DO
1870 20450014 : qred = qred + reduc
1871 20450014 : ratio = reduc/qred
1872 20450014 : IF (iterc < itermax .AND. ratio > 0.01_dp) THEN
1873 886 : jump2 = .TRUE.
1874 : ELSE
1875 : EXIT mainloop
1876 : END IF
1877 :
1878 41107799 : IF (gg <= 1.0e-4_dp*ggbeg) EXIT mainloop
1879 :
1880 : END DO mainloop
1881 :
1882 : !*******************************************************************************
1883 : CONTAINS
1884 : ! **************************************************************************************************
1885 : !> \brief ...
1886 : ! **************************************************************************************************
1887 130903593 : SUBROUTINE updatehd
1888 : INTEGER :: i, ih, j, k
1889 :
1890 392733571 : DO i = 1, n
1891 392733571 : hd(i) = zero
1892 : END DO
1893 785467142 : DO k = 1, npt
1894 654563549 : temp = zero
1895 1963958423 : DO j = 1, n
1896 1963958423 : temp = temp + xpt(k, j)*d(j)
1897 : END DO
1898 654563549 : temp = temp*pq(k)
1899 2094862016 : DO i = 1, n
1900 1963958423 : hd(i) = hd(i) + temp*xpt(k, i)
1901 : END DO
1902 : END DO
1903 130903593 : ih = 0
1904 392733571 : DO j = 1, n
1905 785539784 : DO i = 1, j
1906 392806213 : ih = ih + 1
1907 392806213 : IF (i < j) hd(j) = hd(j) + hq(ih)*d(i)
1908 654636191 : hd(i) = hd(i) + hq(ih)*d(j)
1909 : END DO
1910 : END DO
1911 130903593 : 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 47682925 : 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 47682925 : nptm = npt - n - 1
1954 : !
1955 : ! Apply the rotations that put zeros in the KNEW-th row of ZMAT.
1956 : !
1957 47682925 : jl = 1
1958 95371719 : DO j = 2, nptm
1959 95371719 : IF (j == idz) THEN
1960 : jl = idz
1961 47688794 : ELSE IF (zmat(knew, j) /= zero) THEN
1962 46395187 : temp = SQRT(zmat(knew, jl)**2 + zmat(knew, j)**2)
1963 46395187 : tempa = zmat(knew, jl)/temp
1964 46395187 : tempb = zmat(knew, j)/temp
1965 278418438 : DO I = 1, NPT
1966 232023251 : temp = tempa*zmat(i, jl) + tempb*zmat(i, j)
1967 232023251 : zmat(i, j) = tempa*zmat(i, j) - tempb*zmat(i, jl)
1968 278418438 : zmat(i, jl) = temp
1969 : END DO
1970 46395187 : 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 47682925 : tempa = zmat(knew, 1)
1978 47682925 : IF (idz >= 2) tempa = -tempa
1979 47682925 : IF (jl > 1) tempb = zmat(knew, jl)
1980 286109288 : DO i = 1, npt
1981 238426363 : w(i) = tempa*zmat(i, 1)
1982 286109288 : IF (jl > 1) w(i) = w(i) + tempb*zmat(i, jl)
1983 : END DO
1984 47682925 : alpha = w(knew)
1985 47682925 : tau = vlag(knew)
1986 47682925 : tausq = tau*tau
1987 47682925 : denom = alpha*beta + tausq
1988 47682925 : 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 47682925 : iflag = 0
1995 47682925 : IF (JL == 1) THEN
1996 47682925 : temp = SQRT(ABS(denom))
1997 47682925 : tempb = tempa/temp
1998 47682925 : tempa = tau/temp
1999 286109288 : DO i = 1, npt
2000 286109288 : zmat(i, 1) = tempa*zmat(i, 1) - tempb*vlag(i)
2001 : END DO
2002 47682925 : IF (idz == 1 .AND. temp < zero) idz = 2
2003 47682925 : 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 143054644 : DO j = 1, n
2042 95371719 : jp = npt + j
2043 95371719 : w(jp) = bmat(knew, j)
2044 95371719 : tempa = (alpha*vlag(jp) - tau*w(jp))/denom
2045 95371719 : tempb = (-beta*w(jp) - tau*vlag(jp))/denom
2046 763048190 : DO i = 1, jp
2047 619993546 : bmat(i, j) = bmat(i, j) + tempa*vlag(i) + tempb*w(i)
2048 715365265 : IF (i > npt) bmat(jp, i - npt) = bmat(i, j)
2049 : END DO
2050 : END DO
2051 :
2052 47682925 : END SUBROUTINE update
2053 :
2054 0 : END MODULE powell
2055 :
2056 : !******************************************************************************
|