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 54343991 : 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 54343991 : CALL timeset(routineN, handle)
64 :
65 55033475 : SELECT CASE (optstate%state)
66 : CASE (0)
67 689484 : npt = 2*n + 1
68 2068452 : ALLOCATE (optstate%w((npt + 13)*(npt + n) + 3*n*(n + 3)/2))
69 2068452 : ALLOCATE (optstate%xopt(n))
70 : ! Initialize w
71 98044419 : optstate%w = 0.0_dp
72 689484 : optstate%state = 1
73 689484 : CALL newuoa(n, x, optstate)
74 : CASE (1, 2)
75 52275541 : 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 689469 : optstate%state = -1
93 : CASE (8)
94 2068773 : x(1:n) = optstate%xopt(1:n)
95 689484 : DEALLOCATE (optstate%w)
96 689484 : DEALLOCATE (optstate%xopt)
97 689484 : optstate%state = -1
98 : CASE DEFAULT
99 54343991 : CPABORT("")
100 : END SELECT
101 :
102 54343991 : CALL timestop(handle)
103 :
104 54343991 : END SUBROUTINE powell_optimize
105 : !******************************************************************************
106 : ! **************************************************************************************************
107 : !> \brief ...
108 : !> \param n ...
109 : !> \param x ...
110 : !> \param optstate ...
111 : ! **************************************************************************************************
112 52965025 : 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 52965025 : maxfun = optstate%maxfun
124 52965025 : rhobeg = optstate%rhobeg
125 52965025 : 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 52965025 : np = n + 1
162 52965025 : npt = 2*n + 1
163 52965025 : nptm = npt - np
164 52965025 : IF (npt < n + 2 .OR. npt > ((n + 2)*np)/2) THEN
165 0 : optstate%state = 5
166 0 : RETURN
167 : END IF
168 52965025 : ndim = npt + n
169 52965025 : ixb = 1
170 52965025 : ixo = ixb + n
171 52965025 : ixn = ixo + n
172 52965025 : ixp = ixn + n
173 52965025 : ifv = ixp + n*npt
174 52965025 : igq = ifv + npt
175 52965025 : ihq = igq + n
176 52965025 : ipq = ihq + (n*np)/2
177 52965025 : ibmat = ipq + npt
178 52965025 : izmat = ibmat + ndim*n
179 52965025 : id = izmat + npt*nptm
180 52965025 : ivl = id + n
181 52965025 : 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 52965025 : optstate%w(ivl:), optstate%w(iw:), optstate)
191 :
192 158906799 : 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 52965025 : SUBROUTINE newuob(n, npt, x, rhobeg, rhoend, maxfun, xbase, &
222 52965025 : 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 52965025 : 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 689484 : idz = 0
283 689484 : itest = 0
284 689484 : nf = 0
285 689484 : nfm = 0
286 689484 : nfmm = 0
287 689484 : nfsav = 0
288 689484 : knew = 0
289 689484 : kopt = 0
290 689484 : ksave = 0
291 689484 : ktemp = 0
292 689484 : rhosq = 0._dp
293 689484 : recip = 0._dp
294 689484 : reciq = 0._dp
295 689484 : fbeg = 0._dp
296 689484 : fopt = 0._dp
297 689484 : diffa = 0._dp
298 689484 : xoptsq = 0._dp
299 689484 : rho = 0._dp
300 689484 : delta = 0._dp
301 689484 : dsq = 0._dp
302 689484 : dnorm = 0._dp
303 689484 : ratio = 0._dp
304 689484 : temp = 0._dp
305 689484 : tempq = 0._dp
306 689484 : beta = 0._dp
307 689484 : dx = 0._dp
308 689484 : vquad = 0._dp
309 689484 : diff = 0._dp
310 689484 : diffc = 0._dp
311 689484 : diffb = 0._dp
312 689484 : fsave = 0._dp
313 689484 : detrat = 0._dp
314 689484 : hdiag = 0._dp
315 689484 : distsq = 0._dp
316 689484 : gisq = 0._dp
317 689484 : gqsq = 0._dp
318 689484 : f = 0._dp
319 689484 : bstep = 0._dp
320 689484 : alpha = 0._dp
321 689484 : dstep = 0._dp
322 : !
323 : END IF
324 :
325 52965025 : ipt = 0
326 52965025 : jpt = 0
327 52965025 : xipt = 0._dp
328 52965025 : xjpt = 0._dp
329 :
330 52965025 : half = 0.5_dp
331 52965025 : one = 1.0_dp
332 52965025 : tenth = 0.1_dp
333 52965025 : zero = 0.0_dp
334 52965025 : np = n + 1
335 52965025 : nh = (n*np)/2
336 52965025 : nptm = npt - np
337 52965025 : nftest = MAX(maxfun, 1)
338 :
339 52965025 : IF (opt%state == 2) GOTO 1000
340 : !
341 : ! Set the initial elements of XPT, BMAT, HQ, PQ and ZMAT to zero.
342 : !
343 2068773 : DO j = 1, n
344 1379289 : xbase(j) = x(j)
345 8307016 : DO k = 1, npt
346 8307016 : xpt(k, j) = zero
347 : END DO
348 11770719 : DO i = 1, ndim
349 11081235 : bmat(i, j) = zero
350 : END DO
351 : END DO
352 2766238 : DO ih = 1, nh
353 2766238 : hq(ih) = zero
354 : END DO
355 4137546 : DO k = 1, npt
356 3448062 : pq(k) = zero
357 11065273 : DO j = 1, nptm
358 10375789 : 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 689484 : rhosq = rhobeg*rhobeg
367 689484 : recip = one/rhosq
368 689484 : reciq = SQRT(half)/rhosq
369 689484 : nf = 0
370 3447599 : 50 nfm = nf
371 3447599 : nfmm = nf - n
372 3447599 : nf = nf + 1
373 3447599 : IF (nfm <= 2*n) THEN
374 3447599 : IF (nfm >= 1 .AND. nfm <= N) THEN
375 1379094 : xpt(nf, nfm) = rhobeg
376 2068505 : ELSE IF (nfm > n) THEN
377 1379021 : 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 10348471 : DO j = 1, n
401 10348471 : x(j) = xpt(nf, j) + xbase(j)
402 : END DO
403 3447591 : GOTO 310
404 3447591 : 70 fval(nf) = f
405 3447591 : IF (nf == 1) THEN
406 689484 : fbeg = f
407 689484 : fopt = f
408 689484 : kopt = 1
409 2758107 : ELSE IF (f < fopt) THEN
410 768489 : fopt = f
411 768489 : 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 3447591 : IF (NFM <= 2*N) THEN
418 3447591 : IF (nfm >= 1 .AND. nfm <= n) THEN
419 1379086 : gq(nfm) = (f - fbeg)/rhobeg
420 1379086 : 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 2068505 : ELSE IF (nfm > n) THEN
426 1379021 : bmat(nf - n, nfmm) = half/rhobeg
427 1379021 : bmat(nf, nfmm) = -half/rhobeg
428 1379021 : zmat(1, nfmm) = -reciq - reciq
429 1379021 : zmat(nf - n, nfmm) = reciq
430 1379021 : zmat(nf, nfmm) = reciq
431 1379021 : ih = (nfmm*(nfmm + 1))/2
432 1379021 : temp = (fbeg - f)/rhobeg
433 1379021 : hq(ih) = (gq(nfmm) - temp)/rhobeg
434 1379021 : 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 3447591 : IF (nf < npt) GOTO 50
451 : !
452 : ! Begin the iterative procedure, because the initial model is comple
453 : !
454 689476 : rho = rhobeg
455 689476 : delta = rho
456 689476 : idz = 1
457 689476 : diffa = zero
458 689476 : diffb = zero
459 689476 : itest = 0
460 689476 : xoptsq = zero
461 2068497 : DO i = 1, n
462 1379021 : xopt(i) = xpt(kopt, i)
463 2068497 : xoptsq = xoptsq + xopt(i)**2
464 : END DO
465 4137052 : 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 41246682 : 100 knew = 0
471 41246682 : CALL trsapp(n, npt, xopt, xpt, gq, hq, pq, delta, d, w, w(np), w(np + n), w(np + 2*n), crvmin)
472 41246682 : dsq = zero
473 123744373 : DO i = 1, n
474 123744373 : dsq = dsq + d(i)**2
475 : END DO
476 41246682 : dnorm = MIN(delta, SQRT(dsq))
477 41246682 : IF (dnorm < half*rho) THEN
478 10055372 : knew = -1
479 10055372 : delta = tenth*delta
480 10055372 : ratio = -1.0_dp
481 10055372 : IF (delta <= 1.5_dp*rho) delta = rho
482 10055372 : IF (nf <= nfsav + 2) GOTO 460
483 2781064 : temp = 0.125_dp*crvmin*rho*rho
484 2781064 : 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 48253529 : 120 IF (dsq <= 1.0e-3_dp*xoptsq) THEN
492 2958177 : tempq = 0.25_dp*xoptsq
493 17749362 : DO k = 1, npt
494 : sum = zero
495 44375257 : DO i = 1, n
496 44375257 : sum = sum + xpt(k, i)*xopt(i)
497 : END DO
498 14791185 : temp = pq(k)*sum
499 14791185 : sum = sum - half*xoptsq
500 14791185 : w(npt + k) = sum
501 47333434 : DO i = 1, n
502 29584072 : gq(i) = gq(i) + temp*xpt(k, i)
503 29584072 : xpt(k, i) = xpt(k, i) - half*xopt(i)
504 29584072 : vlag(i) = bmat(k, i)
505 29584072 : w(i) = sum*xpt(k, i) + tempq*xopt(i)
506 29584072 : ip = npt + i
507 88755841 : DO j = 1, i
508 73964656 : 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 8874681 : DO k = 1, nptm
516 : sumz = zero
517 35500576 : DO i = 1, npt
518 29584072 : sumz = sumz + zmat(i, k)
519 35500576 : w(i) = w(npt + i)*zmat(i, k)
520 : END DO
521 17750288 : DO j = 1, n
522 11833784 : sum = tempq*sumz*xopt(j)
523 71010880 : DO i = 1, npt
524 59177096 : sum = sum + w(i)*xpt(i, j)
525 59177096 : vlag(j) = sum
526 71010880 : IF (k < idz) sum = -sum
527 : END DO
528 76927384 : DO i = 1, npt
529 71010880 : bmat(i, j) = bmat(i, j) + sum*zmat(i, k)
530 : END DO
531 : END DO
532 20708465 : DO i = 1, n
533 11833784 : ip = i + npt
534 11833784 : temp = vlag(i)
535 11833784 : IF (k < idz) temp = -temp
536 35503008 : DO j = 1, i
537 29586504 : 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 8874681 : DO j = 1, n
547 5916504 : w(j) = zero
548 35500576 : DO k = 1, npt
549 29584072 : w(j) = w(j) + pq(k)*xpt(k, j)
550 35500576 : xpt(k, j) = xpt(k, j) - half*xopt(j)
551 : END DO
552 17749825 : DO i = 1, j
553 8875144 : ih = ih + 1
554 8875144 : IF (i < j) gq(j) = gq(j) + hq(ih)*xopt(i)
555 8875144 : gq(i) = gq(i) + hq(ih)*xopt(j)
556 8875144 : hq(ih) = hq(ih) + w(i)*xopt(j) + xopt(i)*w(j)
557 14791648 : bmat(npt + i, j) = bmat(npt + j, i)
558 : END DO
559 : END DO
560 8874681 : DO j = 1, n
561 5916504 : xbase(j) = xbase(j) + xopt(j)
562 8874681 : xopt(j) = zero
563 : END DO
564 2958177 : 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 48253529 : IF (knew > 0) THEN
572 : CALL biglag(n, npt, xopt, xpt, bmat, zmat, idz, ndim, knew, dstep, &
573 17062219 : 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 289533066 : DO k = 1, npt
580 : suma = zero
581 : sumb = zero
582 : sum = zero
583 723907325 : DO j = 1, n
584 482627788 : suma = suma + xpt(k, j)*d(j)
585 482627788 : sumb = sumb + xpt(k, j)*xopt(j)
586 723907325 : sum = sum + bmat(k, j)*d(j)
587 : END DO
588 241279537 : w(k) = suma*(half*suma + sumb)
589 289533066 : vlag(k) = sum
590 : END DO
591 48253529 : beta = zero
592 144766533 : DO k = 1, nptm
593 : sum = zero
594 579140792 : DO i = 1, npt
595 579140792 : sum = sum + zmat(i, k)*w(i)
596 : END DO
597 96513004 : IF (k < idz) THEN
598 0 : beta = beta + sum*sum
599 0 : sum = -sum
600 : ELSE
601 96513004 : beta = beta - sum*sum
602 : END IF
603 627394321 : DO i = 1, npt
604 579140792 : vlag(i) = vlag(i) + sum*zmat(i, k)
605 : END DO
606 : END DO
607 48253529 : bsum = zero
608 48253529 : dx = zero
609 144766533 : DO j = 1, n
610 : sum = zero
611 579140792 : DO i = 1, npt
612 579140792 : sum = sum + w(i)*bmat(i, j)
613 : END DO
614 96513004 : bsum = bsum + sum*d(j)
615 96513004 : jp = npt + j
616 289570396 : DO k = 1, n
617 289570396 : sum = sum + bmat(jp, k)*d(k)
618 : END DO
619 96513004 : vlag(jp) = sum
620 96513004 : bsum = bsum + sum*d(j)
621 144766533 : dx = dx + d(j)*xopt(j)
622 : END DO
623 48253529 : beta = dx*dx + dsq*(xoptsq + dx + dx + half*dsq) + beta - bsum
624 48253529 : 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 48253529 : IF (knew > 0) THEN
631 17062219 : temp = one + alpha*beta/vlag(knew)**2
632 17062219 : 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 146489845 : 290 DO i = 1, n
641 97661892 : xnew(i) = xopt(i) + d(i)
642 146489845 : x(i) = xbase(i) + xnew(i)
643 : END DO
644 48827953 : nf = nf + 1
645 52275552 : 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 52275541 : CALL get_state
654 :
655 52275541 : opt%state = 2
656 :
657 52275541 : RETURN
658 :
659 : 1000 CONTINUE
660 :
661 52275541 : CALL set_state
662 :
663 52275541 : IF (nf <= npt) GOTO 70
664 48827950 : IF (knew == -1) THEN
665 574424 : opt%state = 6
666 574424 : CALL get_state
667 574424 : 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 48253526 : vquad = zero
674 48253526 : ih = 0
675 144766519 : DO j = 1, n
676 96512993 : vquad = vquad + d(j)*gq(j)
677 289551683 : DO i = 1, j
678 144785164 : ih = ih + 1
679 144785164 : temp = d(i)*xnew(j) + d(j)*xopt(i)
680 144785164 : IF (i == j) temp = half*temp
681 241298157 : vquad = vquad + temp*hq(ih)
682 : END DO
683 : END DO
684 289533038 : DO k = 1, npt
685 289533038 : vquad = vquad + pq(k)*w(k)
686 : END DO
687 48253526 : diff = f - fopt - vquad
688 48253526 : diffc = diffb
689 48253526 : diffb = diffa
690 48253526 : diffa = ABS(diff)
691 48253526 : 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 48253526 : fsave = fopt
698 48253526 : IF (f < fopt) THEN
699 24677180 : fopt = f
700 24677180 : xoptsq = zero
701 74033437 : DO i = 1, n
702 49356257 : xopt(i) = xnew(i)
703 74033437 : xoptsq = xoptsq + xopt(i)**2
704 : END DO
705 : END IF
706 48253526 : ksave = knew
707 48253526 : IF (knew > 0) GOTO 410
708 : !
709 : ! Pick the next value of DELTA after a trust region step.
710 : !
711 31191309 : 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 31191305 : ratio = (f - fsave)/vquad
718 31191305 : IF (ratio <= tenth) THEN
719 11541111 : delta = half*dnorm
720 19650194 : ELSE IF (ratio <= 0.7_dp) THEN
721 3391282 : delta = MAX(half*delta, dnorm)
722 : ELSE
723 16258912 : delta = MAX(half*delta, dnorm + dnorm)
724 : END IF
725 31191305 : 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 31191305 : rhosq = MAX(tenth*delta, rho)**2
730 31191305 : ktemp = 0
731 31191305 : detrat = zero
732 31191305 : IF (f >= fsave) THEN
733 9901953 : ktemp = kopt
734 9901953 : detrat = one
735 : END IF
736 187155012 : DO k = 1, npt
737 155963707 : hdiag = zero
738 467932382 : DO j = 1, nptm
739 311968675 : temp = one
740 311968675 : IF (j < idz) temp = -one
741 467932382 : hdiag = hdiag + temp*zmat(k, j)**2
742 : END DO
743 155963707 : temp = ABS(beta*hdiag + vlag(k)**2)
744 155963707 : distsq = zero
745 467932382 : DO j = 1, n
746 467932382 : distsq = distsq + (xpt(k, j) - xopt(j))**2
747 : END DO
748 155963707 : IF (distsq > rhosq) temp = temp*(distsq/rhosq)**3
749 187155012 : IF (temp > detrat .AND. k /= ktemp) THEN
750 67153080 : detrat = temp
751 67153080 : knew = k
752 : END IF
753 : END DO
754 31191305 : 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 47845697 : 410 CALL update(n, npt, bmat, zmat, idz, ndim, vlag, beta, knew, w)
761 47845697 : fval(knew) = f
762 47845697 : ih = 0
763 143542960 : DO i = 1, n
764 95697263 : temp = pq(knew)*xpt(knew, i)
765 287104329 : DO j = 1, i
766 143561369 : ih = ih + 1
767 239258632 : hq(ih) = hq(ih) + temp*xpt(knew, j)
768 : END DO
769 : END DO
770 47845697 : 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 143542960 : DO j = 1, nptm
776 95697263 : temp = diff*zmat(knew, j)
777 95697263 : IF (j < idz) temp = -temp
778 622091173 : DO k = 1, npt
779 574245476 : pq(k) = pq(k) + temp*zmat(k, j)
780 : END DO
781 : END DO
782 47845697 : gqsq = zero
783 143542960 : DO i = 1, n
784 95697263 : gq(i) = gq(i) + diff*bmat(knew, i)
785 95697263 : gqsq = gqsq + gq(i)**2
786 143542960 : 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 47845697 : IF (ksave == 0 .AND. delta == rho) THEN
794 6195754 : IF (ABS(ratio) > 1.0e-2_dp) THEN
795 4162631 : itest = 0
796 : ELSE
797 12198832 : DO k = 1, npt
798 12198832 : vlag(k) = fval(k) - fval(kopt)
799 : END DO
800 2033123 : gisq = zero
801 6099416 : DO i = 1, n
802 : sum = zero
803 24398272 : DO k = 1, npt
804 24398272 : sum = sum + bmat(k, i)*vlag(k)
805 : END DO
806 4066293 : gisq = gisq + sum*sum
807 6099416 : 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 2033123 : itest = itest + 1
814 2033123 : IF (gqsq < 1.0e2_dp*gisq) itest = 0
815 2033123 : IF (itest >= 3) THEN
816 348981 : DO i = 1, n
817 348981 : gq(i) = w(i)
818 : END DO
819 465308 : DO ih = 1, nh
820 465308 : hq(ih) = zero
821 : END DO
822 348981 : DO j = 1, nptm
823 232654 : w(j) = zero
824 1395924 : DO k = 1, npt
825 1395924 : w(j) = w(j) + vlag(k)*zmat(k, j)
826 : END DO
827 348981 : IF (j < idz) w(j) = -w(j)
828 : END DO
829 697962 : DO k = 1, npt
830 581635 : pq(k) = zero
831 1861232 : DO j = 1, nptm
832 1744905 : pq(k) = pq(k) + zmat(k, j)*w(j)
833 : END DO
834 : END DO
835 116327 : itest = 0
836 : END IF
837 : END IF
838 : END IF
839 47845697 : 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 47845697 : IF (f <= fsave + tenth*vquad) GOTO 100
846 24035314 : 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 20161162 : knew = 0
852 20161162 : 460 distsq = 4.0_dp*delta*delta
853 120972284 : DO k = 1, npt
854 100811122 : sum = zero
855 302464578 : DO j = 1, n
856 302464578 : sum = sum + (xpt(k, j) - xopt(j))**2
857 : END DO
858 120972284 : IF (sum > distsq) THEN
859 27561867 : knew = k
860 27561867 : 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 20161162 : IF (knew > 0) THEN
868 17062219 : dstep = MAX(MIN(tenth*SQRT(distsq), half*delta), rho)
869 17062219 : dsq = dstep*dstep
870 17062219 : GOTO 120
871 : END IF
872 3098943 : IF (ratio > zero) GOTO 100
873 2898920 : 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 4137045 : 490 IF (rho > rhoend) THEN
879 3447576 : delta = half*rho
880 3447576 : ratio = rho/rhoend
881 3447576 : IF (ratio <= 16.0_dp) THEN
882 689463 : rho = rhoend
883 2758113 : ELSE IF (ratio <= 250.0_dp) THEN
884 689463 : rho = SQRT(ratio)*rhoend
885 : ELSE
886 2068650 : rho = tenth*rho
887 : END IF
888 3447576 : delta = MAX(delta, rho)
889 3447576 : 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 689469 : IF (knew == -1) GOTO 290
896 115045 : opt%state = 7
897 115045 : CALL get_state
898 689484 : 530 IF (fopt <= f) THEN
899 644749 : DO i = 1, n
900 644749 : x(i) = xbase(i) + xopt(i)
901 : END DO
902 214810 : f = fopt
903 : END IF
904 :
905 689484 : CALL get_state
906 :
907 : !******************************************************************************
908 : CONTAINS
909 : !******************************************************************************
910 : ! **************************************************************************************************
911 : !> \brief ...
912 : ! **************************************************************************************************
913 53654509 : SUBROUTINE get_state()
914 53654509 : opt%np = np
915 53654509 : opt%nh = nh
916 53654509 : opt%nptm = nptm
917 53654509 : opt%nftest = nftest
918 53654509 : opt%idz = idz
919 53654509 : opt%itest = itest
920 53654509 : opt%nf = nf
921 53654509 : opt%nfm = nfm
922 53654509 : opt%nfmm = nfmm
923 53654509 : opt%nfsav = nfsav
924 53654509 : opt%knew = knew
925 53654509 : opt%kopt = kopt
926 53654509 : opt%ksave = ksave
927 53654509 : opt%ktemp = ktemp
928 53654509 : opt%rhosq = rhosq
929 53654509 : opt%recip = recip
930 53654509 : opt%reciq = reciq
931 53654509 : opt%fbeg = fbeg
932 53654509 : opt%fopt = fopt
933 53654509 : opt%diffa = diffa
934 53654509 : opt%xoptsq = xoptsq
935 53654509 : opt%rho = rho
936 53654509 : opt%delta = delta
937 53654509 : opt%dsq = dsq
938 53654509 : opt%dnorm = dnorm
939 53654509 : opt%ratio = ratio
940 53654509 : opt%temp = temp
941 53654509 : opt%tempq = tempq
942 53654509 : opt%beta = beta
943 53654509 : opt%dx = dx
944 53654509 : opt%vquad = vquad
945 53654509 : opt%diff = diff
946 53654509 : opt%diffc = diffc
947 53654509 : opt%diffb = diffb
948 53654509 : opt%fsave = fsave
949 53654509 : opt%detrat = detrat
950 53654509 : opt%hdiag = hdiag
951 53654509 : opt%distsq = distsq
952 53654509 : opt%gisq = gisq
953 53654509 : opt%gqsq = gqsq
954 53654509 : opt%f = f
955 53654509 : opt%bstep = bstep
956 53654509 : opt%alpha = alpha
957 53654509 : opt%dstep = dstep
958 53654509 : END SUBROUTINE get_state
959 :
960 : !******************************************************************************
961 : ! **************************************************************************************************
962 : !> \brief ...
963 : ! **************************************************************************************************
964 52275541 : SUBROUTINE set_state()
965 52275541 : np = opt%np
966 52275541 : nh = opt%nh
967 52275541 : nptm = opt%nptm
968 52275541 : nftest = opt%nftest
969 52275541 : idz = opt%idz
970 52275541 : itest = opt%itest
971 52275541 : nf = opt%nf
972 52275541 : nfm = opt%nfm
973 52275541 : nfmm = opt%nfmm
974 52275541 : nfsav = opt%nfsav
975 52275541 : knew = opt%knew
976 52275541 : kopt = opt%kopt
977 52275541 : ksave = opt%ksave
978 52275541 : ktemp = opt%ktemp
979 52275541 : rhosq = opt%rhosq
980 52275541 : recip = opt%recip
981 52275541 : reciq = opt%reciq
982 52275541 : fbeg = opt%fbeg
983 52275541 : fopt = opt%fopt
984 52275541 : diffa = opt%diffa
985 52275541 : xoptsq = opt%xoptsq
986 52275541 : rho = opt%rho
987 52275541 : delta = opt%delta
988 52275541 : dsq = opt%dsq
989 52275541 : dnorm = opt%dnorm
990 52275541 : ratio = opt%ratio
991 52275541 : temp = opt%temp
992 52275541 : tempq = opt%tempq
993 52275541 : beta = opt%beta
994 52275541 : dx = opt%dx
995 52275541 : vquad = opt%vquad
996 52275541 : diff = opt%diff
997 52275541 : diffc = opt%diffc
998 52275541 : diffb = opt%diffb
999 52275541 : fsave = opt%fsave
1000 52275541 : detrat = opt%detrat
1001 52275541 : hdiag = opt%hdiag
1002 52275541 : distsq = opt%distsq
1003 52275541 : gisq = opt%gisq
1004 52275541 : gqsq = opt%gqsq
1005 52275541 : f = opt%f
1006 52275541 : bstep = opt%bstep
1007 52275541 : alpha = opt%alpha
1008 52275541 : dstep = opt%dstep
1009 52275541 : 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 17062219 : 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 17062219 : delsq = delta*delta
1469 17062219 : 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 17062219 : iterc = 0
1475 102378014 : DO k = 1, npt
1476 102378014 : hcol(k) = zero
1477 : END DO
1478 51189007 : DO j = 1, nptm
1479 34126788 : temp = zmat(knew, j)
1480 34126788 : IF (j < idz) temp = -temp
1481 221847975 : DO k = 1, npt
1482 204785756 : hcol(k) = hcol(k) + temp*zmat(k, j)
1483 : END DO
1484 : END DO
1485 17062219 : 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 17062219 : dd = zero
1491 51189007 : DO i = 1, n
1492 34126788 : d(i) = xpt(knew, i) - xopt(i)
1493 34126788 : gc(i) = bmat(knew, i)
1494 34126788 : gd(i) = zero
1495 51189007 : dd = dd + d(i)**2
1496 : END DO
1497 102378014 : DO k = 1, npt
1498 : temp = zero
1499 : sum = zero
1500 255974763 : DO j = 1, n
1501 170658968 : temp = temp + xpt(k, j)*xopt(j)
1502 255974763 : sum = sum + xpt(k, j)*d(j)
1503 : END DO
1504 85315795 : temp = hcol(k)*temp
1505 85315795 : sum = hcol(k)*sum
1506 273036982 : DO i = 1, n
1507 170658968 : gc(i) = gc(i) + temp*xpt(k, i)
1508 255974763 : 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 51189007 : DO i = 1, n
1519 34126788 : gg = gg + gc(i)**2
1520 34126788 : sp = sp + d(i)*gc(i)
1521 51189007 : dhd = dhd + d(i)*gd(i)
1522 : END DO
1523 17062219 : scale = delta/SQRT(dd)
1524 17062219 : IF (sp*dhd < zero) scale = -scale
1525 17062219 : temp = zero
1526 17062219 : IF (sp*sp > 0.99_dp*dd*gg) temp = one
1527 17062219 : tau = scale*(ABS(sp) + half*scale*ABS(dhd))
1528 17062219 : IF (gg*delsq < 0.01_dp*tau*tau) temp = one
1529 51189007 : DO i = 1, n
1530 34126788 : d(i) = scale*d(i)
1531 34126788 : gd(i) = scale*gd(i)
1532 51189007 : 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 24160928 : iterc = iterc + 1
1541 24160928 : dd = zero
1542 24160928 : sp = zero
1543 24160928 : ss = zero
1544 72486562 : DO i = 1, n
1545 48325634 : dd = dd + d(i)**2
1546 48325634 : sp = sp + d(i)*s(i)
1547 72486562 : ss = ss + s(i)**2
1548 : END DO
1549 24160928 : temp = dd*ss - sp*sp
1550 24160928 : IF (temp <= 1.0e-8_dp*dd*ss) EXIT mainloop
1551 23101359 : denom = SQRT(temp)
1552 69307579 : DO i = 1, n
1553 46206220 : s(i) = (dd*s(i) - sp*d(i))/denom
1554 69307579 : 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 138615158 : DO k = 1, npt
1561 : sum = zero
1562 346582327 : DO j = 1, n
1563 346582327 : sum = sum + xpt(k, j)*s(j)
1564 : END DO
1565 115513799 : sum = hcol(k)*sum
1566 369683686 : DO i = 1, n
1567 346582327 : 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 69307579 : DO i = 1, n
1576 46206220 : cf1 = cf1 + s(i)*w(i)
1577 46206220 : cf2 = cf2 + d(i)*gc(i)
1578 46206220 : cf3 = cf3 + s(i)*gc(i)
1579 46206220 : cf4 = cf4 + d(i)*gd(i)
1580 69307579 : cf5 = cf5 + s(i)*gd(i)
1581 : END DO
1582 23101359 : cf1 = half*cf1
1583 23101359 : cf4 = half*cf4 - cf1
1584 : !
1585 : ! Seek the value of the angle that maximizes the modulus of TAU.
1586 : !
1587 23101359 : taubeg = cf1 + cf2 + cf4
1588 23101359 : taumax = taubeg
1589 23101359 : tauold = taubeg
1590 23101359 : isave = 0
1591 23101359 : iu = 49
1592 23101359 : temp = twopi/REAL(iu + 1, DP)
1593 1155067950 : DO i = 1, iu
1594 1131966591 : angle = REAL(i, dp)*temp
1595 1131966591 : cth = COS(angle)
1596 1131966591 : sth = SIN(angle)
1597 1131966591 : tau = cf1 + (cf2 + cf4*cth)*cth + (cf3 + cf5*cth)*sth
1598 1131966591 : IF (ABS(tau) > ABS(taumax)) THEN
1599 : taumax = tau
1600 : isave = i
1601 : tempa = tauold
1602 1072810966 : ELSE IF (i == isave + 1) THEN
1603 25118921 : tempb = taU
1604 : END IF
1605 1155067950 : tauold = tau
1606 : END DO
1607 23101359 : IF (isave == 0) tempa = tau
1608 13575495 : IF (isave == iu) tempb = taubeg
1609 23101359 : step = zero
1610 23101359 : IF (tempa /= tempb) THEN
1611 23101359 : tempa = tempa - taumax
1612 23101359 : tempb = tempb - taumax
1613 23101359 : step = half*(tempa - tempb)/(tempa + tempb)
1614 : END IF
1615 23101359 : angle = temp*(REAL(isave, DP) + step)
1616 : !
1617 : ! Calculate the new D and GD. Then test for convergence.
1618 : !
1619 23101359 : cth = COS(angle)
1620 23101359 : sth = SIN(angle)
1621 23101359 : tau = cf1 + (cf2 + cf4*cth)*cth + (cf3 + cf5*cth)*sth
1622 69307579 : DO i = 1, n
1623 46206220 : d(i) = cth*d(i) + sth*s(i)
1624 46206220 : gd(i) = cth*gd(i) + sth*w(i)
1625 69307579 : s(i) = gc(i) + gd(i)
1626 : END DO
1627 23101359 : IF (ABS(tau) <= 1.1_dp*ABS(taubeg)) EXIT mainloop
1628 24160928 : IF (iterc >= n) EXIT mainloop
1629 : END DO mainloop
1630 :
1631 17062219 : 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 41246682 : 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 41246682 : delsq = delta*delta
1692 41246682 : iterc = 0
1693 41246682 : itermax = n
1694 41246682 : itersw = itermax
1695 123744373 : DO i = 1, n
1696 123744373 : d(i) = xopt(i)
1697 : END DO
1698 41246682 : CALL updatehd
1699 : !
1700 : ! Prepare for the first line search.
1701 : !
1702 41246682 : qred = zero
1703 41246682 : dd = zero
1704 123744373 : DO i = 1, n
1705 82497691 : step(i) = zero
1706 82497691 : hs(i) = zero
1707 82497691 : g(i) = gq(i) + hd(i)
1708 82497691 : d(i) = -g(i)
1709 123744373 : dd = dd + d(i)**2
1710 : END DO
1711 41246682 : crvmin = zero
1712 41246682 : 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 69583701 : IF (.NOT. jump2) THEN
1724 69582815 : IF (.NOT. jump1) THEN
1725 69582815 : iterc = iterc + 1
1726 69582815 : temp = delsq - ss
1727 69582815 : bstep = temp/(ds + SQRT(ds*ds + dd*temp))
1728 69582815 : CALL updatehd
1729 : END IF
1730 69582815 : jump1 = .FALSE.
1731 69582815 : IF (iterc <= itersw) THEN
1732 69582815 : dhd = zero
1733 208761487 : DO j = 1, n
1734 208761487 : dhd = dhd + d(j)*hd(j)
1735 : END DO
1736 : !
1737 : ! Update CRVMIN and set the step-length ALPHA.
1738 : !
1739 69582815 : alpha = bstep
1740 69582815 : IF (dhd > zero) THEN
1741 61501039 : temp = dhd/dd
1742 61501039 : IF (iterc == 1) crvmin = temp
1743 61501039 : crvmin = MIN(crvmin, temp)
1744 61501039 : alpha = MIN(alpha, gg/dhd)
1745 : END IF
1746 69582815 : qadd = alpha*(gg - half*alpha*dhd)
1747 69582815 : qred = qred + qadd
1748 : !
1749 : ! Update STEP and HS.
1750 : !
1751 69582815 : ggsav = gg
1752 69582815 : gg = zero
1753 208761487 : DO i = 1, n
1754 139178672 : step(i) = step(i) + alpha*d(i)
1755 139178672 : hs(i) = hs(i) + alpha*hd(i)
1756 208761487 : gg = gg + (g(i) + hs(i))**2
1757 : END DO
1758 : !
1759 : ! Begin another conjugate direction iteration if required.
1760 : !
1761 69582815 : IF (alpha < bstep) THEN
1762 45724763 : IF (qadd <= 0.01_dp*qred) EXIT mainloop
1763 45035675 : IF (gg <= 1.0e-4_dp*ggbeg) EXIT mainloop
1764 28336346 : IF (iterc == itermax) EXIT mainloop
1765 28336286 : temp = gg/ggsav
1766 28336286 : dd = zero
1767 28336286 : ds = zero
1768 28336286 : ss = zero
1769 85017904 : DO i = 1, n
1770 56681618 : d(i) = temp*d(i) - g(i) - hs(i)
1771 56681618 : dd = dd + d(i)**2
1772 56681618 : ds = ds + d(i)*step(I)
1773 85017904 : ss = ss + step(i)**2
1774 : END DO
1775 28336286 : IF (ds <= zero) EXIT mainloop
1776 28336286 : IF (ss < delsq) CYCLE mainloop
1777 : END IF
1778 23858052 : crvmin = zero
1779 23858052 : itersw = iterc
1780 23858052 : jump2 = .TRUE.
1781 23858052 : 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 23503123 : IF (jump2) THEN
1791 23503123 : sg = zero
1792 23503123 : shs = zero
1793 70515302 : DO i = 1, n
1794 47012179 : sg = sg + step(i)*g(i)
1795 70515302 : shs = shs + step(i)*hs(i)
1796 : END DO
1797 23503123 : sgk = sg + shs
1798 23503123 : angtest = sgk/SQRT(gg*delsq)
1799 23503123 : 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 20520518 : iterc = iterc + 1
1805 20520518 : temp = SQRT(delsq*gg - sgk*sgk)
1806 20520518 : tempa = delsq/temp
1807 20520518 : tempb = sgk/temp
1808 61566977 : DO i = 1, n
1809 61566977 : d(i) = tempa*(g(i) + hs(i)) - tempb*step(i)
1810 : END DO
1811 20520518 : CALL updatehd
1812 20520518 : IF (iterc <= itersw) THEN
1813 : jump1 = .TRUE.
1814 : CYCLE mainloop
1815 : END IF
1816 : END IF
1817 20520518 : dg = zero
1818 20520518 : dhd = zero
1819 20520518 : dhs = zero
1820 61566977 : DO i = 1, n
1821 41046459 : dg = dg + d(i)*g(i)
1822 41046459 : dhd = dhd + hd(i)*d(i)
1823 61566977 : dhs = dhs + hd(i)*step(i)
1824 : END DO
1825 : !
1826 : ! Seek the value of the angle that minimizes Q.
1827 : !
1828 20520518 : cf = half*(shs - dhd)
1829 20520518 : qbeg = sg + cf
1830 20520518 : qsav = qbeg
1831 20520518 : qmin = qbeg
1832 20520518 : isave = 0
1833 20520518 : iu = 49
1834 20520518 : temp = twopi/REAL(iu + 1, dp)
1835 1026025900 : DO i = 1, iu
1836 1005505382 : angle = REAL(i, dp)*temp
1837 1005505382 : cth = COS(angle)
1838 1005505382 : sth = SIN(angle)
1839 1005505382 : qnew = (sg + cf*cth)*cth + (dg + dhs*cth)*sth
1840 1005505382 : IF (qnew < qmin) THEN
1841 : qmin = qnew
1842 : isave = i
1843 : tempa = qsav
1844 984145543 : ELSE IF (i == isave + 1) THEN
1845 25602995 : tempb = qnew
1846 : END IF
1847 1026025900 : qsav = qnew
1848 : END DO
1849 20520518 : IF (isave == zero) tempa = qnew
1850 8883354 : IF (isave == iu) tempb = qbeg
1851 20520518 : angle = zero
1852 20520518 : IF (tempa /= tempb) THEN
1853 20520518 : tempa = tempa - qmin
1854 20520518 : tempb = tempb - qmin
1855 20520518 : angle = half*(tempa - tempb)/(tempa + tempb)
1856 : END IF
1857 20520518 : angle = temp*(REAL(isave, DP) + angle)
1858 : !
1859 : ! Calculate the new STEP and HS. Then test for convergence.
1860 : !
1861 20520518 : cth = COS(angle)
1862 20520518 : sth = SIN(angle)
1863 20520518 : reduc = qbeg - (sg + cf*cth)*cth - (dg + dhs*cth)*sth
1864 20520518 : gg = zero
1865 61566977 : DO i = 1, n
1866 41046459 : step(i) = cth*step(i) + sth*d(i)
1867 41046459 : hs(i) = cth*hs(i) + sth*hd(i)
1868 61566977 : gg = gg + (g(i) + hs(i))**2
1869 : END DO
1870 20520518 : qred = qred + reduc
1871 20520518 : ratio = reduc/qred
1872 20520518 : IF (iterc < itermax .AND. ratio > 0.01_dp) THEN
1873 886 : jump2 = .TRUE.
1874 : ELSE
1875 : EXIT mainloop
1876 : END IF
1877 :
1878 41247415 : IF (gg <= 1.0e-4_dp*ggbeg) EXIT mainloop
1879 :
1880 : END DO mainloop
1881 :
1882 : !*******************************************************************************
1883 : CONTAINS
1884 : ! **************************************************************************************************
1885 : !> \brief ...
1886 : ! **************************************************************************************************
1887 131350015 : SUBROUTINE updatehd
1888 : INTEGER :: i, ih, j, k
1889 :
1890 394072837 : DO i = 1, n
1891 394072837 : hd(i) = zero
1892 : END DO
1893 788145674 : DO k = 1, npt
1894 656795659 : temp = zero
1895 1970654753 : DO j = 1, n
1896 1970654753 : temp = temp + xpt(k, j)*d(j)
1897 : END DO
1898 656795659 : temp = temp*pq(k)
1899 2102004768 : DO i = 1, n
1900 1970654753 : hd(i) = hd(i) + temp*xpt(k, i)
1901 : END DO
1902 : END DO
1903 131350015 : ih = 0
1904 394072837 : DO j = 1, n
1905 788218316 : DO i = 1, j
1906 394145479 : ih = ih + 1
1907 394145479 : IF (i < j) hd(j) = hd(j) + hq(ih)*d(i)
1908 656868301 : hd(i) = hd(i) + hq(ih)*d(j)
1909 : END DO
1910 : END DO
1911 131350015 : 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 47845697 : 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 47845697 : nptm = npt - n - 1
1954 : !
1955 : ! Apply the rotations that put zeros in the KNEW-th row of ZMAT.
1956 : !
1957 47845697 : jl = 1
1958 95697263 : DO j = 2, nptm
1959 95697263 : IF (j == idz) THEN
1960 : jl = idz
1961 47851566 : ELSE IF (zmat(knew, j) /= zero) THEN
1962 46553483 : temp = SQRT(zmat(knew, jl)**2 + zmat(knew, j)**2)
1963 46553483 : tempa = zmat(knew, jl)/temp
1964 46553483 : tempb = zmat(knew, j)/temp
1965 279368214 : DO I = 1, NPT
1966 232814731 : temp = tempa*zmat(i, jl) + tempb*zmat(i, j)
1967 232814731 : zmat(i, j) = tempa*zmat(i, j) - tempb*zmat(i, jl)
1968 279368214 : zmat(i, jl) = temp
1969 : END DO
1970 46553483 : 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 47845697 : tempa = zmat(knew, 1)
1978 47845697 : IF (idz >= 2) tempa = -tempa
1979 47845697 : IF (jl > 1) tempb = zmat(knew, jl)
1980 287085920 : DO i = 1, npt
1981 239240223 : w(i) = tempa*zmat(i, 1)
1982 287085920 : IF (jl > 1) w(i) = w(i) + tempb*zmat(i, jl)
1983 : END DO
1984 47845697 : alpha = w(knew)
1985 47845697 : tau = vlag(knew)
1986 47845697 : tausq = tau*tau
1987 47845697 : denom = alpha*beta + tausq
1988 47845697 : 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 47845697 : iflag = 0
1995 47845697 : IF (JL == 1) THEN
1996 47845697 : temp = SQRT(ABS(denom))
1997 47845697 : tempb = tempa/temp
1998 47845697 : tempa = tau/temp
1999 287085920 : DO i = 1, npt
2000 287085920 : zmat(i, 1) = tempa*zmat(i, 1) - tempb*vlag(i)
2001 : END DO
2002 47845697 : IF (idz == 1 .AND. temp < zero) idz = 2
2003 47845697 : 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 143542960 : DO j = 1, n
2042 95697263 : jp = npt + j
2043 95697263 : w(jp) = bmat(knew, j)
2044 95697263 : tempa = (alpha*vlag(jp) - tau*w(jp))/denom
2045 95697263 : tempb = (-beta*w(jp) - tau*vlag(jp))/denom
2046 765652542 : DO i = 1, jp
2047 622109582 : bmat(i, j) = bmat(i, j) + tempa*vlag(i) + tempb*w(i)
2048 717806845 : IF (i > npt) bmat(jp, i - npt) = bmat(i, j)
2049 : END DO
2050 : END DO
2051 :
2052 47845697 : END SUBROUTINE update
2053 :
2054 0 : END MODULE powell
2055 :
2056 : !******************************************************************************
|