35 use mpi_f08,
only: mpi_in_place
40 module subroutine mma_update_cpu(this, iter, x, df0dx, fval, dfdx)
48 class(mma_t),
intent(inout) :: this
49 integer,
intent(in) :: iter
50 real(kind=rp),
dimension(this%n),
intent(inout) :: x
51 type(vector_t) :: df0dx, fval
52 type(matrix_t) :: dfdx
54 if (.not. this%is_initialized)
then
55 write(stderr, *)
"The MMA object is not initialized."
60 call mma_gensub_cpu(this, iter, x, df0dx, fval, dfdx)
63 call mma_subsolve_dpip_cpu(this, x)
65 this%is_updated = .true.
66 end subroutine mma_update_cpu
69 module subroutine mma_kkt_cpu(this, x, df0dx, fval, dfdx)
89 class(mma_t),
intent(inout) :: this
90 real(kind=rp),
dimension(this%n),
intent(in) :: x
91 type(vector_t),
intent(in) :: df0dx, fval
92 type(matrix_t),
intent(in) :: dfdx
94 real(kind=rp) :: rez, rezeta
95 real(kind=rp),
dimension(this%m) :: rey, relambda, remu, res
96 real(kind=rp),
dimension(this%n) :: rex, rexsi, reeta
97 real(kind=rp),
dimension(3*this%n+4*this%m+2) :: residual
99 real(kind=rp),
dimension(4*this%m+2) :: residual_small
101 real(kind=rp) :: re_sq_norm
104 associate(fval => fval%x, dfdx => dfdx%x, df0dx => df0dx%x)
106 rex = df0dx + matmul(transpose(dfdx), this%lambda%x) &
107 - this%xsi%x + this%eta%x
108 rey = this%c%x + this%d%x*this%y%x - this%lambda%x - this%mu%x
109 rez = this%a0 - this%zeta - dot_product(this%lambda%x, this%a%x)
111 relambda = fval - this%a%x * this%z - this%y%x + this%s%x
112 rexsi = this%xsi%x * (x - this%xmin%x)
113 reeta = this%eta%x * (this%xmax%x - x)
114 remu = this%mu%x * this%y%x
115 rezeta = this%zeta * this%z
116 res = this%lambda%x * this%s%x
118 residual = [rex, rey, rez, relambda, rexsi, reeta, remu, rezeta, res]
119 residual_small = [rey, rez, relambda, remu, rezeta, res]
121 this%residumax = maxval(abs(residual))
122 re_sq_norm = norm2(rex)**2 + norm2(rexsi)**2 + norm2(reeta)**2
124 call mpi_allreduce(mpi_in_place, this%residumax, 1, &
125 mpi_real_precision, mpi_max, neko_comm, ierr)
127 call mpi_allreduce(mpi_in_place, re_sq_norm, 1, &
128 mpi_real_precision, mpi_sum, neko_comm, ierr)
130 this%residunorm = sqrt(norm2(residual_small)**2 + re_sq_norm)
132 end subroutine mma_kkt_cpu
138 subroutine mma_gensub_cpu(this, iter, xdesign, df0dx, fval, dfdx)
144 class(mma_t),
intent(inout) :: this
145 real(kind=rp),
dimension(this%n),
intent(in) :: xdesign
146 type(vector_t) :: df0dx, fval
147 type(matrix_t) :: dfdx
148 integer,
intent(in) :: iter
149 integer :: i, j, ierr
150 real(kind=rp),
dimension(this%n) :: x_diff
151 real(kind=rp) :: asy_factor
153 x_diff = this%xmax%x - this%xmin%x
157 associate(low => this%low%x, upp => this%upp%x, &
158 x_1 => this%xold1%x, x_2 => this%xold2%x, x => xdesign)
160 if (iter .lt. 3)
then
162 low = x - this%asyinit * x_diff
163 upp = x + this%asyinit * x_diff
166 if ((x(j) - x_1(j)) * (x_1(j) - x_2(j)) .lt. 0.0_rp)
then
167 asy_factor = this%asydecr
168 else if ((x(j) - x_1(j)) * (x_1(j) - x_2(j)) .gt. 0.0_rp)
then
169 asy_factor = this%asyincr
174 low(j) = x(j) - asy_factor * (x_1(j) - low(j))
175 upp(j) = x(j) + asy_factor * (upp(j) - x_1(j))
181 low = max(low, x - 10.0_rp * x_diff)
182 low = min(low, x - 0.01_rp * x_diff)
184 upp = min(upp, x + 10.0_rp * x_diff)
185 upp = max(upp, x + 0.01_rp * x_diff)
199 associate(alpha => this%alpha%x, beta => this%beta%x, &
200 xmin => this%xmin%x, xmax => this%xmax%x, &
201 low => this%low%x, upp => this%upp%x, x => xdesign)
203 alpha = max(xmin, low + 0.1_rp*(x - low), x - 0.5_rp*x_diff)
204 beta = min(xmax, upp - 0.1_rp*(upp - x), x + 0.5_rp*x_diff)
212 associate(p0j => this%p0j%x, q0j => this%q0j%x, &
213 pij => this%pij%x, qij => this%qij%x, &
214 low => this%low%x, upp => this%upp%x, x => xdesign, &
215 dfdx => dfdx%x, df0dx => df0dx%x)
218 1.001_rp * max(df0dx, 0.0_rp) &
219 + 0.001_rp * max(-df0dx, 0.0_rp) &
220 + 0.00001_rp / max(x_diff, 0.00001_rp) &
224 0.001_rp * max(df0dx, 0.0_rp) &
225 + 1.001_rp * max(-df0dx, 0.0_rp) &
226 + 0.00001_rp / max(x_diff, 0.00001_rp)&
232 1.001_rp * max(dfdx(i, j), 0.0_rp) &
233 + 0.001_rp * max(-dfdx(i, j), 0.0_rp) &
234 + 0.00001_rp / max(x_diff(j), 0.00001_rp) &
235 ) * (upp(j) - x(j))**2
238 0.001_rp * max(dfdx(i, j), 0.0_rp) &
239 + 1.001_rp * max(-dfdx(i, j), 0.0_rp) &
240 + 0.00001_rp / max(x_diff(j), 0.00001_rp) &
241 ) * (x(j) - low(j))**2
250 associate(bi => this%bi%x, &
251 pij => this%pij%x, qij => this%qij%x, &
252 low => this%low%x, upp => this%upp%x, x => xdesign)
258 + pij(i, j) / (upp(j) - x(j)) &
259 + qij(i, j) / (x(j) - low(j))
263 call mpi_allreduce(mpi_in_place, bi, this%m, &
264 mpi_real_precision, mpi_sum, neko_comm, ierr)
269 end subroutine mma_gensub_cpu
272 subroutine mma_subsolve_dpip_cpu(this, designx)
283 class(mma_t),
intent(inout) :: this
284 real(kind=rp),
dimension(this%n),
intent(inout) :: designx
287 integer :: i, j, k, iter, itto, ierr
288 real(kind=rp) :: epsi, residual_max, residual_norm, &
289 z, zeta, rez, rezeta, &
291 steg, zold, zetaold, new_residual
292 real(kind=rp),
dimension(this%m) :: y, lambda, s, mu, &
293 rey, relambda, remu, res, &
295 dy, dlambda, ds, dmu, &
296 yold, lambdaold, sold, muold
297 real(kind=rp),
dimension(this%n) :: x, xsi, eta, &
299 delx, diagx, dx, dxsi, deta, &
301 real(kind=rp),
dimension(4*this%m + 2) :: residual_small
302 real(kind=rp),
dimension(3*this%n + 4*this%m + 2) :: residual
303 real(kind=rp),
dimension(2*this%n + 4*this%m + 2) :: xx, dxx
305 real(kind=rp),
dimension(this%m, this%n) :: gg
306 real(kind=rp),
dimension(this%m+1) :: bb
307 real(kind=rp),
dimension(this%m+1, this%m+1) :: aa
312 integer,
dimension(this%m+1) :: ipiv
315 real(kind=rp) :: re_sq_norm
316 real(kind=rp) :: minimal_epsilon
325 x = 0.5_rp * (this%alpha%x + this%beta%x)
331 xsi = max(1.0_rp, 1.0_rp / (x - this%alpha%x))
332 eta = max(1.0_rp, 1.0_rp / (this%beta%x - x))
333 mu = max(1.0_rp, 0.5_rp * this%c%x)
335 call mpi_allreduce(this%n, nglobal, 1, &
336 mpi_integer, mpi_sum, neko_comm, ierr)
341 minimal_epsilon = max(0.9_rp * this%epsimin, 1.0e-12_rp)
342 call mpi_allreduce(mpi_in_place, minimal_epsilon, 1, &
343 mpi_real_precision, mpi_min, neko_comm, ierr)
348 do while (epsi .gt. minimal_epsilon)
355 associate(p0j => this%p0j%x, q0j => this%q0j%x, &
356 pij => this%pij%x, qij => this%qij%x, &
357 low => this%low%x, upp => this%upp%x, &
358 alpha => this%alpha%x, beta => this%beta%x, &
359 c => this%c%x, d => this%d%x, &
360 a0 => this%a0, a => this%a%x, &
363 rex = (p0j + matmul(transpose(pij), lambda)) / (upp - x)**2 &
364 - (q0j + matmul(transpose(qij), lambda)) / (x - low)**2 &
367 rey = c + d * y - lambda - mu
368 rez = a0 - zeta - dot_product(lambda, a)
374 relambda(i) = relambda(i) &
375 + pij(i, j) / (upp(j) - x(j)) &
376 + qij(i, j) / (x(j) - low(j))
386 call mpi_allreduce(mpi_in_place, relambda, this%m, &
387 mpi_real_precision, mpi_sum, neko_comm, ierr)
388 relambda = relambda - this%a%x*z - y + s - this%bi%x
390 rexsi = xsi * (x - this%alpha%x) - epsi
391 reeta = eta * (this%beta%x - x) - epsi
393 rezeta = zeta * z - epsi
394 res = lambda * s - epsi
397 residual = [rex, rey, rez, relambda, rexsi, reeta, remu, rezeta, res]
398 residual_small = [rey, rez, relambda, remu, rezeta, res]
400 residual_max = maxval(abs(residual))
401 re_sq_norm = norm2(rex)**2 + norm2(rexsi)**2 + norm2(reeta)**2
403 call mpi_allreduce(mpi_in_place, residual_max, 1, &
404 mpi_real_precision, mpi_max, neko_comm, ierr)
406 call mpi_allreduce(mpi_in_place, re_sq_norm, &
407 1, mpi_real_precision, mpi_sum, neko_comm, ierr)
409 residual_norm = sqrt(norm2(residual_small)**2 + re_sq_norm)
414 do iter = 1, this%max_iter
417 if (residual_max .lt. epsi)
exit
423 + this%pij%x(i,j) * lambda(i) / (this%upp%x(j) - x(j))**2 &
424 - this%qij%x(i,j) * lambda(i) / (x(j) - this%low%x(j))**2
429 + this%p0j%x / (this%upp%x - x)**2 &
430 - this%q0j%x / (x - this%low%x)**2 &
431 - epsi / (x - this%alpha%x) &
432 + epsi / (this%beta%x - x)
434 dely = this%c%x + this%d%x * y - lambda - epsi / y
435 delz = this%a0 - dot_product(lambda, this%a%x) - epsi / z
441 dellambda(i) = dellambda(i) &
442 + this%pij%x(i, j) / (this%upp%x(j) - x(j)) &
443 + this%qij%x(i, j) / (x(j) - this%low%x(j))
447 call mpi_allreduce(mpi_in_place, dellambda, this%m, &
448 mpi_real_precision, mpi_sum, neko_comm, ierr)
450 dellambda = dellambda - this%a%x*z - y - this%bi%x + epsi / lambda
453 gg(i,:) = this%pij%x(i,:) / (this%upp%x - x)**2 &
454 - this%qij%x(i,:) / (x - this%low%x)**2
458 (this%p0j%x + matmul(transpose(this%pij%x), lambda)) &
459 / (this%upp%x - x)**3 &
460 + (this%q0j%x + matmul(transpose(this%qij%x), lambda)) &
461 / (x - this%low%x)**3
463 diagx = 2.0_rp * diagx &
464 + xsi / (x - this%alpha%x) &
465 + eta / (this%beta%x - x)
479 bb(i) = bb(i) + gg(i, j) * (delx(j) / diagx(j))
483 call mpi_allreduce(mpi_in_place, bb(1:this%m), this%m, &
484 mpi_real_precision, mpi_sum, neko_comm, ierr)
486 bb(1:this%m) = dellambda + dely / (this%d%x + mu / y) - bb(1:this%m)
487 bb(this%m + 1) = delz
504 aa(i, j) = aa(i, j) &
505 + gg(i, k) * (1.0_rp / diagx(k)) * gg(j, k)
510 call mpi_allreduce(mpi_in_place, aa(1:this%m, 1:this%m), &
511 this%m*this%m, mpi_real_precision, mpi_sum, neko_comm, ierr)
515 aa(i, i) = aa(i, i) &
517 + 1.0_rp / (this%d%x(i) + mu(i) / y(i))
520 aa(1:this%m, this%m+1) = this%a%x
521 aa(this%m+1, 1:this%m) = this%a%x
522 aa(this%m+1, this%m+1) = - zeta/z
524 call dgesv(this%m + 1, 1, aa, this%m + 1, ipiv, bb, this%m + 1, info)
526 if (info .ne. 0)
then
527 write(stderr, *)
"DGESV failed to solve the linear system in MMA."
528 write(stderr, *)
"Please check mma_subsolve_dpip in mma.f90"
532 dlambda = bb(1:this%m)
536 dx = - delx / diagx - matmul(transpose(gg), dlambda) / diagx
537 dy = (-dely + dlambda) / (this%d%x + mu / y)
539 dxsi = -xsi + (epsi - dx * xsi) / (x - this%alpha%x)
540 deta = -eta + (epsi + dx * eta) / (this%beta%x - x)
541 dmu = -mu + (epsi - mu * dy) / y
542 dzeta = -zeta + (epsi - zeta * dz) / z
543 ds = -s + (epsi - dlambda * s) / lambda
545 dxx = [dy, dz, dlambda, dxsi, deta, dmu, dzeta, ds]
546 xx = [y, z, lambda, xsi, eta, mu, zeta, s]
548 steg = 1.0_rp / maxval([ &
550 -1.01_rp * dxx / xx, &
551 -1.01_rp * dx / (x - this%alpha%x), &
552 1.01_rp * dx / (this%beta%x - x) &
568 new_residual = 2.0_rp * residual_norm
571 call mpi_allreduce(mpi_in_place, steg, 1, &
572 mpi_real_precision, mpi_min, neko_comm, ierr)
573 call mpi_allreduce(mpi_in_place, new_residual, 1, &
574 mpi_real_precision, mpi_min, neko_comm, ierr)
577 do while ((new_residual .gt. residual_norm) .and. (itto .lt. 50))
584 lambda = lambdaold + steg*dlambda
585 xsi = xsiold + steg*dxsi
586 eta = etaold + steg*deta
587 mu = muold + steg*dmu
588 zeta = zetaold + steg*dzeta
593 rex = (this%p0j%x + matmul(transpose(this%pij%x), lambda)) &
594 / (this%upp%x - x)**2 &
595 - (this%q0j%x + matmul(transpose(this%qij%x), lambda)) &
596 / (x - this%low%x)**2 &
599 rey = this%c%x + this%d%x*y - lambda - mu
600 rez = this%a0 - zeta - dot_product(lambda, this%a%x)
606 relambda(i) = relambda(i) &
607 + this%pij%x(i, j) / (this%upp%x(j) - x(j)) &
608 + this%qij%x(i, j) / (x(j) - this%low%x(j))
612 call mpi_allreduce(mpi_in_place, relambda, this%m, &
613 mpi_real_precision, mpi_sum, neko_comm, ierr)
615 relambda = relambda - this%a%x*z - y + s - this%bi%x
617 rexsi = xsi * (x - this%alpha%x) - epsi
618 reeta = eta * (this%beta%x - x) - epsi
620 rezeta = zeta * z - epsi
621 res = lambda * s - epsi
623 residual_small = [rey, rez, relambda, remu, rezeta, res]
625 re_sq_norm = norm2(rex)**2 + norm2(rexsi)**2 + norm2(reeta)**2
626 call mpi_allreduce(mpi_in_place, re_sq_norm, &
627 1, mpi_real_precision, mpi_sum, neko_comm, ierr)
629 new_residual = sqrt(norm2(residual_small)**2 + re_sq_norm)
635 residual = [rex, rey, rez, relambda, rexsi, reeta, remu, rezeta, res]
638 residual_norm = new_residual
639 residual_max = maxval(abs(residual))
640 call mpi_allreduce(mpi_in_place, residual_max, 1, &
641 mpi_real_precision, mpi_max, neko_comm, ierr)
648 this%xold2%x = this%xold1%x
649 this%xold1%x = designx
655 this%lambda%x = lambda
662 end subroutine mma_subsolve_dpip_cpu