25subroutine lx(params, constants, workspace, x, y, ddx_error)
28 type(ddx_params_type),
intent(in) :: params
29 type(ddx_constants_type),
intent(in) :: constants
30 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
32 type(ddx_workspace_type),
intent(inout) :: workspace
34 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
35 type(ddx_error_type),
intent(inout) :: ddx_error
37 integer :: isph, jsph, ij, l, ind, iproc
40 if (ddx_error % flag .eq. 0)
continue
47 if (params % matvecmem .eq. 1)
then
50 do isph = 1, params % nsph
51 do ij = constants % inl(isph), constants % inl(isph + 1) - 1
52 jsph = constants % nl(ij)
53 call dgemv(
'n', constants % nbasis, constants % nbasis, one, &
54 & constants % l(:,:,ij), constants % nbasis, x(:,jsph), 1, &
61 do isph = 1, params % nsph
62 iproc = omp_get_thread_num() + 1
64 call calcv(params, constants, isph, workspace % tmp_pot(:, iproc), x, &
65 & workspace % tmp_work(:, iproc))
66 call ddintegrate(1, constants % nbasis, params % ngrid, &
67 & constants % vwgrid, constants % vgrid_nbasis, &
68 & workspace % tmp_pot(:, iproc), y(:, isph))
70 y(:, isph) = - y(:, isph)
76 if (constants % dodiag)
then
77 do isph = 1, params % nsph
78 do l = 0, params % lmax
80 y(ind-l:ind+l, isph) = y(ind-l:ind+l, isph) + &
81 x(ind-l:ind+l, isph) / (constants % vscales(ind)**2)
88subroutine lstarx(params, constants, workspace, x, y, ddx_error)
91 type(ddx_params_type),
intent(in) :: params
92 type(ddx_constants_type),
intent(in) :: constants
93 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
95 type(ddx_workspace_type),
intent(inout) :: workspace
97 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
98 type(ddx_error_type),
intent(inout) :: ddx_error
100 integer :: isph, jsph, ij, indmat, igrid, l, ind, iproc
103 if (ddx_error % flag .eq. 0)
continue
106 if (params % matvecmem .eq. 1)
then
109 do isph = 1, params % nsph
110 do ij = constants % inl(isph), constants % inl(isph + 1) - 1
111 jsph = constants % nl(ij)
112 indmat = constants % itrnl(ij)
113 call dgemv(
't', constants % nbasis, constants % nbasis, one, &
114 & constants % l(:,:,indmat), constants % nbasis, x(:,jsph), 1, &
122 do isph = 1, params % nsph
123 do igrid = 1, params % ngrid
124 workspace % tmp_grid(igrid, isph) = dot_product(x(:, isph), &
125 & constants % vgrid(:constants % nbasis, igrid))
131 do isph = 1, params % nsph
132 iproc = omp_get_thread_num() + 1
133 call adjrhs(params, constants, isph, workspace % tmp_grid, &
134 & y(:, isph), workspace % tmp_work(:, iproc))
136 y(:, isph) = - y(:, isph)
139 if (constants % dodiag)
then
141 do isph = 1, params % nsph
142 do l = 0, params % lmax
144 y(ind-l:ind+l, isph) = y(ind-l:ind+l, isph) + &
145 & x(ind-l:ind+l, isph) / (constants % vscales(ind)**2)
154subroutine ldm1x(params, constants, workspace, x, y, ddx_error)
157 type(ddx_params_type),
intent(in) :: params
158 type(ddx_constants_type),
intent(in) :: constants
159 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
161 type(ddx_workspace_type),
intent(inout) :: workspace
163 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
164 type(ddx_error_type),
intent(inout) :: ddx_error
166 integer :: isph, l, ind
169 if ((ddx_error % flag .eq. 0) .or. &
170 & (
allocated(workspace % tmp_pot)))
continue
175 do isph = 1, params % nsph
176 do l = 0, params % lmax
178 y(ind-l:ind+l, isph) = x(ind-l:ind+l, isph) &
179 & *(constants % vscales(ind)**2)
185subroutine dx(params, constants, workspace, x, y, ddx_error)
188 type(ddx_params_type),
intent(in) :: params
189 type(ddx_constants_type),
intent(in) :: constants
190 type(ddx_workspace_type),
intent(inout) :: workspace
191 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
193 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
194 type(ddx_error_type),
intent(inout) :: ddx_error
199 if (constants % dodiag) do_diag = 1
201 if (params % fmm .eq. 0)
then
202 call dx_dense(params, constants, workspace, do_diag, x, y, ddx_error)
204 call dx_fmm(params, constants, workspace, do_diag, x, y, ddx_error)
209subroutine dx_dense(params, constants, workspace, do_diag, x, y, ddx_error)
212 type(ddx_params_type),
intent(in) :: params
213 type(ddx_constants_type),
intent(in) :: constants
214 type(ddx_workspace_type),
intent(inout) :: workspace
215 integer,
intent(in) :: do_diag
216 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
217 type(ddx_error_type),
intent(inout) :: ddx_error
219 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
221 real(dp) :: c(3), vij(3), sij(3)
222 real(dp) :: vvij, tij, tt, f, rho, ctheta, stheta, cphi, sphi
223 integer :: its, isph, jsph, l, m, ind
224 real(dp),
external :: dnrm2
227 if (ddx_error % flag .eq. 0)
continue
230 do isph = 1, params % nsph
233 workspace % tmp_grid(:, 1) = zero
234 do its = 1, params % ngrid
235 if (constants % ui(its,isph).gt.zero)
then
236 c = params % csph(:,isph) + params % rsph(isph)* &
237 & constants % cgrid(:,its)
238 do jsph = 1, params % nsph
239 if (jsph.ne.isph)
then
241 vij = c - params % csph(:,jsph)
243 vvij = dnrm2(3, vij, 1)
244 tij = vvij / params % rsph(jsph)
247 call ylmbas(sij, rho, ctheta, stheta, cphi, sphi, &
248 & params % lmax, constants % vscales, &
249 & workspace % tmp_vylm, workspace % tmp_vplm, &
250 & workspace % tmp_vcos, workspace % tmp_vsin)
254 do l = 0, params % lmax
256 f = fourpi*dble(l)/(two*dble(l) + one)*tt
258 workspace % tmp_grid(its, 1) = &
259 & workspace % tmp_grid(its, 1) + &
260 & f*x(ind + m,jsph) * &
261 & workspace % tmp_vylm(ind + m, 1)
265 else if (do_diag .eq. 1)
then
267 do l = 0, params % lmax
269 f = (two*dble(l) + one)/fourpi
271 workspace % tmp_grid(its, 1) = &
272 & workspace % tmp_grid(its, 1) - &
273 & pt5*x(ind + m,isph) * &
274 & constants % vgrid(ind + m,its)/f
279 workspace % tmp_grid(its, 1) = constants % ui(its, isph) * &
280 & workspace % tmp_grid(its, 1)
284 call ddintegrate(1, constants % nbasis, params % ngrid, &
285 & constants % vwgrid, constants % vgrid_nbasis, &
286 & workspace % tmp_grid, y(:,isph))
291subroutine dx_fmm(params, constants, workspace, do_diag, x, y, ddx_error)
294 type(ddx_params_type),
intent(in) :: params
295 type(ddx_constants_type),
intent(in) :: constants
296 type(ddx_workspace_type),
intent(inout) :: workspace
297 integer,
intent(in) :: do_diag
298 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
299 type(ddx_error_type),
intent(inout) :: ddx_error
301 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
303 integer :: isph, inode, l, indl, indl1
306 if (ddx_error % flag .eq. 0)
continue
309 workspace % tmp_sph(1, :) = zero
311 do l = 1, params % lmax
313 workspace % tmp_sph(indl:indl1, :) = l * x(indl:indl1, :)
317 if(params % lmax .lt. params % pm)
then
318 do isph = 1, params % nsph
319 inode = constants % snode(isph)
320 workspace % tmp_node_m(1:constants % nbasis, inode) = &
321 & workspace % tmp_sph(:, isph)
322 workspace % tmp_node_m(constants % nbasis+1:, inode) = zero
325 indl = (params % pm+1)**2
326 do isph = 1, params % nsph
327 inode = constants % snode(isph)
328 workspace % tmp_node_m(:, inode) = workspace % tmp_sph(:indl, isph)
332 call tree_m2m_rotation(params, constants, workspace % tmp_node_m)
333 call tree_m2l_rotation(params, constants, workspace % tmp_node_m, &
334 & workspace % tmp_node_l)
335 call tree_l2l_rotation(params, constants, workspace % tmp_node_l)
336 call tree_l2p(params, constants, one, workspace % tmp_node_l, zero, &
337 & workspace % tmp_grid, workspace % tmp_sph_l)
338 call tree_m2p(params, constants, params % lmax, one, workspace % tmp_sph, one, &
339 & workspace % tmp_grid)
341 if(do_diag .eq. 1)
then
342 call dgemm(
'T',
'N', params % ngrid, params % nsph, &
343 & constants % nbasis, -pt5, constants % vgrid2, &
344 & constants % vgrid_nbasis, x, constants % nbasis, one, &
345 & workspace % tmp_grid, params % ngrid)
348 workspace % tmp_grid = workspace % tmp_grid * constants % ui
351 call dgemm(
'N',
'N', constants % nbasis, params % nsph, params % ngrid, &
352 & one, constants % vwgrid, constants % vgrid_nbasis, workspace % tmp_grid, &
353 & params % ngrid, zero, y, constants % nbasis)
357subroutine dstarx(params, constants, workspace, x, y, ddx_error)
360 type(ddx_params_type),
intent(in) :: params
361 type(ddx_constants_type),
intent(in) :: constants
362 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
364 type(ddx_workspace_type),
intent(inout) :: workspace
366 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
367 type(ddx_error_type),
intent(inout) :: ddx_error
372 if (constants % dodiag) do_diag = 1
374 if (params % fmm .eq. 0)
then
375 call dstarx_dense(params, constants, workspace, do_diag, x, y, ddx_error)
377 call dstarx_fmm(params, constants, workspace, do_diag, x, y, ddx_error)
382subroutine dstarx_dense(params, constants, workspace, do_diag, x, y, ddx_error)
385 type(ddx_params_type),
intent(in) :: params
386 type(ddx_constants_type),
intent(in) :: constants
387 integer,
intent(in) :: do_diag
388 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
390 type(ddx_workspace_type),
intent(inout) :: workspace
391 type(ddx_error_type),
intent(inout) :: ddx_error
393 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
395 real(dp) :: vji(3), sji(3)
396 real(dp) :: vvji, tji, tt, f, rho, ctheta, stheta, cphi, sphi
397 integer :: its, isph, jsph, l, m, ind, iproc
398 real(dp),
external :: dnrm2
401 if (ddx_error % flag .eq. 0)
continue
407 do isph = 1, params % nsph
408 iproc = omp_get_thread_num() + 1
409 do jsph = 1, params % nsph
410 if (jsph.ne.isph)
then
411 do its = 1, params % ngrid
412 if (constants % ui(its,jsph).gt.zero)
then
414 vji = params % csph(:,jsph) + params % rsph(jsph) * &
415 & constants % cgrid(:,its) - params % csph(:,isph)
417 vvji = dnrm2(3, vji, 1)
418 tji = vvji/params % rsph(isph)
421 call ylmbas(sji, rho, ctheta, stheta, cphi, sphi, &
422 & params % lmax, constants % vscales, &
423 & workspace % tmp_vylm(:(params % lmax + 1)**2, iproc), &
424 & workspace % tmp_vplm(:(params % lmax + 1)**2, iproc), &
425 & workspace % tmp_vcos(:(params % lmax + 1), iproc), &
426 & workspace % tmp_vsin(:(params % lmax + 1), iproc))
427 tt = constants % ui(its,jsph) &
428 & *dot_product(constants % vwgrid(:constants % nbasis, its), &
430 do l = 0, params % lmax
432 f = dble(l)*tt/ constants % vscales(ind)**2
434 y(ind+m,isph) = y(ind+m,isph) + &
435 & f*workspace % tmp_vylm(ind+m, iproc)
441 else if (do_diag .eq. 1)
then
442 do its = 1, params % ngrid
443 f = pt5*constants % ui(its,jsph) &
444 & *dot_product(constants % vwgrid(:constants % nbasis, its), &
446 do l = 0, params % lmax
448 y(ind-l:ind+l,isph) = y(ind-l:ind+l,isph) - &
449 & f*constants % vgrid(ind-l:ind+l,its)/ &
450 & constants % vscales(ind)**2
459subroutine dstarx_fmm(params, constants, workspace, do_diag, x, y, ddx_error)
462 type(ddx_params_type),
intent(in) :: params
463 type(ddx_constants_type),
intent(in) :: constants
464 integer,
intent(in) :: do_diag
465 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
467 type(ddx_workspace_type),
intent(inout) :: workspace
468 type(ddx_error_type),
intent(inout) :: ddx_error
470 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
472 integer :: isph, inode, l, indl, indl1
475 if (ddx_error % flag .eq. 0)
continue
478 call dgemm(
'T',
'N', params % ngrid, params % nsph, constants % nbasis, &
479 & one, constants % vwgrid, constants % vgrid_nbasis, x, &
480 & constants % nbasis, zero, workspace % tmp_grid, params % ngrid)
482 workspace % tmp_grid = workspace % tmp_grid * constants % ui
484 call tree_m2p_adj(params, constants, params % lmax, one, workspace % tmp_grid, &
486 call tree_l2p_adj(params, constants, one, workspace % tmp_grid, zero, &
487 & workspace % tmp_node_l, workspace % tmp_sph_l)
488 call tree_l2l_rotation_adj(params, constants, workspace % tmp_node_l)
489 call tree_m2l_rotation_adj(params, constants, workspace % tmp_node_l, &
490 & workspace % tmp_node_m)
491 call tree_m2m_rotation_adj(params, constants, workspace % tmp_node_m)
493 if(params % lmax .lt. params % pm)
then
494 do isph = 1, params % nsph
495 inode = constants % snode(isph)
496 y(:, isph) = y(:, isph) + &
497 & workspace % tmp_node_m(1:constants % nbasis, inode)
500 indl = (params % pm+1)**2
501 do isph = 1, params % nsph
502 inode = constants % snode(isph)
503 y(1:indl, isph) = y(1:indl, isph) + workspace % tmp_node_m(:, inode)
509 do l = 1, params % lmax
511 y(indl:indl1, :) = l * y(indl:indl1, :)
515 if(do_diag .eq. 1)
then
516 call dgemm(
'N',
'N', constants % nbasis, params % nsph, &
517 & params % ngrid, -pt5, constants % vgrid2, &
518 & constants % vgrid_nbasis, workspace % tmp_grid, params % ngrid, &
519 & one, y, constants % nbasis)
527subroutine repsx(params, constants, workspace, x, y, ddx_error)
530 type(ddx_params_type),
intent(in) :: params
531 type(ddx_constants_type),
intent(in) :: constants
532 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
534 type(ddx_workspace_type),
intent(inout) :: workspace
536 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
537 type(ddx_error_type),
intent(inout) :: ddx_error
541 call dx(params, constants, workspace, x, y, ddx_error)
543 if (constants % dodiag)
then
545 fac = twopi * (params % eps + one) / (params % eps - one)
555subroutine repsstarx(params, constants, workspace, x, y, ddx_error)
558 type(ddx_params_type),
intent(in) :: params
559 type(ddx_constants_type),
intent(in) :: constants
560 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
562 type(ddx_workspace_type),
intent(inout) :: workspace
564 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
565 type(ddx_error_type),
intent(inout) :: ddx_error
569 call dstarx(params, constants, workspace, x, y, ddx_error)
572 if (constants % dodiag)
then
573 fac = twopi * (params % eps + one) / (params % eps - one)
587subroutine rinfx(params, constants, workspace, x, y, ddx_error)
590 type(ddx_params_type),
intent(in) :: params
591 type(ddx_constants_type),
intent(in) :: constants
592 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
594 type(ddx_workspace_type),
intent(inout) :: workspace
596 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
597 type(ddx_error_type),
intent(inout) :: ddx_error
600 if (params % fmm .eq. 0)
then
601 call dx_dense(params, constants, workspace, 1, x, y, ddx_error)
603 call dx_fmm(params, constants, workspace, 1, x, y, ddx_error)
618subroutine rstarinfx(params, constants, workspace, x, y, ddx_error)
621 type(ddx_params_type),
intent(in) :: params
622 type(ddx_constants_type),
intent(in) :: constants
623 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
625 type(ddx_workspace_type),
intent(inout) :: workspace
627 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
628 type(ddx_error_type),
intent(inout) :: ddx_error
630 call dstarx(params, constants, workspace, x, y, ddx_error)
637subroutine prec_repsx(params, constants, workspace, x, y, ddx_error)
640 type(ddx_params_type),
intent(in) :: params
641 type(ddx_constants_type),
intent(in) :: constants
642 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
644 type(ddx_workspace_type),
intent(inout) :: workspace
646 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
647 type(ddx_error_type),
intent(inout) :: ddx_error
651 if ((ddx_error % flag .eq. 0) .or. &
652 & (
allocated(workspace % tmp_pot)))
continue
657 do isph = 1, params % nsph
658 call dgemm(
'N',
'N', constants % nbasis, 1, constants % nbasis, one, &
659 & constants % rx_prc(:, :, isph), constants % nbasis, x(:, isph), &
660 & constants % nbasis, zero, y(:, isph), constants % nbasis)
668 type(ddx_params_type),
intent(in) :: params
669 type(ddx_constants_type),
intent(in) :: constants
670 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
672 type(ddx_workspace_type),
intent(inout) :: workspace
674 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
675 type(ddx_error_type),
intent(inout) :: ddx_error
680 if ((ddx_error % flag .eq. 0) .or. &
681 & (
allocated(workspace % tmp_pot)))
continue
686 do isph = 1, params % nsph
687 call dgemm(
'T',
'N', constants % nbasis, 1, constants % nbasis, one, &
688 & constants % rx_prc(:, :, isph), constants % nbasis, x(:, isph), &
689 & constants % nbasis, zero, y(:, isph), constants % nbasis)
694subroutine bstarx(params, constants, workspace, x, y, ddx_error)
696 type(ddx_params_type),
intent(in) :: params
697 type(ddx_constants_type),
intent(in) :: constants
698 type(ddx_workspace_type),
intent(inout) :: workspace
699 real(dp),
intent(in) :: x(constants % nbasis, params % nsph)
700 real(dp),
intent(out) :: y(constants % nbasis, params % nsph)
701 type(ddx_error_type),
intent(inout) :: ddx_error
703 integer :: isph, jsph, ij, indmat, iproc
706 if (ddx_error % flag .eq. 0)
continue
709 if (params % matvecmem .eq. 1)
then
712 do isph = 1, params % nsph
713 do ij = constants % inl(isph), constants % inl(isph + 1) - 1
714 jsph = constants % nl(ij)
715 indmat = constants % itrnl(ij)
716 call dgemv(
't', constants % nbasis, constants % nbasis, one, &
717 & constants % b(:,:,indmat), constants % nbasis, x(:,jsph), 1, &
724 do isph = 1, params % nsph
725 call dgemv(
't', constants % nbasis, params % ngrid, one, constants % vgrid, &
726 & constants % vgrid_nbasis, x(:, isph), 1, zero, &
727 & workspace % tmp_grid(:, isph), 1)
731 do isph = 1, params % nsph
732 iproc = omp_get_thread_num() + 1
733 call adjrhs_lpb(params, constants, isph, workspace % tmp_grid, &
734 & y(:, isph), workspace % tmp_vylm(:, iproc), workspace % tmp_vplm(:, iproc), &
735 & workspace % tmp_vcos(:, iproc), workspace % tmp_vsin(:, iproc), &
736 & workspace % tmp_bessel(:, iproc))
737 y(:,isph) = - y(:,isph)
742 if (constants % dodiag) y = y + x
746subroutine bx(params, constants, workspace, x, y, ddx_error)
748 type(ddx_params_type),
intent(in) :: params
749 type(ddx_constants_type),
intent(in) :: constants
750 type(ddx_workspace_type),
intent(inout) :: workspace
751 real(dp),
dimension(constants % nbasis, params % nsph),
intent(in) :: x
752 real(dp),
dimension(constants % nbasis, params % nsph),
intent(out) :: y
753 type(ddx_error_type),
intent(inout) :: ddx_error
754 integer :: isph, jsph, ij, iproc
757 if (ddx_error % flag .eq. 0)
continue
760 if (params % matvecmem .eq. 1)
then
763 do isph = 1, params % nsph
764 do ij = constants % inl(isph), constants % inl(isph + 1) - 1
765 jsph = constants % nl(ij)
766 call dgemv(
'n', constants % nbasis, constants % nbasis, one, &
767 & constants % b(:,:,ij), constants % nbasis, x(:,jsph), 1, &
774 do isph = 1, params % nsph
775 iproc = omp_get_thread_num() + 1
776 call calcv2_lpb(params, constants, isph, workspace % tmp_pot(:, iproc), x)
777 call ddintegrate(1, constants % nbasis, params % ngrid, constants % vwgrid, &
778 & constants % vgrid_nbasis, workspace % tmp_pot(:, iproc), y(:,isph))
779 y(:,isph) = - y(:,isph)
782 if (constants % dodiag) y = y + x
786subroutine tstarx(params, constants, workspace, x, y, ddx_error)
788 type(ddx_params_type),
intent(in) :: params
789 type(ddx_constants_type),
intent(in) :: constants
790 type(ddx_workspace_type),
intent(inout) :: workspace
791 real(dp),
dimension(constants % nbasis, params % nsph, 2),
intent(in) :: x
792 real(dp),
dimension(constants % nbasis, params % nsph, 2),
intent(out) :: y
793 type(ddx_error_type),
intent(inout) :: ddx_error
795 real(dp),
dimension(constants % nbasis, params % nsph, 2) :: temp_vector
801 call lstarx(params, constants, workspace, x(:,:,1), temp_vector(:,:,1), &
804 call convert_ddcosmo(params, constants, 1, temp_vector(:,:,1))
805 y(:,:,1) = y(:,:,1) + temp_vector(:,:,1)
807 call bstarx(params, constants, workspace, x(:,:,2), temp_vector(:,:,2), &
809 y(:,:,2) = y(:,:,2) + temp_vector(:,:,2)
814 call cstarx(params, constants, workspace, x, temp_vector, ddx_error)
820subroutine bx_prec(params, constants, workspace, x, y, ddx_error)
822 type(ddx_params_type),
intent(in) :: params
823 type(ddx_constants_type),
intent(in) :: constants
824 type(ddx_workspace_type),
intent(inout) :: workspace
825 real(dp),
dimension(constants % nbasis, params % nsph),
intent(in) :: x
826 real(dp),
dimension(constants % nbasis, params % nsph),
intent(out) :: y
827 type(ddx_error_type),
intent(inout) :: ddx_error
830 if ((ddx_error % flag .eq. 0) .or. &
831 & (
allocated(workspace % tmp_pot)))
continue
837subroutine prec_tstarx(params, constants, workspace, x, y, ddx_error)
839 type(ddx_params_type),
intent(in) :: params
840 type(ddx_constants_type),
intent(in) :: constants
841 type(ddx_workspace_type),
intent(inout) :: workspace
842 real(dp),
intent(in) :: x(constants % nbasis, params % nsph, 2)
843 real(dp),
intent(inout) :: y(constants % nbasis, params % nsph, 2)
844 type(ddx_error_type),
intent(inout) :: ddx_error
846 real(dp),
dimension(params % maxiter) :: x_rel_diff
847 real(dp) :: start_time
849 start_time = omp_get_wtime()
851 call convert_ddcosmo(params, constants, 1, y(:,:,1))
852 n_iter = params % maxiter
853 call jacobi_diis(params, constants, workspace, constants % inner_tol, &
854 & y(:,:,1), workspace % ddcosmo_guess, n_iter, x_rel_diff,
lstarx, &
855 &
ldm1x, hnorm, ddx_error)
856 if (ddx_error % flag .ne. 0)
then
857 call update_error(ddx_error,
'prec_tstarx: ddCOSMO failed to ' // &
858 &
'converge, exiting')
861 y(:,:,1) = workspace % ddcosmo_guess
862 workspace % s_time = workspace % s_time + omp_get_wtime() - start_time
864 start_time = omp_get_wtime()
865 n_iter = params % maxiter
866 call jacobi_diis(params, constants, workspace, constants % inner_tol, &
867 & x(:,:,2), workspace % hsp_guess, n_iter, x_rel_diff,
bstarx, &
869 if (ddx_error % flag .ne. 0)
then
870 call update_error(ddx_error,
'prec_tstarx: HSP failed to ' // &
871 &
'converge, exiting')
874 y(:,:,2) = workspace % hsp_guess
875 workspace % hsp_adj_time = workspace % hsp_adj_time &
876 & + omp_get_wtime() - start_time
887subroutine prec_tx(params, constants, workspace, x, y, ddx_error)
889 type(ddx_params_type),
intent(in) :: params
890 type(ddx_constants_type),
intent(in) :: constants
891 type(ddx_workspace_type),
intent(inout) :: workspace
892 real(dp),
intent(in) :: x(constants % nbasis, params % nsph, 2)
893 real(dp),
intent(inout) :: y(constants % nbasis, params % nsph, 2)
894 type(ddx_error_type),
intent(inout) :: ddx_error
896 real(dp),
dimension(params % maxiter) :: x_rel_diff
897 real(dp) :: start_time
900 start_time = omp_get_wtime()
901 n_iter = params % maxiter
902 call jacobi_diis(params, constants, workspace, constants % inner_tol, &
903 & x(:,:,1), workspace % ddcosmo_guess, n_iter, x_rel_diff,
lx, &
904 &
ldm1x, hnorm, ddx_error)
905 if (ddx_error % flag .ne. 0)
then
906 call update_error(ddx_error,
'prec_tx: ddCOSMO failed to ' // &
907 &
'converge, exiting')
912 y(:,:,1) = workspace % ddcosmo_guess
913 call convert_ddcosmo(params, constants, 1, y(:,:,1))
914 workspace % xs_time = workspace % xs_time + omp_get_wtime() - start_time
917 start_time = omp_get_wtime()
918 n_iter = params % maxiter
919 call jacobi_diis(params, constants, workspace, constants % inner_tol, &
920 & x(:,:,2), workspace % hsp_guess, n_iter, x_rel_diff,
bx, &
922 y(:,:,2) = workspace % hsp_guess
923 workspace % hsp_time = workspace % hsp_time + omp_get_wtime() - start_time
925 if (ddx_error % flag .ne. 0)
then
926 call update_error(ddx_error,
'prec_tx: HSP failed to ' // &
927 &
'converge, exiting')
934subroutine cstarx(params, constants, workspace, x, y, ddx_error)
937 type(ddx_params_type),
intent(in) :: params
938 type(ddx_constants_type),
intent(in) :: constants
939 type(ddx_workspace_type),
intent(inout) :: workspace
940 real(dp),
dimension(constants % nbasis, params % nsph, 2),
intent(in) :: x
941 real(dp),
dimension(constants % nbasis, params % nsph, 2),
intent(out) :: y
942 type(ddx_error_type),
intent(inout) :: ddx_error
944 complex(dp) :: work_complex(constants % lmax0+1)
945 real(dp) :: work(constants % lmax0+1)
946 integer :: isph, igrid, jsph, ind, l0, ind0, indl, inode, l, m
947 real(dp),
dimension(3) :: vij, vtij
948 real(dp) :: val, epsilon_ratio
949 real(dp),
allocatable :: scratch(:,:), scratch0(:,:)
952 if (ddx_error % flag .eq. 0)
continue
954 allocate(scratch(constants % nbasis, params % nsph), &
955 & scratch0(constants % nbasis0, params % nsph))
957 epsilon_ratio = params % epsp/params % eps
960 scratch = - x(:,:,1) - x(:,:,2)
961 call dgemm(
'T',
'N', params % ngrid, params % nsph, constants % nbasis, &
962 & one, constants % vwgrid, constants % vgrid_nbasis, scratch, &
963 & constants % nbasis, zero, workspace % tmp_grid, params % ngrid)
966 if (params % fmm .eq. 0)
then
967 do isph = 1, params % nsph
968 do igrid = 1, params % ngrid
969 if (constants % ui(igrid, isph).gt.zero)
then
970 val = workspace % tmp_grid(igrid,isph) &
971 & *constants % ui(igrid,isph)
973 do jsph = 1, params % nsph
974 vij = params % csph(:,isph) + &
975 & params % rsph(isph)*constants % cgrid(:,igrid) - &
976 & params % csph(:,jsph)
977 vtij = vij * params % kappa
978 call fmm_m2p_bessel_adj_work(vtij, val, &
979 & constants % SK_ri(:, jsph), constants % lmax0, &
980 & constants % vscales, one, scratch0(:, jsph), &
981 & work_complex, work)
988 workspace % tmp_grid = workspace % tmp_grid * constants % ui
989 workspace % tmp_sph = zero
991 call tree_m2p_bessel_adj(params, constants, constants % lmax0, &
992 & one, workspace % tmp_grid, zero, params % lmax, &
993 & workspace % tmp_sph)
994 call tree_l2p_bessel_adj(params, constants, one, &
995 & workspace % tmp_grid, zero, workspace % tmp_node_l)
996 call tree_l2l_bessel_rotation_adj(params, constants, &
997 & workspace % tmp_node_l)
998 call tree_m2l_bessel_rotation_adj(params, constants, &
999 & workspace % tmp_node_l, workspace % tmp_node_m)
1000 call tree_m2m_bessel_rotation_adj(params, constants, &
1001 & workspace % tmp_node_m)
1003 if(constants % lmax0 .lt. params % pm)
then
1004 do isph = 1, params % nsph
1005 inode = constants % snode(isph)
1006 scratch0(:, isph) = workspace % tmp_sph(1:constants % nbasis0, isph) + &
1007 & workspace % tmp_node_m(1:constants % nbasis0, inode)
1010 indl = (params % pm+1)**2
1011 do isph = 1, params % nsph
1012 inode = constants % snode(isph)
1013 scratch0(1:indl, isph) = &
1014 & workspace % tmp_sph(1:indl, isph) + &
1015 & workspace % tmp_node_m(:, inode)
1016 scratch0(indl+1:, isph) = zero
1021 do isph = 1, params % nsph
1022 do l0 = 0, constants % lmax0
1023 ind0 = l0*l0 + l0 + 1
1024 scratch0(ind0-l0:ind0+l0, isph) = scratch0(ind0-l0:ind0+l0, isph) * &
1025 & constants % C_ik(l0, isph)
1029 do jsph = 1, params % nsph
1030 call dgemv(
'n', constants % nbasis, constants % nbasis0, one, &
1031 & constants % pchi(1,1,jsph), constants % nbasis, &
1032 & scratch0(1,jsph), 1, zero, scratch(1,jsph), 1)
1035 do isph = 1, params % nsph
1036 do l = 0, params % lmax
1038 ind = l**2 + l + m + 1
1039 y(ind,isph,1) = - (epsilon_ratio*l*scratch(ind,isph)) &
1040 & /params % rsph(isph)
1041 y(ind,isph,2) = constants % termimat(l,isph)*scratch(ind,isph)
1049subroutine cx(params, constants, workspace, x, y, ddx_error)
1051 type(ddx_params_type),
intent(in) :: params
1052 type(ddx_constants_type),
intent(in) :: constants
1053 type(ddx_workspace_type),
intent(inout) :: workspace
1054 real(dp),
dimension(constants % nbasis, params % nsph, 2),
intent(in) :: x
1055 real(dp),
dimension(constants % nbasis, params % nsph, 2),
intent(out) :: y
1056 type(ddx_error_type),
intent(inout) :: ddx_error
1058 integer :: isph, jsph, igrid, ind, l, m, ind0
1059 real(dp),
dimension(3) :: vij, vtij
1061 complex(dp) :: work_complex(constants % lmax0 + 1)
1062 real(dp) :: work(constants % lmax0 + 1)
1063 integer :: indl, inode, info
1065 real(dp),
allocatable :: diff_re(:,:), diff0(:,:)
1067 allocate(diff_re(constants % nbasis, params % nsph), &
1068 & diff0(constants % nbasis0, params % nsph), stat=info)
1070 call update_error(ddx_error,
"Allocation failed in cx")
1078 do jsph = 1, params % nsph
1079 do l = 0, params % lmax
1081 ind = l**2 + l + m + 1
1082 diff_re(ind,jsph) = (params % epsp/params % eps)* &
1083 & (l/params % rsph(jsph))*x(ind,jsph,1) &
1084 & - constants % termimat(l,jsph)*x(ind,jsph,2)
1092 do jsph = 1, params % nsph
1093 call dgemv(
't', constants % nbasis, constants % nbasis0, one, &
1094 & constants % pchi(1,1,jsph), constants % nbasis, &
1095 & diff_re(1,jsph), 1, zero, diff0(1,jsph), 1)
1099 do isph = 1, params % nsph
1100 do l = 0, constants % lmax0
1102 diff0(ind0-l:ind0+l, isph) = diff0(ind0-l:ind0+l, isph) * &
1103 & constants % C_ik(l, isph)
1108 if (params % fmm .eq. 0)
then
1112 do isph = 1, params % nsph
1113 do igrid = 1, params % ngrid
1114 if (constants % ui(igrid,isph).gt.zero)
then
1118 do jsph = 1, params % nsph
1119 vij = params % csph(:,isph) + &
1120 & params % rsph(isph)*constants % cgrid(:,igrid) - &
1121 & params % csph(:,jsph)
1122 vtij = vij * params % kappa
1123 call fmm_m2p_bessel_work(vtij, constants % lmax0, &
1124 & constants % vscales, constants % SK_ri(:, jsph), &
1125 & one, diff0(:, jsph), one, val, work_complex, work)
1127 do ind = 1, constants % nbasis
1128 y(ind,isph,1) = y(ind,isph,1) + val*&
1129 & constants % ui(igrid,isph)*&
1130 & constants % vwgrid(ind,igrid)
1137 workspace % tmp_node_m = zero
1138 workspace % tmp_node_l = zero
1139 workspace % tmp_sph = zero
1140 do isph = 1, params % nsph
1141 do l = 0, constants % lmax0
1143 workspace % tmp_sph(ind0-l:ind0+l, isph) = &
1144 & diff0(ind0-l:ind0+l, isph)
1147 if(constants % lmax0 .lt. params % pm)
then
1148 do isph = 1, params % nsph
1149 inode = constants % snode(isph)
1150 workspace % tmp_node_m(1:constants % nbasis0, inode) = &
1151 & workspace % tmp_sph(1:constants % nbasis0, isph)
1152 workspace % tmp_node_m(constants % nbasis0+1:, inode) = zero
1155 indl = (params % pm+1)**2
1156 do isph = 1, params % nsph
1157 inode = constants % snode(isph)
1158 workspace % tmp_node_m(:, inode) = workspace % tmp_sph(1:indl, isph)
1162 call tree_m2m_bessel_rotation(params, constants, workspace % tmp_node_m)
1163 call tree_m2l_bessel_rotation(params, constants, workspace % tmp_node_m, &
1164 & workspace % tmp_node_l)
1165 call tree_l2l_bessel_rotation(params, constants, workspace % tmp_node_l)
1166 workspace % tmp_grid = zero
1167 call tree_l2p_bessel(params, constants, one, workspace % tmp_node_l, zero, &
1168 & workspace % tmp_grid)
1169 call tree_m2p_bessel(params, constants, constants % lmax0, one, &
1170 & params % lmax, workspace % tmp_sph, one, &
1171 & workspace % tmp_grid)
1173 do isph = 1, params % nsph
1174 do igrid = 1, params % ngrid
1175 do ind = 1, constants % nbasis
1176 y(ind,isph,1) = y(ind,isph,1) + workspace % tmp_grid(igrid, isph)*&
1177 & constants % vwgrid(ind, igrid)*&
1178 & constants % ui(igrid,isph)
1186 deallocate(diff_re, diff0, stat=info)
1188 call update_error(ddx_error,
"Deallocation failed in cx")
Core routines and parameters specific to gradients.
Core routines and parameters specific to ddLPB.
Operators shared among ddX methods.
subroutine repsx(params, constants, workspace, x, y, ddx_error)
Apply operator to spherical harmonics.
subroutine prec_repsstarx(params, constants, workspace, x, y, ddx_error)
Apply preconditioner for ddPCM adjoint linear system.
subroutine prec_repsx(params, constants, workspace, x, y, ddx_error)
Apply preconditioner for ddPCM primal linear system.
subroutine bx_prec(params, constants, workspace, x, y, ddx_error)
Apply the preconditioner to the primal HSP linear system.
subroutine lx(params, constants, workspace, x, y, ddx_error)
Single layer operator matvec.
subroutine dstarx_dense(params, constants, workspace, do_diag, x, y, ddx_error)
Baseline implementation of adjoint double layer operator.
subroutine dx(params, constants, workspace, x, y, ddx_error)
Double layer operator matvec without diagonal blocks.
subroutine dstarx_fmm(params, constants, workspace, do_diag, x, y, ddx_error)
FMM-accelerated implementation of adjoint double layer operator.
subroutine bstarx(params, constants, workspace, x, y, ddx_error)
Adjoint HSP matrix vector product.
subroutine prec_tx(params, constants, workspace, x, y, ddx_error)
Apply the preconditioner to the primal ddLPB linear system |Yr| = |A^-1 0 |*|Xr| |Ye| |0 B^-1 | |Xe|.
subroutine rinfx(params, constants, workspace, x, y, ddx_error)
Apply operator to spherical harmonics.
subroutine bx(params, constants, workspace, x, y, ddx_error)
Primal HSP matrix vector product.
subroutine cstarx(params, constants, workspace, x, y, ddx_error)
ddLPB adjoint matrix-vector product
subroutine dx_fmm(params, constants, workspace, do_diag, x, y, ddx_error)
FMM-accelerated implementation of double layer operator.
subroutine cx(params, constants, workspace, x, y, ddx_error)
ddLPB matrix-vector product
subroutine dx_dense(params, constants, workspace, do_diag, x, y, ddx_error)
Baseline implementation of double layer operator.
subroutine tstarx(params, constants, workspace, x, y, ddx_error)
Adjoint ddLPB matrix-vector product.
subroutine ldm1x(params, constants, workspace, x, y, ddx_error)
Diagonal preconditioning for Lx operator.
subroutine repsstarx(params, constants, workspace, x, y, ddx_error)
Apply operator to spherical harmonics.
subroutine dstarx(params, constants, workspace, x, y, ddx_error)
Adjoint double layer operator matvec.
subroutine lstarx(params, constants, workspace, x, y, ddx_error)
Adjoint single layer operator matvec.
subroutine rstarinfx(params, constants, workspace, x, y, ddx_error)
Apply operator to spherical harmonics.
subroutine prec_tstarx(params, constants, workspace, x, y, ddx_error)
Apply the preconditioner to the ddLPB adjoint linear system.
Core routines and parameters of ddX software.
subroutine jacobi_diis(params, constants, workspace, tol, rhs, x, niter, x_rel_diff, matvec, dm1vec, norm_func, ddx_error)
Jacobi iterative solver.