35 use lapack_interfaces,
only:
dgesv
36 use mpi_f08,
only: mpi_in_place, mpi_max, mpi_min
37 use comm,
only: neko_comm, pe_rank, mpi_real_precision
38 use math,
only: neko_eps
39 use profiler,
only: profiler_start_region, profiler_end_region
40 use,
intrinsic :: ieee_arithmetic, only: ieee_is_nan
46 module subroutine mma_update_cpu(this, iter, x, df0dx, fval, dfdx)
54 class(mma_t),
intent(inout) :: this
55 integer,
intent(in) :: iter
56 real(kind=rp),
dimension(this%n),
intent(inout) :: x
57 real(kind=rp),
dimension(this%n),
intent(in) :: df0dx
58 real(kind=rp),
dimension(this%m),
intent(in) :: fval
59 real(kind=rp),
dimension(this%m, this%n),
intent(in) :: dfdx
61 if (.not. this%is_initialized)
then
62 call neko_error(
"The MMA object is not initialized.")
65 call profiler_start_region(
"MMA update")
68 call profiler_start_region(
"MMA gensub")
69 call mma_gensub_cpu(this, iter, x, df0dx, fval, dfdx)
70 call profiler_end_region(
"MMA gensub")
73 call profiler_start_region(
"MMA subsolve")
74 if (this%subsolver .eq.
"dip")
then
75 call mma_subsolve_dip_cpu(this, x)
76 else if (this%subsolver .eq.
"pdip")
then
77 call mma_subsolve_pdip_cpu(this, x)
79 call neko_error(
"Unrecognized subsolver for MMA in mma_cpu.")
81 call profiler_end_region(
"MMA subsolve")
83 call profiler_end_region(
"MMA update")
85 this%is_updated = .true.
86 end subroutine mma_update_cpu
89 module subroutine mma_kkt_cpu(this, x, df0dx, fval, dfdx)
109 class(mma_t),
intent(inout) :: this
110 real(kind=rp),
dimension(this%n),
intent(in) :: x
111 real(kind=rp),
dimension(this%n),
intent(in) :: df0dx
112 real(kind=rp),
dimension(this%m),
intent(in) :: fval
113 real(kind=rp),
dimension(this%m, this%n),
intent(in) :: dfdx
115 call profiler_start_region(
"MMA KKT computation")
117 if (this%subsolver .eq.
"dip")
then
118 call mma_dip_kkt_cpu(this, x, df0dx, fval, dfdx)
119 else if (this%subsolver .eq.
"pdip")
then
120 call mma_pdip_kkt_cpu(this, x, df0dx, fval, dfdx)
122 call neko_error(
"Unrecognized subsolver for MMA in mma_cpu.")
125 call profiler_end_region(
"MMA KKT computation")
126 end subroutine mma_kkt_cpu
130 module subroutine mma_pdip_kkt_cpu(this, x, df0dx, fval, dfdx)
150 class(mma_t),
intent(inout) :: this
151 real(kind=rp),
dimension(this%n),
intent(in) :: x
152 real(kind=rp),
dimension(this%n),
intent(in) :: df0dx
153 real(kind=rp),
dimension(this%m),
intent(in) :: fval
154 real(kind=rp),
dimension(this%m, this%n),
intent(in) :: dfdx
156 real(kind=rp) :: rez, rezeta
157 real(kind=rp),
dimension(this%m) :: rey, relambda, remu, res
158 real(kind=rp),
dimension(this%n) :: rex, rexsi, reeta
159 real(kind=rp),
dimension(3*this%n+4*this%m+2) :: residual
161 real(kind=rp),
dimension(4*this%m+2) :: residual_small
163 real(kind=rp) :: re_sq_norm
165 rex = df0dx + matmul(transpose(dfdx), this%lambda%x) &
166 - this%xsi%x + this%eta%x
167 rey = this%c%x + this%d%x*this%y%x - this%lambda%x - this%mu%x
168 rez = this%a0 - this%zeta - dot_product(this%lambda%x, this%a%x)
170 relambda = fval - this%a%x * this%z - this%y%x + this%s%x
171 rexsi = this%xsi%x * (x - this%xmin%x)
172 reeta = this%eta%x * (this%xmax%x - x)
173 remu = this%mu%x * this%y%x
174 rezeta = this%zeta * this%z
175 res = this%lambda%x * this%s%x
177 residual = [rex, rey, rez, relambda, rexsi, reeta, remu, rezeta, res]
178 residual_small = [rey, rez, relambda, remu, rezeta, res]
180 this%residumax = maxval(abs(residual))
181 re_sq_norm = norm2(rex)**2 + norm2(rexsi)**2 + norm2(reeta)**2
183 call mpi_allreduce(mpi_in_place, this%residumax, 1, &
184 mpi_real_precision, mpi_max, neko_comm, ierr)
186 call mpi_allreduce(mpi_in_place, re_sq_norm, 1, &
187 mpi_real_precision, mpi_sum, neko_comm, ierr)
189 this%residunorm = sqrt(norm2(residual_small)**2 + re_sq_norm)
194 if (ieee_is_nan(this%residunorm)) this%residumax = this%residunorm
195 end subroutine mma_pdip_kkt_cpu
199 module subroutine mma_dip_kkt_cpu(this, x, df0dx, fval, dfdx)
224 class(mma_t),
intent(inout) :: this
225 real(kind=rp),
dimension(this%n),
intent(in) :: x
226 real(kind=rp),
dimension(this%n),
intent(in) :: df0dx
227 real(kind=rp),
dimension(this%m),
intent(in) :: fval
228 real(kind=rp),
dimension(this%m, this%n),
intent(in) :: dfdx
230 real(kind=rp) :: rex, resi, xsi, eta, relambda
231 real(kind=rp) :: residual_max, residual_sq_norm
232 integer :: i, j, ierr
234 residual_max = 0.0_rp
235 residual_sq_norm = 0.0_rp
237 associate(xmin => this%xmin%x, xmax => this%xmax%x, &
238 lambda => this%lambda%x)
244 rex = rex + lambda(i) * dfdx(i, j)
249 if (x(j) .lt. xmin(j) + 1.0e-5_rp .and. rex .gt. 0.0_rp) xsi = rex
251 if (x(j) .gt. xmax(j) - 1.0e-5_rp .and. rex .lt. 0.0_rp) eta = -rex
252 rex = rex + (-xsi + eta)
254 residual_sq_norm = residual_sq_norm + rex**2
255 residual_max = max(abs(rex), residual_max)
256 resi = xsi * (x(j) - xmin(j))
257 residual_sq_norm = residual_sq_norm + resi**2
258 residual_max = max(abs(resi), residual_max)
259 resi = eta * (xmax(j) - x(j))
260 residual_sq_norm = residual_sq_norm + resi**2
261 residual_max = max(abs(resi), residual_max)
266 call mpi_allreduce(mpi_in_place, residual_sq_norm, 1, &
267 mpi_real_precision, mpi_sum, neko_comm, ierr)
268 call mpi_allreduce(mpi_in_place, residual_max, 1, &
269 mpi_real_precision, mpi_max, neko_comm, ierr)
274 relambda = relambda + this%lambda%x(i) * &
275 (this%a%x(i) * this%z + this%y%x(i) - fval(i))
278 this%residumax = max(abs(relambda), residual_max)
279 this%residunorm = sqrt(residual_sq_norm + relambda**2)
284 if (ieee_is_nan(this%residunorm)) this%residumax = this%residunorm
286 end subroutine mma_dip_kkt_cpu
292 subroutine mma_gensub_cpu(this, iter, x, df0dx, fval, dfdx)
298 class(mma_t),
intent(inout) :: this
299 real(kind=rp),
dimension(this%n),
intent(in) :: x
300 real(kind=rp),
dimension(this%n),
intent(in) :: df0dx
301 real(kind=rp),
dimension(this%m),
intent(in) :: fval
302 real(kind=rp),
dimension(this%m, this%n),
intent(in) :: dfdx
303 integer,
intent(in) :: iter
304 integer :: i, j, ierr
305 real(kind=rp),
dimension(this%n) :: xmin_eff, xmax_eff
306 real(kind=rp),
dimension(this%n) :: x_diff
307 real(kind=rp) :: asy_factor
309 xmin_eff = this%xmin%x
310 xmax_eff = this%xmax%x
311 if (this%move_limit .gt. 0.0_rp)
then
312 xmin_eff = max(xmin_eff, x - this%move_limit)
313 xmax_eff = min(xmax_eff, x + this%move_limit)
316 x_diff = max(xmax_eff - xmin_eff, 1.0e-5_rp)
320 associate(low => this%low%x, upp => this%upp%x, &
321 x_1 => this%xold1%x, x_2 => this%xold2%x)
323 if (iter .lt. 3)
then
325 low = x - this%asyinit * x_diff
326 upp = x + this%asyinit * x_diff
329 if ((x(j) - x_1(j)) * (x_1(j) - x_2(j)) .lt. 0.0_rp)
then
330 asy_factor = this%asydecr
331 else if ((x(j) - x_1(j)) * (x_1(j) - x_2(j)) .gt. 0.0_rp)
then
332 asy_factor = this%asyincr
337 low(j) = x(j) - asy_factor * (x_1(j) - low(j))
338 upp(j) = x(j) + asy_factor * (upp(j) - x_1(j))
344 low = max(low, x - 10.0_rp * x_diff)
345 low = min(low, x - 0.01_rp * x_diff)
347 upp = min(upp, x + 10.0_rp * x_diff)
348 upp = max(upp, x + 0.01_rp * x_diff)
362 associate(alpha => this%alpha%x, beta => this%beta%x, &
363 xmin => xmin_eff, xmax => xmax_eff, &
364 low => this%low%x, upp => this%upp%x, x => x)
366 alpha = max(xmin, low + 0.1_rp*(x - low))
367 beta = min(xmax, upp - 0.1_rp*(upp - x))
374 associate(p0j => this%p0j%x, q0j => this%q0j%x, &
375 pij => this%pij%x, qij => this%qij%x, &
376 low => this%low%x, upp => this%upp%x)
378 if (this%subsolver .eq.
"dip")
then
382 p0j = (upp - x)**2 * (max(df0dx, 0.0_rp) + 0.001_rp*abs(df0dx) &
383 + 0.5_rp*1.0e-6_rp/(upp - low))
384 q0j = (x - low)**2 * (max(-df0dx, 0.0_rp) + 0.001_rp*abs(df0dx) &
385 + 0.5_rp*1.0e-6_rp/(upp - low))
388 pij(i, j) = (upp(j) - x(j))**2 * max(dfdx(i, j), 0.0_rp)
389 qij(i, j) = (x(j) - low(j))**2 * max(-dfdx(i, j), 0.0_rp)
396 1.001_rp * max(df0dx, 0.0_rp) &
397 + 0.001_rp * max(-df0dx, 0.0_rp) &
398 + 0.00001_rp / max(x_diff, 0.00001_rp) &
402 0.001_rp * max(df0dx, 0.0_rp) &
403 + 1.001_rp * max(-df0dx, 0.0_rp) &
404 + 0.00001_rp / max(x_diff, 0.00001_rp)&
410 1.001_rp * max(dfdx(i, j), 0.0_rp) &
411 + 0.001_rp * max(-dfdx(i, j), 0.0_rp) &
412 + 0.00001_rp / max(x_diff(j), 0.00001_rp) &
413 ) * (upp(j) - x(j))**2
416 0.001_rp * max(dfdx(i, j), 0.0_rp) &
417 + 1.001_rp * max(-dfdx(i, j), 0.0_rp) &
418 + 0.00001_rp / max(x_diff(j), 0.00001_rp) &
419 ) * (x(j) - low(j))**2
429 associate(bi => this%bi%x, &
430 pij => this%pij%x, qij => this%qij%x, &
431 low => this%low%x, upp => this%upp%x)
437 + pij(i, j) / (upp(j) - x(j)) &
438 + qij(i, j) / (x(j) - low(j))
442 call mpi_allreduce(mpi_in_place, bi, this%m, &
443 mpi_real_precision, mpi_sum, neko_comm, ierr)
447 end subroutine mma_gensub_cpu
451 subroutine mma_subsolve_pdip_cpu(this, designx)
462 class(mma_t),
intent(inout) :: this
463 real(kind=rp),
dimension(this%n),
intent(inout) :: designx
466 integer :: i, j, k, iter, itto, ierr
467 real(kind=rp) :: epsi, residual_max, residual_norm, &
468 z, zeta, rez, rezeta, &
470 steg, zold, zetaold, new_residual
471 real(kind=rp),
dimension(this%m) :: y, lambda, s, mu, &
472 rey, relambda, remu, res, &
474 dy, dlambda, ds, dmu, &
475 yold, lambdaold, sold, muold
476 real(kind=rp),
dimension(this%n) :: x, xsi, eta, &
478 delx, diagx, dx, dxsi, deta, &
480 real(kind=rp),
dimension(4*this%m + 2) :: residual_small
481 real(kind=rp),
dimension(3*this%n + 4*this%m + 2) :: residual
482 real(kind=rp),
dimension(2*this%n + 4*this%m + 2) :: xx, dxx
484 real(kind=rp),
dimension(this%m, this%n) :: gg
485 real(kind=rp),
dimension(this%m+1) :: bb
486 real(kind=rp),
dimension(this%m+1, this%m+1) :: aa
487 real(kind=rp),
dimension(this%m * this%m) :: aa_buffer
492 integer,
dimension(this%m+1) :: ipiv
495 real(kind=rp) :: re_sq_norm
496 real(kind=rp) :: minimal_epsilon
503 x = 0.5_rp * (this%alpha%x + this%beta%x)
509 xsi = max(1.0_rp, 1.0_rp / (x - this%alpha%x))
510 eta = max(1.0_rp, 1.0_rp / (this%beta%x - x))
511 mu = max(1.0_rp, 0.5_rp * this%c%x)
516 minimal_epsilon = max(0.9_rp * this%epsimin, 1.0e-12_rp)
517 call mpi_allreduce(mpi_in_place, minimal_epsilon, 1, &
518 mpi_real_precision, mpi_min, neko_comm, ierr)
523 do while (epsi .gt. minimal_epsilon)
530 associate(p0j => this%p0j%x, q0j => this%q0j%x, &
531 pij => this%pij%x, qij => this%qij%x, &
532 low => this%low%x, upp => this%upp%x, &
533 alpha => this%alpha%x, beta => this%beta%x, &
534 c => this%c%x, d => this%d%x, &
535 a0 => this%a0, a => this%a%x)
537 rex = (p0j + matmul(transpose(pij), lambda)) / (upp - x)**2 &
538 - (q0j + matmul(transpose(qij), lambda)) / (x - low)**2 &
541 rey = c + d * y - lambda - mu
542 rez = a0 - zeta - dot_product(lambda, a)
548 relambda(i) = relambda(i) &
549 + pij(i, j) / (upp(j) - x(j)) &
550 + qij(i, j) / (x(j) - low(j))
560 call mpi_allreduce(mpi_in_place, relambda, this%m, &
561 mpi_real_precision, mpi_sum, neko_comm, ierr)
562 relambda = relambda - this%a%x*z - y + s - this%bi%x
564 rexsi = xsi * (x - this%alpha%x) - epsi
565 reeta = eta * (this%beta%x - x) - epsi
567 rezeta = zeta * z - epsi
568 res = lambda * s - epsi
571 residual = [rex, rey, rez, relambda, rexsi, reeta, remu, rezeta, res]
572 residual_small = [rey, rez, relambda, remu, rezeta, res]
574 residual_max = maxval(abs(residual))
575 re_sq_norm = norm2(rex)**2 + norm2(rexsi)**2 + norm2(reeta)**2
577 call mpi_allreduce(mpi_in_place, residual_max, 1, &
578 mpi_real_precision, mpi_max, neko_comm, ierr)
580 call mpi_allreduce(mpi_in_place, re_sq_norm, &
581 1, mpi_real_precision, mpi_sum, neko_comm, ierr)
583 residual_norm = sqrt(norm2(residual_small)**2 + re_sq_norm)
588 do iter = 1, this%max_iter
591 if (residual_max .lt. epsi)
exit
597 + this%pij%x(i,j) * lambda(i) / (this%upp%x(j) - x(j))**2 &
598 - this%qij%x(i,j) * lambda(i) / (x(j) - this%low%x(j))**2
603 + this%p0j%x / (this%upp%x - x)**2 &
604 - this%q0j%x / (x - this%low%x)**2 &
605 - epsi / (x - this%alpha%x) &
606 + epsi / (this%beta%x - x)
608 dely = this%c%x + this%d%x * y - lambda - epsi / y
609 delz = this%a0 - dot_product(lambda, this%a%x) - epsi / z
615 dellambda(i) = dellambda(i) &
616 + this%pij%x(i, j) / (this%upp%x(j) - x(j)) &
617 + this%qij%x(i, j) / (x(j) - this%low%x(j))
621 call mpi_allreduce(mpi_in_place, dellambda, this%m, &
622 mpi_real_precision, mpi_sum, neko_comm, ierr)
624 dellambda = dellambda - this%a%x*z - y - this%bi%x + epsi / lambda
627 gg(i,:) = this%pij%x(i,:) / (this%upp%x - x)**2 &
628 - this%qij%x(i,:) / (x - this%low%x)**2
632 (this%p0j%x + matmul(transpose(this%pij%x), lambda)) &
633 / (this%upp%x - x)**3 &
634 + (this%q0j%x + matmul(transpose(this%qij%x), lambda)) &
635 / (x - this%low%x)**3
637 diagx = 2.0_rp * diagx &
638 + xsi / (x - this%alpha%x) &
639 + eta / (this%beta%x - x)
653 bb(i) = bb(i) + gg(i, j) * (delx(j) / diagx(j))
657 call mpi_allreduce(mpi_in_place, bb, this%m, &
658 mpi_real_precision, mpi_sum, neko_comm, ierr)
660 bb(1:this%m) = dellambda + dely / (this%d%x + mu / y) - bb(1:this%m)
661 bb(this%m + 1) = delz
678 aa(i, j) = aa(i, j) &
679 + gg(i, k) * (1.0_rp / diagx(k)) * gg(j, k)
684 aa_buffer = reshape(aa(1:this%m, 1:this%m), [this%m * this%m])
686 call mpi_allreduce(mpi_in_place, aa_buffer, &
687 this%m*this%m, mpi_real_precision, mpi_sum, neko_comm, ierr)
689 aa(1:this%m, 1:this%m) = reshape(aa_buffer, [this%m, this%m])
693 aa(i, i) = aa(i, i) &
695 + 1.0_rp / (this%d%x(i) + mu(i) / y(i))
698 aa(1:this%m, this%m+1) = this%a%x
699 aa(this%m+1, 1:this%m) = this%a%x
700 aa(this%m+1, this%m+1) = - zeta/z
702 call dgesv(this%m + 1, 1, aa, this%m + 1, ipiv, bb, this%m + 1, info)
704 if (info .ne. 0)
then
705 call neko_error(
"DGESV failed to solve the linear system in " // &
706 "mma_subsolve_pdip.")
710 dlambda = bb(1:this%m)
714 dx = - delx / diagx - matmul(transpose(gg), dlambda) / diagx
715 dy = (-dely + dlambda) / (this%d%x + mu / y)
717 dxsi = -xsi + (epsi - dx * xsi) / (x - this%alpha%x)
718 deta = -eta + (epsi + dx * eta) / (this%beta%x - x)
719 dmu = -mu + (epsi - mu * dy) / y
720 dzeta = -zeta + (epsi - zeta * dz) / z
721 ds = -s + (epsi - dlambda * s) / lambda
723 dxx = [dy, dz, dlambda, dxsi, deta, dmu, dzeta, ds]
724 xx = [y, z, lambda, xsi, eta, mu, zeta, s]
726 steg = 1.0_rp / maxval([ &
728 -1.01_rp * dxx / xx, &
729 -1.01_rp * dx / (x - this%alpha%x), &
730 1.01_rp * dx / (this%beta%x - x) &
744 new_residual = 2.0_rp * residual_norm
747 call mpi_allreduce(mpi_in_place, steg, 1, &
748 mpi_real_precision, mpi_min, neko_comm, ierr)
749 call mpi_allreduce(mpi_in_place, new_residual, 1, &
750 mpi_real_precision, mpi_min, neko_comm, ierr)
755 do while ((new_residual .gt. residual_norm) .and. (itto .lt. 50))
763 lambda = lambdaold + steg*dlambda
764 xsi = xsiold + steg*dxsi
765 eta = etaold + steg*deta
766 mu = muold + steg*dmu
767 zeta = zetaold + steg*dzeta
772 rex = (this%p0j%x + matmul(transpose(this%pij%x), lambda)) &
773 / (this%upp%x - x)**2 &
774 - (this%q0j%x + matmul(transpose(this%qij%x), lambda)) &
775 / (x - this%low%x)**2 &
778 rey = this%c%x + this%d%x*y - lambda - mu
779 rez = this%a0 - zeta - dot_product(lambda, this%a%x)
785 relambda(i) = relambda(i) &
786 + this%pij%x(i, j) / (this%upp%x(j) - x(j)) &
787 + this%qij%x(i, j) / (x(j) - this%low%x(j))
791 call mpi_allreduce(mpi_in_place, relambda, this%m, &
792 mpi_real_precision, mpi_sum, neko_comm, ierr)
794 relambda = relambda - this%a%x*z - y + s - this%bi%x
796 rexsi = xsi * (x - this%alpha%x) - epsi
797 reeta = eta * (this%beta%x - x) - epsi
799 rezeta = zeta * z - epsi
800 res = lambda * s - epsi
803 re_sq_norm = norm2(rex)**2 + norm2(rexsi)**2 + norm2(reeta)**2
804 call mpi_allreduce(mpi_in_place, re_sq_norm, &
805 1, mpi_real_precision, mpi_sum, neko_comm, ierr)
807 residual_small = [rey, rez, relambda, remu, rezeta, res]
808 new_residual = sqrt(norm2(residual_small)**2 + re_sq_norm)
809 call mpi_allreduce(mpi_in_place, new_residual, 1, &
810 mpi_real_precision, mpi_min, neko_comm, ierr)
816 residual = [rex, rey, rez, relambda, rexsi, reeta, remu, rezeta, res]
819 residual_norm = new_residual
820 residual_max = maxval(abs(residual))
821 call mpi_allreduce(mpi_in_place, residual_max, 1, &
822 mpi_real_precision, mpi_max, neko_comm, ierr)
829 this%xold2%x = this%xold1%x
830 this%xold1%x = designx
836 this%lambda%x = lambda
843 end subroutine mma_subsolve_pdip_cpu
847 subroutine mma_subsolve_dip_cpu(this, designx)
885 class(mma_t),
intent(inout) :: this
886 real(kind=rp),
dimension(this%n),
intent(inout) :: designx
889 integer :: i, j, k, iter, ierr
890 real(kind=rp) :: epsi, residual_max, z, steg
891 real(kind=rp),
dimension(this%m) :: y, lambda, mu, &
892 relambda, remu, dlambda, dmu, gradlambda
893 real(kind=rp),
dimension(this%n) :: x, pjlambda, qjlambda
899 real(kind=rp),
dimension(this%n) :: ljjxinv
900 real(kind=rp),
dimension(this%m,this%n) :: hijx
901 real(kind=rp),
dimension(this%m,this%m) :: hess
902 real(kind=rp) :: hesstrace
908 integer,
dimension(this%m+1) :: ipiv
911 real(kind=rp) :: minimal_epsilon
922 lambda = max(1.0_rp, 0.5_rp * this%c%x)
930 minimal_epsilon = this%epsimin
931 call mpi_allreduce(mpi_in_place, minimal_epsilon, 1, &
932 mpi_real_precision, mpi_min, neko_comm, ierr)
936 residual_max = 1.0_rp
941 do while (epsi .gt. minimal_epsilon)
948 associate(p0j => this%p0j%x, q0j => this%q0j%x, &
949 pij => this%pij%x, qij => this%qij%x, &
950 low => this%low%x, upp => this%upp%x, &
951 alpha => this%alpha%x, beta => this%beta%x, &
952 c => this%c%x, d => this%d%x, &
953 a0 => this%a0, a => this%a%x, &
961 y = max(0.0_rp, lambda - c)
966 z = max(0.0_rp, 10.0_rp * (dot_product(lambda, a) - a0))
972 pjlambda = (p0j + matmul(transpose(pij), lambda))
973 qjlambda = (q0j + matmul(transpose(qij), lambda))
974 x = (sqrt(pjlambda) * low + sqrt(qjlambda) * upp) / &
975 (sqrt(pjlambda) + sqrt(qjlambda))
978 x = merge(alpha, x, x .lt. alpha)
979 x = merge(beta, x, x .gt. beta)
984 do iter = 1, this%max_iter
987 if (.not. (residual_max .gt. 0.9_rp * epsi))
exit
991 gradlambda = matmul(pij, 1.0_rp / (upp - x)) + &
992 matmul(qij, 1.0_rp/(x - low))
995 call mpi_allreduce(mpi_in_place, gradlambda, this%m, &
996 mpi_real_precision, mpi_sum, neko_comm, ierr)
997 gradlambda = gradlambda - bi - y - a * z
1000 gradlambda = - gradlambda - epsi / lambda
1006 ljjxinv= - 1.0_rp / ( (2.0_rp * pjlambda/(upp - x)**3) + &
1007 (2.0_rp * qjlambda/(x - low)**3))
1011 ljjxinv = merge(0.0_rp, ljjxinv, x - alpha < neko_eps)
1012 ljjxinv = merge(0.0_rp, ljjxinv, beta - x < neko_eps)
1015 hijx(i,:) = pij(i,:) / (upp - x)**2 &
1016 - qij(i,:) / (x - low)**2
1027 hess(i, j) = hess(i, j) &
1028 + hijx(i, k) * (ljjxinv(k)) * hijx(j, k)
1033 call mpi_allreduce(mpi_in_place, hess, &
1034 this%m * this%m, mpi_real_precision, mpi_sum, neko_comm, ierr)
1040 if (dot_product(lambda, a) .gt. 0.0_rp)
then
1043 hess(i, j) = hess(i, j) - 10.0_rp * a(i) * a(j)
1051 if (y(i) .gt. 0.0_rp)
then
1052 hess(i, i) = hess(i, i) - 1.0_rp
1055 hess(i, i) = hess(i, i) - mu(i) / lambda(i)
1062 hesstrace = hesstrace + hess(i, i)
1065 hess(i,i) = hess(i, i) - &
1066 max(-1.0e-4_rp*hesstrace/this%m, 1.0e-7_rp)
1069 call dgesv(this%m , 1, hess, this%m , ipiv, &
1070 gradlambda, this%m, info)
1072 if (info .ne. 0)
then
1073 call neko_error(
"DGESV failed to solve the linear system in " // &
1074 "mma_subsolve_dip.")
1076 dlambda = gradlambda
1079 dmu = -mu + epsi / lambda - dlambda * mu / lambda
1085 steg = merge(-1.01_rp * dlambda(i) / lambda(i), steg, &
1086 steg < -1.01_rp * dlambda(i) / lambda(i))
1087 steg = merge(-1.01_rp * dmu(i) / mu(i), &
1088 steg, steg < -1.01_rp * dmu(i) / mu(i))
1091 steg = 1.0_rp / steg
1093 lambda = lambda + steg*dlambda
1102 y = max(0.0_rp, lambda - c)
1108 z = max(0.0_rp, 10.0_rp * (dot_product(lambda, a) - a0))
1114 pjlambda = (p0j + matmul(transpose(pij), lambda))
1115 qjlambda = (q0j + matmul(transpose(qij), lambda))
1116 x = (sqrt(pjlambda) * low + sqrt(qjlambda) * upp) / &
1117 (sqrt(pjlambda) + sqrt(qjlambda))
1120 x = merge(alpha, x, x .lt. alpha)
1121 x = merge(beta, x, x .gt. beta)
1124 relambda = matmul(pij, 1.0_rp / (upp - x)) + &
1125 matmul(qij, 1.0_rp / (x - low))
1127 call mpi_allreduce(mpi_in_place, relambda, this%m, &
1128 mpi_real_precision, mpi_sum, neko_comm, ierr)
1129 relambda = relambda - bi - y - a * z + mu
1132 remu = mu * lambda - epsi
1134 residual_max = maxval(abs([relambda, remu]))
1135 call mpi_allreduce(mpi_in_place, residual_max, 1, &
1136 mpi_real_precision, mpi_max, neko_comm, ierr)
1140 epsi = 0.1_rp * epsi
1144 this%xold2%x = this%xold1%x
1145 this%xold1%x = designx
1152 this%lambda%x = lambda
1154 end subroutine mma_subsolve_dip_cpu
1156end submodule mma_cpu