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
45 module subroutine mma_update_cpu(this, iter, x, df0dx, fval, dfdx)
53 class(mma_t),
intent(inout) :: this
54 integer,
intent(in) :: iter
55 real(kind=rp),
dimension(this%n),
intent(inout) :: x
56 real(kind=rp),
dimension(this%n),
intent(in) :: df0dx
57 real(kind=rp),
dimension(this%m),
intent(in) :: fval
58 real(kind=rp),
dimension(this%m, this%n),
intent(in) :: dfdx
60 if (.not. this%is_initialized)
then
61 call neko_error(
"The MMA object is not initialized.")
64 call profiler_start_region(
"MMA update")
67 call profiler_start_region(
"MMA gensub")
68 call mma_gensub_cpu(this, iter, x, df0dx, fval, dfdx)
69 call profiler_end_region(
"MMA gensub")
72 call profiler_start_region(
"MMA subsolve")
73 if (this%subsolver .eq.
"dip")
then
74 call mma_subsolve_dip_cpu(this, x)
75 else if (this%subsolver .eq.
"pdip")
then
76 call mma_subsolve_pdip_cpu(this, x)
78 call neko_error(
"Unrecognized subsolver for MMA in mma_cpu.")
80 call profiler_end_region(
"MMA subsolve")
82 call profiler_end_region(
"MMA update")
84 this%is_updated = .true.
85 end subroutine mma_update_cpu
88 module subroutine mma_kkt_cpu(this, x, df0dx, fval, dfdx)
108 class(mma_t),
intent(inout) :: this
109 real(kind=rp),
dimension(this%n),
intent(in) :: x
110 real(kind=rp),
dimension(this%n),
intent(in) :: df0dx
111 real(kind=rp),
dimension(this%m),
intent(in) :: fval
112 real(kind=rp),
dimension(this%m, this%n),
intent(in) :: dfdx
114 call profiler_start_region(
"MMA KKT computation")
116 if (this%subsolver .eq.
"dip")
then
117 call mma_dip_kkt_cpu(this, x, df0dx, fval, dfdx)
118 else if (this%subsolver .eq.
"pdip")
then
119 call mma_pdip_kkt_cpu(this, x, df0dx, fval, dfdx)
121 call neko_error(
"Unrecognized subsolver for MMA in mma_cpu.")
124 call profiler_end_region(
"MMA KKT computation")
125 end subroutine mma_kkt_cpu
129 module subroutine mma_pdip_kkt_cpu(this, x, df0dx, fval, dfdx)
149 class(mma_t),
intent(inout) :: this
150 real(kind=rp),
dimension(this%n),
intent(in) :: x
151 real(kind=rp),
dimension(this%n),
intent(in) :: df0dx
152 real(kind=rp),
dimension(this%m),
intent(in) :: fval
153 real(kind=rp),
dimension(this%m, this%n),
intent(in) :: dfdx
155 real(kind=rp) :: rez, rezeta
156 real(kind=rp),
dimension(this%m) :: rey, relambda, remu, res
157 real(kind=rp),
dimension(this%n) :: rex, rexsi, reeta
158 real(kind=rp),
dimension(3*this%n+4*this%m+2) :: residual
160 real(kind=rp),
dimension(4*this%m+2) :: residual_small
162 real(kind=rp) :: re_sq_norm
164 rex = df0dx + matmul(transpose(dfdx), this%lambda%x) &
165 - this%xsi%x + this%eta%x
166 rey = this%c%x + this%d%x*this%y%x - this%lambda%x - this%mu%x
167 rez = this%a0 - this%zeta - dot_product(this%lambda%x, this%a%x)
169 relambda = fval - this%a%x * this%z - this%y%x + this%s%x
170 rexsi = this%xsi%x * (x - this%xmin%x)
171 reeta = this%eta%x * (this%xmax%x - x)
172 remu = this%mu%x * this%y%x
173 rezeta = this%zeta * this%z
174 res = this%lambda%x * this%s%x
176 residual = [rex, rey, rez, relambda, rexsi, reeta, remu, rezeta, res]
177 residual_small = [rey, rez, relambda, remu, rezeta, res]
179 this%residumax = maxval(abs(residual))
180 re_sq_norm = norm2(rex)**2 + norm2(rexsi)**2 + norm2(reeta)**2
182 call mpi_allreduce(mpi_in_place, this%residumax, 1, &
183 mpi_real_precision, mpi_max, neko_comm, ierr)
185 call mpi_allreduce(mpi_in_place, re_sq_norm, 1, &
186 mpi_real_precision, mpi_sum, neko_comm, ierr)
188 this%residunorm = sqrt(norm2(residual_small)**2 + re_sq_norm)
189 end subroutine mma_pdip_kkt_cpu
193 module subroutine mma_dip_kkt_cpu(this, x, df0dx, fval, dfdx)
213 class(mma_t),
intent(inout) :: this
214 real(kind=rp),
dimension(this%n),
intent(in) :: x
215 real(kind=rp),
dimension(this%n),
intent(in) :: df0dx
216 real(kind=rp),
dimension(this%m),
intent(in) :: fval
217 real(kind=rp),
dimension(this%m, this%n),
intent(in) :: dfdx
219 real(kind=rp),
dimension(this%m) :: relambda, remu
220 real(kind=rp),
dimension(2*this%m) :: residual
223 relambda = fval - this%a%x * this%z - this%y%x + this%mu%x
225 remu = this%lambda%x * this%mu%x
227 residual = abs([relambda, remu])
228 this%residumax = maxval(residual)
229 this%residunorm = norm2(residual)
231 end subroutine mma_dip_kkt_cpu
237 subroutine mma_gensub_cpu(this, iter, x, df0dx, fval, dfdx)
243 class(mma_t),
intent(inout) :: this
244 real(kind=rp),
dimension(this%n),
intent(in) :: x
245 real(kind=rp),
dimension(this%n),
intent(in) :: df0dx
246 real(kind=rp),
dimension(this%m),
intent(in) :: fval
247 real(kind=rp),
dimension(this%m, this%n),
intent(in) :: dfdx
248 integer,
intent(in) :: iter
249 integer :: i, j, ierr
250 real(kind=rp),
dimension(this%n) :: xmin_eff, xmax_eff
251 real(kind=rp),
dimension(this%n) :: x_diff
252 real(kind=rp) :: asy_factor
254 xmin_eff = this%xmin%x
255 xmax_eff = this%xmax%x
256 if (this%move_limit .gt. 0.0_rp)
then
257 xmin_eff = max(xmin_eff, x - this%move_limit)
258 xmax_eff = min(xmax_eff, x + this%move_limit)
261 x_diff = max(xmax_eff - xmin_eff, 1.0e-5_rp)
265 associate(low => this%low%x, upp => this%upp%x, &
266 x_1 => this%xold1%x, x_2 => this%xold2%x)
268 if (iter .lt. 3)
then
270 low = x - this%asyinit * x_diff
271 upp = x + this%asyinit * x_diff
274 if ((x(j) - x_1(j)) * (x_1(j) - x_2(j)) .lt. 0.0_rp)
then
275 asy_factor = this%asydecr
276 else if ((x(j) - x_1(j)) * (x_1(j) - x_2(j)) .gt. 0.0_rp)
then
277 asy_factor = this%asyincr
282 low(j) = x(j) - asy_factor * (x_1(j) - low(j))
283 upp(j) = x(j) + asy_factor * (upp(j) - x_1(j))
289 low = max(low, x - 10.0_rp * x_diff)
290 low = min(low, x - 0.01_rp * x_diff)
292 upp = min(upp, x + 10.0_rp * x_diff)
293 upp = max(upp, x + 0.01_rp * x_diff)
307 associate(alpha => this%alpha%x, beta => this%beta%x, &
308 xmin => xmin_eff, xmax => xmax_eff, &
309 low => this%low%x, upp => this%upp%x, x => x)
311 alpha = max(xmin, low + 0.1_rp*(x - low), x - 0.5_rp*x_diff)
312 beta = min(xmax, upp - 0.1_rp*(upp - x), x + 0.5_rp*x_diff)
319 associate(p0j => this%p0j%x, q0j => this%q0j%x, &
320 pij => this%pij%x, qij => this%qij%x, &
321 low => this%low%x, upp => this%upp%x)
324 1.001_rp * max(df0dx, 0.0_rp) &
325 + 0.001_rp * max(-df0dx, 0.0_rp) &
326 + 0.00001_rp / max(x_diff, 0.00001_rp) &
330 0.001_rp * max(df0dx, 0.0_rp) &
331 + 1.001_rp * max(-df0dx, 0.0_rp) &
332 + 0.00001_rp / max(x_diff, 0.00001_rp)&
338 1.001_rp * max(dfdx(i, j), 0.0_rp) &
339 + 0.001_rp * max(-dfdx(i, j), 0.0_rp) &
340 + 0.00001_rp / max(x_diff(j), 0.00001_rp) &
341 ) * (upp(j) - x(j))**2
344 0.001_rp * max(dfdx(i, j), 0.0_rp) &
345 + 1.001_rp * max(-dfdx(i, j), 0.0_rp) &
346 + 0.00001_rp / max(x_diff(j), 0.00001_rp) &
347 ) * (x(j) - low(j))**2
356 associate(bi => this%bi%x, &
357 pij => this%pij%x, qij => this%qij%x, &
358 low => this%low%x, upp => this%upp%x)
364 + pij(i, j) / (upp(j) - x(j)) &
365 + qij(i, j) / (x(j) - low(j))
369 call mpi_allreduce(mpi_in_place, bi, this%m, &
370 mpi_real_precision, mpi_sum, neko_comm, ierr)
374 end subroutine mma_gensub_cpu
378 subroutine mma_subsolve_pdip_cpu(this, designx)
389 class(mma_t),
intent(inout) :: this
390 real(kind=rp),
dimension(this%n),
intent(inout) :: designx
393 integer :: i, j, k, iter, itto, ierr
394 real(kind=rp) :: epsi, residual_max, residual_norm, &
395 z, zeta, rez, rezeta, &
397 steg, zold, zetaold, new_residual
398 real(kind=rp),
dimension(this%m) :: y, lambda, s, mu, &
399 rey, relambda, remu, res, &
401 dy, dlambda, ds, dmu, &
402 yold, lambdaold, sold, muold
403 real(kind=rp),
dimension(this%n) :: x, xsi, eta, &
405 delx, diagx, dx, dxsi, deta, &
407 real(kind=rp),
dimension(4*this%m + 2) :: residual_small
408 real(kind=rp),
dimension(3*this%n + 4*this%m + 2) :: residual
409 real(kind=rp),
dimension(2*this%n + 4*this%m + 2) :: xx, dxx
411 real(kind=rp),
dimension(this%m, this%n) :: gg
412 real(kind=rp),
dimension(this%m+1) :: bb
413 real(kind=rp),
dimension(this%m+1, this%m+1) :: aa
414 real(kind=rp),
dimension(this%m * this%m) :: aa_buffer
419 integer,
dimension(this%m+1) :: ipiv
422 real(kind=rp) :: re_sq_norm
423 real(kind=rp) :: minimal_epsilon
430 x = 0.5_rp * (this%alpha%x + this%beta%x)
436 xsi = max(1.0_rp, 1.0_rp / (x - this%alpha%x))
437 eta = max(1.0_rp, 1.0_rp / (this%beta%x - x))
438 mu = max(1.0_rp, 0.5_rp * this%c%x)
443 minimal_epsilon = max(0.9_rp * this%epsimin, 1.0e-12_rp)
444 call mpi_allreduce(mpi_in_place, minimal_epsilon, 1, &
445 mpi_real_precision, mpi_min, neko_comm, ierr)
450 do while (epsi .gt. minimal_epsilon)
457 associate(p0j => this%p0j%x, q0j => this%q0j%x, &
458 pij => this%pij%x, qij => this%qij%x, &
459 low => this%low%x, upp => this%upp%x, &
460 alpha => this%alpha%x, beta => this%beta%x, &
461 c => this%c%x, d => this%d%x, &
462 a0 => this%a0, a => this%a%x)
464 rex = (p0j + matmul(transpose(pij), lambda)) / (upp - x)**2 &
465 - (q0j + matmul(transpose(qij), lambda)) / (x - low)**2 &
468 rey = c + d * y - lambda - mu
469 rez = a0 - zeta - dot_product(lambda, a)
475 relambda(i) = relambda(i) &
476 + pij(i, j) / (upp(j) - x(j)) &
477 + qij(i, j) / (x(j) - low(j))
487 call mpi_allreduce(mpi_in_place, relambda, this%m, &
488 mpi_real_precision, mpi_sum, neko_comm, ierr)
489 relambda = relambda - this%a%x*z - y + s - this%bi%x
491 rexsi = xsi * (x - this%alpha%x) - epsi
492 reeta = eta * (this%beta%x - x) - epsi
494 rezeta = zeta * z - epsi
495 res = lambda * s - epsi
498 residual = [rex, rey, rez, relambda, rexsi, reeta, remu, rezeta, res]
499 residual_small = [rey, rez, relambda, remu, rezeta, res]
501 residual_max = maxval(abs(residual))
502 re_sq_norm = norm2(rex)**2 + norm2(rexsi)**2 + norm2(reeta)**2
504 call mpi_allreduce(mpi_in_place, residual_max, 1, &
505 mpi_real_precision, mpi_max, neko_comm, ierr)
507 call mpi_allreduce(mpi_in_place, re_sq_norm, &
508 1, mpi_real_precision, mpi_sum, neko_comm, ierr)
510 residual_norm = sqrt(norm2(residual_small)**2 + re_sq_norm)
515 do iter = 1, this%max_iter
518 if (residual_max .lt. epsi)
exit
524 + this%pij%x(i,j) * lambda(i) / (this%upp%x(j) - x(j))**2 &
525 - this%qij%x(i,j) * lambda(i) / (x(j) - this%low%x(j))**2
530 + this%p0j%x / (this%upp%x - x)**2 &
531 - this%q0j%x / (x - this%low%x)**2 &
532 - epsi / (x - this%alpha%x) &
533 + epsi / (this%beta%x - x)
535 dely = this%c%x + this%d%x * y - lambda - epsi / y
536 delz = this%a0 - dot_product(lambda, this%a%x) - epsi / z
542 dellambda(i) = dellambda(i) &
543 + this%pij%x(i, j) / (this%upp%x(j) - x(j)) &
544 + this%qij%x(i, j) / (x(j) - this%low%x(j))
548 call mpi_allreduce(mpi_in_place, dellambda, this%m, &
549 mpi_real_precision, mpi_sum, neko_comm, ierr)
551 dellambda = dellambda - this%a%x*z - y - this%bi%x + epsi / lambda
554 gg(i,:) = this%pij%x(i,:) / (this%upp%x - x)**2 &
555 - this%qij%x(i,:) / (x - this%low%x)**2
559 (this%p0j%x + matmul(transpose(this%pij%x), lambda)) &
560 / (this%upp%x - x)**3 &
561 + (this%q0j%x + matmul(transpose(this%qij%x), lambda)) &
562 / (x - this%low%x)**3
564 diagx = 2.0_rp * diagx &
565 + xsi / (x - this%alpha%x) &
566 + eta / (this%beta%x - x)
580 bb(i) = bb(i) + gg(i, j) * (delx(j) / diagx(j))
584 call mpi_allreduce(mpi_in_place, bb, this%m, &
585 mpi_real_precision, mpi_sum, neko_comm, ierr)
587 bb(1:this%m) = dellambda + dely / (this%d%x + mu / y) - bb(1:this%m)
588 bb(this%m + 1) = delz
605 aa(i, j) = aa(i, j) &
606 + gg(i, k) * (1.0_rp / diagx(k)) * gg(j, k)
611 aa_buffer = reshape(aa(1:this%m, 1:this%m), [this%m * this%m])
613 call mpi_allreduce(mpi_in_place, aa_buffer, &
614 this%m*this%m, mpi_real_precision, mpi_sum, neko_comm, ierr)
616 aa(1:this%m, 1:this%m) = reshape(aa_buffer, [this%m, this%m])
620 aa(i, i) = aa(i, i) &
622 + 1.0_rp / (this%d%x(i) + mu(i) / y(i))
625 aa(1:this%m, this%m+1) = this%a%x
626 aa(this%m+1, 1:this%m) = this%a%x
627 aa(this%m+1, this%m+1) = - zeta/z
629 call dgesv(this%m + 1, 1, aa, this%m + 1, ipiv, bb, this%m + 1, info)
631 if (info .ne. 0)
then
632 call neko_error(
"DGESV failed to solve the linear system in " // &
633 "mma_subsolve_pdip.")
637 dlambda = bb(1:this%m)
641 dx = - delx / diagx - matmul(transpose(gg), dlambda) / diagx
642 dy = (-dely + dlambda) / (this%d%x + mu / y)
644 dxsi = -xsi + (epsi - dx * xsi) / (x - this%alpha%x)
645 deta = -eta + (epsi + dx * eta) / (this%beta%x - x)
646 dmu = -mu + (epsi - mu * dy) / y
647 dzeta = -zeta + (epsi - zeta * dz) / z
648 ds = -s + (epsi - dlambda * s) / lambda
650 dxx = [dy, dz, dlambda, dxsi, deta, dmu, dzeta, ds]
651 xx = [y, z, lambda, xsi, eta, mu, zeta, s]
653 steg = 1.0_rp / maxval([ &
655 -1.01_rp * dxx / xx, &
656 -1.01_rp * dx / (x - this%alpha%x), &
657 1.01_rp * dx / (this%beta%x - x) &
671 new_residual = 2.0_rp * residual_norm
674 call mpi_allreduce(mpi_in_place, steg, 1, &
675 mpi_real_precision, mpi_min, neko_comm, ierr)
676 call mpi_allreduce(mpi_in_place, new_residual, 1, &
677 mpi_real_precision, mpi_min, neko_comm, ierr)
682 do while ((new_residual .gt. residual_norm) .and. (itto .lt. 50))
690 lambda = lambdaold + steg*dlambda
691 xsi = xsiold + steg*dxsi
692 eta = etaold + steg*deta
693 mu = muold + steg*dmu
694 zeta = zetaold + steg*dzeta
699 rex = (this%p0j%x + matmul(transpose(this%pij%x), lambda)) &
700 / (this%upp%x - x)**2 &
701 - (this%q0j%x + matmul(transpose(this%qij%x), lambda)) &
702 / (x - this%low%x)**2 &
705 rey = this%c%x + this%d%x*y - lambda - mu
706 rez = this%a0 - zeta - dot_product(lambda, this%a%x)
712 relambda(i) = relambda(i) &
713 + this%pij%x(i, j) / (this%upp%x(j) - x(j)) &
714 + this%qij%x(i, j) / (x(j) - this%low%x(j))
718 call mpi_allreduce(mpi_in_place, relambda, this%m, &
719 mpi_real_precision, mpi_sum, neko_comm, ierr)
721 relambda = relambda - this%a%x*z - y + s - this%bi%x
723 rexsi = xsi * (x - this%alpha%x) - epsi
724 reeta = eta * (this%beta%x - x) - epsi
726 rezeta = zeta * z - epsi
727 res = lambda * s - epsi
730 re_sq_norm = norm2(rex)**2 + norm2(rexsi)**2 + norm2(reeta)**2
731 call mpi_allreduce(mpi_in_place, re_sq_norm, &
732 1, mpi_real_precision, mpi_sum, neko_comm, ierr)
734 residual_small = [rey, rez, relambda, remu, rezeta, res]
735 new_residual = sqrt(norm2(residual_small)**2 + re_sq_norm)
736 call mpi_allreduce(mpi_in_place, new_residual, 1, &
737 mpi_real_precision, mpi_min, neko_comm, ierr)
743 residual = [rex, rey, rez, relambda, rexsi, reeta, remu, rezeta, res]
746 residual_norm = new_residual
747 residual_max = maxval(abs(residual))
748 call mpi_allreduce(mpi_in_place, residual_max, 1, &
749 mpi_real_precision, mpi_max, neko_comm, ierr)
756 this%xold2%x = this%xold1%x
757 this%xold1%x = designx
763 this%lambda%x = lambda
770 end subroutine mma_subsolve_pdip_cpu
774 subroutine mma_subsolve_dip_cpu(this, designx)
812 class(mma_t),
intent(inout) :: this
813 real(kind=rp),
dimension(this%n),
intent(inout) :: designx
816 integer :: i, j, k, iter, ierr
817 real(kind=rp) :: epsi, residual_max, z, steg
818 real(kind=rp),
dimension(this%m) :: y, lambda, mu, &
819 relambda, remu, dlambda, dmu, gradlambda
820 real(kind=rp),
dimension(this%n) :: x, pjlambda, qjlambda
826 real(kind=rp),
dimension(this%n) :: ljjxinv
827 real(kind=rp),
dimension(this%m,this%n) :: hijx
828 real(kind=rp),
dimension(this%m,this%m) :: hess
829 real(kind=rp) :: hesstrace
835 integer,
dimension(this%m+1) :: ipiv
838 real(kind=rp) :: minimal_epsilon
848 lambda = max(1.0_rp, 0.5_rp * this%c%x)
856 minimal_epsilon = max(0.9_rp * this%epsimin, 1.0e-12_rp)
857 call mpi_allreduce(mpi_in_place, minimal_epsilon, 1, &
858 mpi_real_precision, mpi_min, neko_comm, ierr)
863 do while (epsi .gt. minimal_epsilon)
870 associate(p0j => this%p0j%x, q0j => this%q0j%x, &
871 pij => this%pij%x, qij => this%qij%x, &
872 low => this%low%x, upp => this%upp%x, &
873 alpha => this%alpha%x, beta => this%beta%x, &
874 c => this%c%x, d => this%d%x, &
875 a0 => this%a0, a => this%a%x, &
883 y = max(0.0_rp, lambda - c)
888 z = max(0.0_rp,dot_product(lambda, a) - a0)
894 pjlambda = (p0j + matmul(transpose(pij), lambda))
895 qjlambda = (q0j + matmul(transpose(qij), lambda))
896 x = (sqrt(pjlambda) * low + sqrt(qjlambda) * upp) / &
897 (sqrt(pjlambda) + sqrt(qjlambda))
900 x = merge(alpha, x, x .lt. alpha)
901 x = merge(beta, x, x .gt. beta)
904 relambda = matmul(pij, 1.0_rp / (upp - x)) + &
905 matmul(qij, 1.0_rp / (x - low))
908 call mpi_allreduce(mpi_in_place, relambda, this%m, &
909 mpi_real_precision, mpi_sum, neko_comm, ierr)
910 relambda = relambda - bi - y - a * z + mu
913 remu = mu * lambda - epsi
915 residual_max = maxval(abs([relambda, remu]))
916 call mpi_allreduce(mpi_in_place, residual_max, 1, &
917 mpi_real_precision, mpi_max, neko_comm, ierr)
921 do iter = 1, this%max_iter
924 if (residual_max .lt. epsi)
exit
928 gradlambda = matmul(pij, 1.0_rp / (upp - x)) + &
929 matmul(qij, 1.0_rp/(x - low))
932 call mpi_allreduce(mpi_in_place, gradlambda, this%m, &
933 mpi_real_precision, mpi_sum, neko_comm, ierr)
934 gradlambda = gradlambda - bi - y - a * z
937 gradlambda = - gradlambda - epsi / lambda
943 ljjxinv= - 1.0_rp / ( (2.0_rp * pjlambda/(upp - x)**3) + &
944 (2.0_rp * qjlambda/(x - low)**3))
948 ljjxinv = merge(0.0_rp, ljjxinv, x - alpha < neko_eps)
949 ljjxinv = merge(0.0_rp, ljjxinv, beta - x < neko_eps)
952 hijx(i,:) = pij(i,:) / (upp - x)**2 &
953 - qij(i,:) / (x - low)**2
963 hess(i, j) = hess(i, j) &
964 + hijx(i, k) * (ljjxinv(k)) * hijx(j, k)
969 call mpi_allreduce(mpi_in_place, hess, &
970 this%m * this%m, mpi_real_precision, mpi_sum, neko_comm, ierr)
975 if (dot_product(lambda, a) .gt. 0.0_rp)
then
978 hess(i, j) = hess(i, j) - a(i) * a(j)
986 if (y(i) .gt. 0.0_rp)
then
987 hess(i, i) = hess(i, i) - 1.0_rp
990 hess(i, i) = hess(i, i) - mu(i) / lambda(i)
997 hesstrace = hesstrace + hess(i, i)
1000 hess(i,i) = hess(i, i) - &
1001 max(-1.0e-4_rp*hesstrace/this%m, 1.0e-7_rp)
1004 call dgesv(this%m , 1, hess, this%m , ipiv, &
1005 gradlambda, this%m, info)
1007 if (info .ne. 0)
then
1008 call neko_error(
"DGESV failed to solve the linear system in " // &
1009 "mma_subsolve_dip.")
1011 dlambda = gradlambda
1014 dmu = -mu + epsi / lambda - dlambda * mu / lambda
1020 steg = merge(-1.01_rp * dlambda(i) / lambda(i), steg, &
1021 steg < -1.01_rp * dlambda(i) / lambda(i))
1022 steg = merge(-1.01_rp * dmu(i) / mu(i), &
1023 steg, steg < -1.01_rp * dmu(i) / mu(i))
1026 steg = 1.0_rp / steg
1028 lambda = lambda + steg*dlambda
1037 y = max(0.0_rp, lambda - c)
1043 z = max(0.0_rp,dot_product(lambda, a) - a0)
1049 pjlambda = (p0j + matmul(transpose(pij), lambda))
1050 qjlambda = (q0j + matmul(transpose(qij), lambda))
1051 x = (sqrt(pjlambda) * low + sqrt(qjlambda) * upp) / &
1052 (sqrt(pjlambda) + sqrt(qjlambda))
1055 x = merge(alpha, x, x .lt. alpha)
1056 x = merge(beta, x, x .gt. beta)
1059 relambda = matmul(pij, 1.0_rp / (upp - x)) + &
1060 matmul(qij, 1.0_rp / (x - low))
1062 call mpi_allreduce(mpi_in_place, relambda, this%m, &
1063 mpi_real_precision, mpi_sum, neko_comm, ierr)
1064 relambda = relambda - bi - y - a * z + mu
1067 remu = mu * lambda - epsi
1069 residual_max = maxval(abs([relambda, remu]))
1070 call mpi_allreduce(mpi_in_place, residual_max, 1, &
1071 mpi_real_precision, mpi_max, neko_comm, ierr)
1075 epsi = 0.1_rp * epsi
1079 this%xold2%x = this%xold1%x
1080 this%xold1%x = designx
1087 this%lambda%x = lambda
1089 end subroutine mma_subsolve_dip_cpu
1091end submodule mma_cpu