31 use,
intrinsic :: iso_c_binding, only: c_double, c_int, c_f_pointer
32 use,
intrinsic :: iso_fortran_env, only: input_unit, int32, int64, real64, output_unit, iostat_end
35 use blas_lapack_gbl,
only: blasint
37 use file_mapping_gbl,
only: file_mapping
39 use phys_const_gbl,
only: pi, imu, to_ev
40 use precisn_gbl,
only: wp, wp_bytes
45 integer(blasint),
external :: numroc
59 integer :: mgvn, stot, nescat, nchan, nopen, ndopen, nchsq, lukmt, nkset, maxne
60 real(wp),
allocatable :: escat(:)
76 real(wp),
allocatable :: rea(:, :, :), ima(:, :, :), evchl(:)
77 integer,
allocatable :: ichl(:), lvchl(:), mvchl(:)
78 integer :: mgvn, nesc, nchan, nstat, lusct
96 real(real64),
pointer :: mat(:, :) => null()
98 type(file_mapping) :: mapping
100 logical :: distributed = .false.
101 integer(blasint) :: desc(9) = 0
102 integer(blasint) :: row_context = 0
103 integer(blasint) :: blk_context = 0
104 integer(blasint) :: block_size = 0
130 integer(int32),
allocatable :: iidipx(:), iidipy(:), iidipz(:)
131 integer(int32),
allocatable :: ifdipx(:), ifdipy(:), ifdipz(:)
138 integer(int32) :: nelc, nz
141 real(real64) :: rmatr
142 real(real64),
allocatable :: crlv(:,:,:), eig(:,:), rg(:), etarg(:), gaunt(:, :, :), r_points(:)
143 integer(int32),
allocatable :: mgvns(:), stot(:), mnp1(:), nchan(:), l2p(:,:), m2p(:,:), ichl(:,:), lm_rg(:,:)
159 #ifdef WITH_SCALAPACK
161 use mpi_gbl,
only: mpi_xermsg
163 integer,
parameter :: mpiint = kind(mpi_comm_world)
164 integer,
parameter :: mpiofs = mpi_offset_kind
166 character(len=200) :: msg
168 integer(mpiint) :: ndims, gsizes(2), distrb(2), dargs(2), psizes(2), locsiz, fh, ierr, datype
169 integer(mpiint) :: comm_size, comm_rank, stat(MPI_STATUS_SIZE), mtwo = 2, dims(2)
170 integer(mpiofs) :: offs
174 character(len=*),
intent(in) :: filename
175 integer(int32),
intent(in) :: u, rows, cols
176 integer(int64),
intent(in) :: offset
178 integer(int64) :: length
179 integer(blasint) :: zero = 0, one = 1, nprow, npcol, lrows, lcols, min_block_size, max_block_size, ld, info, myprow, mypcol
180 integer(blasint) :: brows, bcols
182 #ifdef WITH_SCALAPACK
183 if (this % distributed)
then
184 call mpi_comm_size(mpi_comm_world, comm_size, ierr)
185 call assert_status(
'Failed to obtain world communicator size: ', int(ierr))
186 call mpi_comm_rank(mpi_comm_world, comm_rank, ierr)
187 call assert_status(
'Failed to obtain world communicator rank: ', int(ierr))
190 call mpi_dims_create(comm_size, mtwo, dims, ierr)
191 call assert_status(
'Failed to reshape world communicator to rectangular grid: ', int(ierr))
195 if (npcol * nprow /=
nprocs)
then
196 write (msg,
'(a,3(i0,a))')
'BLACS grid ', nprow,
'x', npcol,
' does not use all ',
nprocs,
' processes. Fix it.'
197 call mpi_xermsg(
'multidip_io',
'load_mapped_matrix', trim(msg), 1, 1);
200 call blacs_get(zero, zero, this % row_context)
201 call blacs_get(zero, zero, this % blk_context)
202 call blacs_gridinit(this % row_context,
'R', one, nprow * npcol)
203 call blacs_gridinit(this % blk_context,
'R', nprow, npcol)
204 call blacs_gridinfo(this % blk_context, nprow, npcol, myprow, mypcol)
209 this % block_size = min(rows / nprow, cols / npcol)
210 this % block_size = min(this % block_size, max_block_size)
211 this % block_size = max(this % block_size, min_block_size)
215 lrows = numroc(brows, this % block_size, myprow, zero, nprow)
216 lcols = numroc(bcols, this % block_size, mypcol, zero, npcol)
219 if (int(lrows, int64)*int(lcols, int64) > huge(1_int32))
then
220 print
'(a,i0,a,i0,a)',
'WARNING: Local portion of the dipole matrix has size ', lrows,
' x ', lcols,
'.'
221 print
'(9x,a)',
'This means that it cannot be indexed with 4-byte integers.'
222 print
'(9x,a,/)',
'If reading fails, try distributing the calculation more.'
225 call descinit(this % desc, brows, bcols, this % block_size, this % block_size, zero, zero, this % blk_context, ld, info)
227 allocate (this % mat(ld, lcols))
231 gsizes = [ rows, cols ]
232 distrb = [ mpi_distribute_cyclic, mpi_distribute_cyclic ]
233 dargs = [ this % block_size, this % block_size ]
234 psizes = [ nprow, npcol ]
235 locsiz = lrows * lcols
237 call mpi_file_open(mpi_comm_world, filename, mpi_mode_rdonly, mpi_info_null, fh, ierr)
238 call assert_status(
'Failed to open file for MPI-IO: ', int(ierr))
239 call mpi_type_create_darray(comm_size, comm_rank, ndims, gsizes, distrb, dargs, &
240 psizes, mpi_order_fortran, mpi_real8, datype, ierr)
241 call assert_status(
'Failed to define distributed array data type: ', int(ierr))
242 call mpi_type_commit(datype, ierr)
243 call assert_status(
'Failed to commit distributed array data type: ', int(ierr))
244 call mpi_file_set_view(fh, offs, mpi_real8, datype,
'native', mpi_info_null, ierr)
245 call assert_status(
'Failed to define file view: ', int(ierr))
246 call mpi_file_read_all(fh, this % mat, locsiz, mpi_real8, stat, ierr)
248 call mpi_type_free(datype, ierr)
249 call assert_status(
'Failed to release distributed array data type: ', int(ierr))
250 call mpi_file_close(fh, ierr)
255 length = int(rows, int64) * int(cols, int64) * wp_bytes
256 call this % mapping % init(filename, offset - 1, length)
257 call c_f_pointer(this % mapping % ptr, this % mat, [rows, cols])
259 allocate (this % mat(rows, cols))
262 #ifdef WITH_SCALAPACK
281 #ifdef WITH_SCALAPACK
282 if (this % distributed)
then
283 deallocate (this % mat)
287 if (
associated(this % mat))
then
288 deallocate (this % mat)
291 #ifdef WITH_SCALAPACK
309 use mpi_gbl,
only: mpi_xermsg
311 type(
kmatrix),
allocatable,
intent(inout) :: km(:)
312 integer,
intent(in) :: lukmt(:), nkset(:)
314 character(len=200) :: msg
319 km(i) % lukmt = lukmt(i)
320 km(i) % nkset = nkset(i)
322 call km(i) % read_kmatrix_file
324 if (km(i) % nescat /= km(1) % nescat)
then
325 write (msg,
'(a,2(i0,a))')
'ERROR: K-matrix units ', lukmt(1),
' and ', lukmt(i), &
326 ' hold different number of scattering energies!'
327 call mpi_xermsg(
'multidip_io',
'read_kmatrices', trim(msg), 1, 1)
330 if (any(km(i) % escat(1 : km(i) % nescat) /= km(1) % escat(1 : km(1) % nescat)))
then
331 write (msg,
'(a,2(i0,a))')
'ERROR: K-matrix units ', lukmt(1),
' and ', lukmt(i), &
332 ' hold different scattering energies!'
333 call mpi_xermsg(
'multidip_io',
'read_kmatrices', trim(msg), 1, 1)
352 use mpi_gbl,
only: mpi_xermsg
354 class(
kmatrix),
intent(inout) :: km
356 integer :: k, n, ifail, key, nset, nrec, ninfo, ndata, ntarg, nvib, ndis, ie, gutot, ion
357 integer :: nopen, ndopen, nchsq, a, b, c, mye, nene, ierr
359 real(wp) :: dE1, dE2, r, rmass, en
360 real(wp),
allocatable :: kmat(:)
361 character(len=80) :: title, msg
363 print
'(/,A,I0,A,I0,/)',
'Reading K-matrices from unit ', km % lukmt,
', set ', km % nkset
365 call getset(km % lukmt, km % nkset, 11,
'UNFORMATTED', ifail)
367 read (km % lukmt) key, nset, nrec, ninfo, ndata
368 read (km % lukmt) title
369 read (km % lukmt) km % mgvn, km % stot, gutot, ion, r, rmass
370 read (km % lukmt) ntarg, nvib, ndis, km % nchan, km % maxne
372 print
'(2x,A,I0)',
'mgvn = ', km % mgvn
373 print
'(2x,A,I0)',
'stot = ', km % stot
374 print
'(2x,A,I0)',
'ntarg = ', ntarg
375 print
'(2x,A,I0)',
'nvib = ', nvib
376 print
'(2x,A,I0)',
'ndis = ', ndis
377 print
'(2x,A,I0)',
'nchan = ', km % nchan
378 print
'(2x,A,I0)',
'maxne = ', km % maxne
380 print
'(/,2x,A,/)',
'Energy ranges:'
383 do ie = 1, km % maxne
384 read (km % lukmt) k, n, de1, de2
385 print
'(4x,I4,I8,F8.3,F8.3)', k, n, de1, de2
386 km % nescat = km % nescat + n
390 allocate (km % escat(km % nescat), kmat(km % nchan * (km % nchan + 1)))
394 do ie = 1, km % nescat
395 read (km % lukmt, iostat = ierr) nopen, ndopen, nchsq, en
396 if (ierr == iostat_end)
then
397 print
'(/,2x,A,I0,A,I0,A)',
'WARNING: Unit ', km % lukmt,
' contains only ', ie - 1,
' K-matrices.'
398 print
'(11x,A)',
'This means that CFASYM failed during RSOLVE for some energies.'
399 print
'(11x,A)',
'The scattering energies MUST be consistent across symmetries!'
402 else if (ierr /= 0)
then
403 write (msg,
'(2x,a,i0,a)')
'ERROR ', ierr,
' while reading K-matrix file.'
404 call mpi_xermsg(
'multidip_io',
'read_kmatrix_file', trim(msg), 1, 1)
406 km % escat(ie) = en/2
407 if (iwarn .and. nopen < km % nchan)
then
408 print
'(/,2x,A,I0,A)',
'WARNING: Unit ', km % lukmt,
' contains only open-open subset of the full K-matrix.'
409 print
'(11x,A)',
'Use IKTYPE = 1 in RSOLVE to save full K-matrices.'
410 print
'(11x,A)',
'You may get spurious below-threshold noise.'
430 class(
kmatrix),
intent(in) :: km
431 integer,
optional,
intent(in) :: skip
436 call getset(km % lukmt, km % nkset, 11,
'UNFORMATTED', i)
447 if (
present(skip))
then
465 use mpi_gbl,
only: mpi_xermsg
467 class(
kmatrix),
intent(in) :: km
468 real(wp),
allocatable,
intent(inout) :: kmat(:, :)
469 integer,
optional,
intent(in) :: skip
471 real(wp),
allocatable :: buffer(:)
472 character(len=200) :: msg
475 integer :: a, b, c, i, ierr, nopen, ndopen, nchsq
477 allocate (buffer(km % nchan * (km % nchan + 1)))
479 read (km % lukmt, iostat = ierr) nopen, ndopen, nchsq, en, buffer(1:nchsq)
481 if (ierr == iostat_end)
then
482 write (msg,
'(a,i0,a)')
'ERROR: Unit ', km % lukmt,
' ended while reading K-matrix!'
483 call mpi_xermsg(
'multidip_io',
'get_kmatrix', trim(msg), 1, 1)
484 else if (ierr /= 0)
then
485 write (msg,
'(2x,a,2(i0,a))')
'ERROR ', ierr,
' while reading K-matrix file unit ', km % lukmt,
'!'
486 call mpi_xermsg(
'multidip_io',
'get_kmatrix', trim(msg), 1, 1)
489 if (
allocated(kmat))
then
490 if (
size(kmat, 1) /= km % nchan .or.
size(kmat, 2) /= km % nchan)
then
495 if (.not.
allocated(kmat))
then
496 allocate (kmat(km % nchan, km % nchan))
503 kmat(a, b) = buffer(c)
504 kmat(b, a) = buffer(c)
508 if (
present(skip))
then
510 read (km % lukmt, iostat = ierr)
528 integer,
intent(in) :: lusct(:)
532 ak(i) % lusct = lusct(i)
533 call ak(i) % read_wfncoeffs_file
553 real(wp),
intent(out) :: bnd(:), Ei
554 integer,
intent(in) :: lubnd, mgvn0, stot0
556 real(wp),
allocatable :: xvec(:), etot(:), vtemp(:)
558 integer :: nbset, nchan, mgvn, stot, gutot, nstat, nbound, iprint, iwrite, ifail
559 character(len=11) :: bform
561 bform =
'unformatted'
566 open (lubnd, action =
'read', form = bform)
568 call readbh(lubnd, nbset, nchan, mgvn, stot, gutot, nstat, nbound, rr, bform, iprint, iwrite, ifail)
570 if (mgvn /= mgvn0 .or. stot /= stot0)
then
571 print
'(*(a,i0))',
'ERROR: Bound coefficients at unit ', lubnd,
' are for MGVN = ', mgvn,
', STOT = ', stot, &
572 ', but I am looking for MGVN = ', mgvn0,
', STOT = ', stot0
577 allocate (xvec(nbound*nchan), vtemp(nbound), etot(nbound))
579 call readbc(nstat, etot, vtemp, bnd, nbound, nchan, xvec)
596 real(wp),
allocatable :: ReA(:), ImA(:)
598 integer :: i, j, keysc, nset, nrec, ninfo, ndata, stot, gutot, nscat, ich, ie, mye, nene
599 character(len=80) :: header
601 print
'(/,A,I0,/)',
'Reading wave function coefficients from unit ', ak % lusct
603 open (ak % lusct, status =
'old', action =
'read', form =
'unformatted')
605 read (ak % lusct) keysc, nset, nrec, ninfo, ndata
606 read (ak % lusct) header
607 read (ak % lusct) nscat, ak % mgvn, stot, gutot, ak % nstat, ak % nchan, ak % nesc
609 print
'(2x,A,I0)',
'mgvn = ', ak % mgvn
610 print
'(2x,A,I0)',
'stot = ', stot
611 print
'(2x,A,I0)',
'nstat = ', ak % nstat
612 print
'(2x,A,I0)',
'nchan = ', ak % nchan
613 print
'(2x,A,I0)',
'nesc = ', ak % nesc
617 if (
allocated(ak % ichl))
deallocate (ak % ichl)
618 if (
allocated(ak % lvchl))
deallocate (ak % lvchl)
619 if (
allocated(ak % mvchl))
deallocate (ak % mvchl)
620 if (
allocated(ak % evchl))
deallocate (ak % evchl)
622 allocate (ak % ichl(ak % nchan))
623 allocate (ak % lvchl(ak % nchan))
624 allocate (ak % mvchl(ak % nchan))
625 allocate (ak % evchl(ak % nchan))
627 read (ak % lusct) ak % ichl, ak % lvchl, ak % mvchl, ak % evchl
629 print
'(/,2x,A)',
'channel table'
631 print
'(2x,4I6,F15.7)', j, ak % ichl(j), ak % lvchl(j), ak % mvchl(j), ak % evchl(j)
650 integer,
optional,
intent(in) :: skip
655 call getset(ak % lusct, 1, 88,
'UNFORMATTED', i)
663 if (
present(skip))
then
665 do ich = 1, ak % nchan
684 use mpi_gbl,
only: mpi_xermsg
687 real(wp),
allocatable,
intent(inout) :: Re_Ak(:, :), Im_Ak(:, :)
688 integer,
optional,
intent(in) :: skip
689 real(wp),
intent(inout) :: E
691 character(len=250) :: msg, iomsg
693 integer :: i, ich, ierr
695 do ich = 1, ak % nchan
696 read (ak % lusct, iostat = ierr, iomsg = iomsg) e, i, re_ak(:, ich)
697 read (ak % lusct, iostat = ierr, iomsg = iomsg) e, i, im_ak(:, ich)
698 if (ierr == iostat_end)
then
699 write (msg,
'(2x,a,i0,a)')
'ERROR: Unit ', ak % lusct,
' ended while reading Ak-coeffs!'
700 call mpi_xermsg(
'multidip_io',
'get_wfncoeffs', trim(msg), 1, 1)
701 else if (ierr /= 0)
then
702 write (msg,
'(2x,a,2(i0,a),a)')
'ERROR ', ierr,
' while reading Ak-coeffs file unit ', ak % lusct,
': ', iomsg
703 call mpi_xermsg(
'multidip_io',
'get_wfncoeffs', trim(msg), 1, 1)
707 if (
present(skip))
then
709 do ich = 1, ak % nchan
710 read (ak % lusct, iostat = ierr)
711 read (ak % lusct, iostat = ierr)
731 character(*),
intent(in) :: filename
732 logical,
intent(in) :: mpiio, read_wmat2
734 integer(int32),
allocatable :: ltarg(:), starg(:), nconat(:)
735 real(real64),
allocatable :: r_points(:), cf(:, :, :)
737 integer(int32) :: i, j, u, s, s1, s2, ntarg, nrg, lrang2, lamax, inast, nchmx, nstmx, lmaxp1, nfdm
738 integer(int32) :: lrgl, nspn, npty
739 integer(int64) :: offset, length
740 real(real64) :: bbloch, delta_r
742 open (newunit = u, file = filename, access =
'stream', status =
'old', action =
'read')
744 print
'(/,3A,/)',
'Reading file "', filename,
'"'
747 length = int(s1, int64) * int(s2, int64) * wp_bytes
748 allocate (moldat % iidipy(s), moldat % ifdipy(s), moldat % dipy(s))
749 read (u) moldat % iidipy, moldat % ifdipy
750 inquire (u, pos = offset)
752 moldat % dipy(i) % distributed = mpiio
753 call moldat % dipy(i) % load(filename, u, offset, s1, s2)
754 offset = offset + length
756 print
'(2x,A,*(1x,I0))',
'[m = -1] iidip =', moldat % iidipy
757 print
'(2x,A,*(1x,I0))',
' ifdip =', moldat % ifdipy
761 if (sum(abs(moldat % dipy(i) % mat)) == 0)
then
762 print
'(/,2x,A,/)',
'WARNING: Norm of some Y dipoles is zero. Something went wrong in CDENPROP?'
767 read (u, pos = offset) s, s1, s2
768 length = int(s1, int64) * int(s2, int64) * wp_bytes
769 allocate (moldat % iidipz(s), moldat % ifdipz(s), moldat % dipz(s))
770 read (u) moldat % iidipz, moldat % ifdipz
771 inquire (u, pos = offset)
773 moldat % dipz(i) % distributed = mpiio
774 call moldat % dipz(i) % load(filename, u, offset, s1, s2)
775 offset = offset + length
777 print
'(2x,A,*(1x,I0))',
'[m = 0] iidip =', moldat % iidipz
778 print
'(2x,A,*(1x,I0))',
' ifdip =', moldat % ifdipz
782 if (sum(abs(moldat % dipz(i) % mat)) == 0)
then
783 print
'(/,2x,A,/)',
'WARNING: Norm of some Z dipoles is zero. Something went wrong in CDENPROP?'
788 read (u, pos = offset) s, s1, s2
789 length = int(s1, int64) * int(s2, int64) * wp_bytes
790 allocate (moldat % iidipx(s), moldat % ifdipx(s), moldat % dipx(s))
791 read (u) moldat % iidipx, moldat % ifdipx
792 inquire (u, pos = offset)
794 moldat % dipx(i) % distributed = mpiio
795 call moldat % dipx(i) % load(filename, u, offset, s1, s2)
796 offset = offset + length
798 print
'(2x,A,*(1x,I0))',
'[m = +1] iidip =', moldat % iidipx
799 print
'(2x,A,*(1x,I0))',
' ifdip =', moldat % ifdipx
803 if (sum(abs(moldat % dipx(i) % mat)) == 0)
then
804 print
'(/,2x,A,/)',
'WARNING: Norm of some X dipoles is zero. Something went wrong in CDENPROP?'
809 read (u, pos = offset) ntarg
810 print
'(/,2x,A,I0)',
'ntarg = ', ntarg
811 allocate (moldat % crlv(ntarg, ntarg, 3))
812 read (u) moldat % crlv
815 allocate (moldat % rg(nrg), moldat % lm_rg(6, nrg))
816 read (u) moldat % rg, moldat % lm_rg
818 read (u) moldat % nelc, moldat % nz, lrang2, lamax, ntarg, inast, nchmx, nstmx, lmaxp1
819 read (u) moldat % rmatr, bbloch
820 allocate (moldat % etarg(ntarg), ltarg(ntarg), starg(ntarg))
821 read (u) moldat % etarg, ltarg, starg
822 read (u) nfdm, delta_r
823 allocate (moldat % r_points(nfdm + 1))
824 read (u) moldat % r_points
825 print
'(2x,A,*(1x,F8.3))',
'sampling radii:', moldat % r_points
827 print
'(/,2x,A)',
'number of inner eigenstates per symmetry'
829 allocate (nconat(ntarg), moldat % l2p(nchmx, inast), moldat % m2p(nchmx, inast), moldat % eig(nstmx, inast), &
830 moldat % wamp(inast), cf(nchmx, nchmx, lamax), moldat % ichl(nchmx, inast), &
831 moldat % mgvns(inast), moldat % stot(inast), moldat % nchan(inast), moldat % mnp1(inast), &
832 moldat % wmat2(nfdm, inast))
834 inquire (u, pos = offset)
836 length = int(nchmx, int64) * int(nstmx, int64) * wp_bytes
840 read (u, pos = offset) lrgl, nspn, npty, moldat % nchan(i), moldat % mnp1(i)
841 moldat % mgvns(i) = lrgl - 1
842 moldat % stot(i) = nspn
843 print
'(4x,I3,I8)', moldat % mgvns(i), moldat % mnp1(i)
844 read (u) nconat, moldat % l2p(:, i), moldat % m2p(:, i)
845 read (u) moldat % eig(:, i)
846 inquire (u, pos = offset)
847 call moldat % wamp(i) % load(filename, u, offset, nchmx, nstmx)
848 offset = offset + length
849 read (u, pos = offset) cf, moldat % ichl(:, i)
851 inquire (u, pos = offset)
856 call moldat % wmat2(j, i) % load(filename, u, offset, s1, s2)
857 offset = offset + int(s1, int64) * int(s2, int64) * wp_bytes
860 offset = offset + int(s1, int64) * int(s2, int64) * nfdm * wp_bytes
866 print
'(/,2x,A,I0,A,I0,A)',
'channels in symmetry #', i,
' (IRR ', moldat % mgvns(i),
'):'
867 do j = 1, moldat % nchan(i)
868 print
'(2x,I4,A,I6,I3,SP,I6)', j,
':', moldat % ichl(j, i), moldat % l2p(j, i), moldat % m2p(j, i)
869 if (moldat % ichl(j, i) > ntarg)
then
870 print
'(4(A,I0),A)',
'Warning: Channel ', j,
' in symmetry ', moldat % mgvns(i),
' is coupled to state ', &
871 moldat % ichl(j, i),
', which is beyond the number of targets ', ntarg,
' (bug in mpi-scatci!)'
872 moldat % ichl(j, i) = ntarg
892 use mpi_gbl,
only: mpi_xermsg
896 integer :: maxl, i, l1, m1, l2, m2, l3, m3
898 maxl = max(0_int32, maxval(moldat % lm_rg))
900 allocate (moldat % gaunt((maxl + 1)**2, (maxl + 1)**2, -1:1))
904 do i = 1,
size(moldat % rg)
905 l1 = moldat % lm_rg(1, i); m1 = moldat % lm_rg(2, i)
906 l2 = moldat % lm_rg(3, i); m2 = moldat % lm_rg(4, i)
907 l3 = moldat % lm_rg(5, i); m3 = moldat % lm_rg(6, i)
908 if (l3 /= 1 .or. abs(m3) > 1)
then
909 call mpi_xermsg(
'multidip_io',
'setup_angular_integrals', &
910 'Unexpected layout of the angular integral storage in molecular_data', 1, 1)
912 moldat % gaunt(l1*(l1+1) + m1 + 1, l2*(l2+1) + m2 + 1, m3) = moldat % rg(i)
929 integer,
intent(in) :: I
930 integer,
allocatable,
intent(inout) :: iidip(:), ifdip(:)
932 if (
allocated(iidip))
deallocate (iidip)
933 if (
allocated(ifdip))
deallocate (ifdip)
937 iidip = moldat % iidipx
938 ifdip = moldat % ifdipx
940 iidip = moldat % iidipy
941 ifdip = moldat % ifdipy
943 iidip = moldat % iidipz
944 ifdip = moldat % ifdipz
989 integer(blasint),
parameter :: one = 1, zero = 0
992 integer,
intent(in) :: component, irrpair, nf, nn
993 character(len=1),
intent(in) :: transp
994 real(wp),
intent(inout) :: X(:, :, :), Y(:, :, :)
996 integer(blasint) :: lda, ldb, ldc, m, n, k, info, Xdesc(9), Xdesc2D(9), Ydesc(9), Ydesc2D(9), desc(9), gn
997 integer(blasint) :: Xlocr, Xlocc, Ylocr, Ylocc, ldX, ldY, rctx, bctx, rbksz, cbksz, myprow, mypcol, nprow, npcol
1000 real(wp),
allocatable :: Xloc(:, :), Yloc(:, :)
1001 real(wp),
pointer :: dips(:, :)
1007 n =
size(x, 2) *
size(x, 3)
1011 select case (component)
1013 dist = moldat % dipx(irrpair) % distributed
1014 desc = moldat % dipx(irrpair) % desc
1015 rctx = moldat % dipx(irrpair) % row_context
1016 bctx = moldat % dipx(irrpair) % blk_context
1017 lda =
size(moldat % dipx(irrpair) % mat, 1)
1018 dips => moldat % dipx(irrpair) % mat(:, :)
1020 dist = moldat % dipy(irrpair) % distributed
1021 desc = moldat % dipy(irrpair) % desc
1022 rctx = moldat % dipy(irrpair) % row_context
1023 bctx = moldat % dipy(irrpair) % blk_context
1024 lda =
size(moldat % dipy(irrpair) % mat, 1)
1025 dips => moldat % dipy(irrpair) % mat(:, :)
1027 dist = moldat % dipz(irrpair) % distributed
1028 desc = moldat % dipz(irrpair) % desc
1029 rctx = moldat % dipz(irrpair) % row_context
1030 bctx = moldat % dipz(irrpair) % blk_context
1031 lda =
size(moldat % dipz(irrpair) % mat, 1)
1032 dips => moldat % dipz(irrpair) % mat(:, :)
1035 #ifdef WITH_SCALAPACK
1041 call blacs_gridinfo(bctx, nprow, npcol, myprow, mypcol)
1044 call descinit(xdesc, k, gn, ldb, n, zero, zero, rctx, ldb, info)
1045 call assert_status(
'Failed to set up X BLACS descriptor: ', int(info))
1046 call descinit(ydesc, m, gn, ldc, n, zero, zero, rctx, ldc, info)
1047 call assert_status(
'Failed to set up Y BLACS descriptor: ', int(info))
1050 rbksz =
clip(min(nf, nn) / int(nprow), 1, 64)
1051 cbksz =
clip(int(gn / npcol), 1, 64)
1054 xlocr = numroc(k, rbksz, myprow, zero, nprow); ldx = max(one, xlocr)
1055 xlocc = numroc(gn, cbksz, mypcol, zero, npcol)
1058 ylocr = numroc(m, rbksz, myprow, zero, nprow); ldy = max(one, ylocr)
1059 ylocc = numroc(gn, cbksz, mypcol, zero, npcol)
1062 allocate (xloc(ldx, xlocc), yloc(ldy, ylocc))
1065 call descinit(xdesc2d, k, gn, rbksz, cbksz, zero, zero, bctx, ldx, info)
1066 call assert_status(
'Failed to set up X2D BLACS descriptor: ', int(info))
1067 call descinit(ydesc2d, m, gn, rbksz, cbksz, zero, zero, bctx, ldy, info)
1068 call assert_status(
'Failed to set up Y2D BLACS descriptor: ', int(info))
1071 call pdgemr2d(k, gn, x, one, one, xdesc, xloc, one, one, xdesc2d, bctx)
1072 call pdgemm(transp,
'N', m, gn, k,
rone, dips, one, one, desc, xloc, one, one, xdesc2d,
rzero, yloc, one, one, ydesc2d)
1073 call pdgemr2d(m, gn, yloc, one, one, ydesc2d, y, one, one, ydesc, bctx)
1076 call blas_dgemm(transp,
'N', m, n, k,
rone, dips, lda, x, ldb,
rzero, y, ldc)
1077 #ifdef WITH_SCALAPACK
1092 use mpi_gbl,
only: mpi_xermsg
1094 character(len=*),
intent(in) :: message
1095 integer,
intent(in) :: errcode
1097 if (errcode /= 0)
then
1098 call mpi_xermsg(
'multidip_io',
'assert_status', trim(message), errcode, 1)
1108 integer function clip (x, a, b)
result (y)
1112 y = max(a, min(x, b))
1131 integer,
intent(in) :: irr
1132 character(len=1),
intent(in) :: transp
1133 real(wp),
intent(inout) :: X(:,:), Y(:,:)
1135 integer(blasint) :: m, n, k, lda, ldb, ldc
1136 real(wp) :: alpha = 1, beta = 0
1137 real(wp),
pointer :: wamp(:, :)
1139 if (transp ==
'T')
then
1140 m = moldat % mnp1(irr)
1142 k = moldat % nchan(irr)
1144 m = moldat % nchan(irr)
1146 k = moldat % mnp1(irr)
1149 lda =
size(moldat % wamp(irr) % mat, 1)
1153 if (lda < merge(m, k, transp ==
'N') .or. ldb < k .or. ldc < m)
then
1154 print
'(a)',
'ERROR: Incompatible matrix dimensions in apply_boundary_amplitudes'
1155 print
'(7x,a,6(", ",a,1x,i0))', transp,
'm =', m,
'n =', n,
'k =', k,
'lda =', lda,
'ldb =', ldb,
'ldc =', ldc
1159 wamp => moldat % wamp(irr) % mat(:, :)
1161 call blas_dgemm(transp,
'N', m, n, k, alpha, wamp, lda, x, ldb, beta, y, ldc)
1176 integer,
intent(in) :: irr
1177 real(wp),
allocatable,
intent(in) :: v(:)
1178 real(wp),
allocatable,
intent(inout) :: vw(:, :)
1180 integer :: k, nstat, p, nchan
1182 nstat = moldat % mnp1(irr)
1183 nchan = moldat % nchan(irr)
1189 vw(k, p) = v(k) * moldat % wamp(irr) % mat(p, k)
1206 real(wp),
intent(in) :: escat(:)
1210 open (newunit = u, file =
'pe_energies.txt', action =
'write', form =
'formatted')
1211 write (u,
'(E25.15)') escat
1225 use mpi_gbl,
only: mpi_reduce_inplace_sum_wp
1228 character(len=*),
intent(in) :: suffix
1229 integer,
intent(in) :: nesc
1230 complex(wp),
allocatable,
intent(in) :: M(:, :, :)
1232 complex(wp),
allocatable :: val(:)
1233 real(wp),
allocatable :: reval(:), imval(:)
1235 integer :: ie, irr, mgvn, u, ichan, ichlf, lf, mf, mye
1236 character(len=100) :: filename
1238 allocate (val(nesc))
1241 do irr = 1,
size(moldat % mgvns)
1242 mgvn = moldat % mgvns(irr)
1243 do ichan = 1,
size(m, 1)
1248 val(ie) = m(ichan, mye, mgvn)
1254 call mpi_reduce_inplace_sum_wp(reval, nesc)
1255 call mpi_reduce_inplace_sum_wp(imval, nesc)
1256 val = cmplx(reval, imval, wp)
1259 if (
myproc == 1 .and. any(val /= 0))
then
1260 ichlf = moldat % ichl(ichan, irr)
1261 lf = moldat % l2p(ichan, irr)
1262 mf = moldat % m2p(ichan, irr)
1263 write (filename,
'(3(A,I0),A,SP,I0,3A)')
'pwdip-', mgvn,
'-(', ichlf,
',', lf,
',', mf,
')', suffix,
'.txt'
1264 open (newunit = u, file = filename, action =
'write', form =
'formatted')
1265 write (u,
'(2E25.15)') val
1282 use mpi_gbl,
only: mpi_reduce_inplace_sum_wp
1284 character(len=*),
intent(in) :: stem
1285 integer,
allocatable,
intent(in) :: chains(:, :)
1286 complex(wp),
allocatable,
intent(in) :: M(:, :, :, :)
1287 integer,
intent(in) :: nesc
1289 character(len=100) :: filename, history
1290 character(len=1),
parameter :: xyz(-1:1) = [
'y',
'z',
'x' ]
1291 character(len=1),
parameter :: sph(-1:1) = [
'm',
'0',
'p' ]
1293 complex(wp),
allocatable :: val(:)
1294 real(wp),
allocatable :: reval(:), imval(:)
1296 integer :: u, itarg, ntarg, ichain, nchain, ipw, npw, icomp, lf, mf, ie, mye
1302 allocate (val(nesc))
1306 do ichain = 1, nchain
1313 val(ie) = m(mye, ipw, ichain, itarg)
1319 call mpi_reduce_inplace_sum_wp(reval, nesc)
1320 call mpi_reduce_inplace_sum_wp(imval, nesc)
1321 val = cmplx(reval, imval, wp)
1324 if (
myproc == 1 .and. any(val /= 0))
then
1325 lf = int(sqrt(real(ipw - 1, wp)))
1326 mf = ipw - lf*lf - lf - 1
1328 do icomp = 1,
size(chains, 1)
1329 select case (trim(stem))
1330 case (
'xyz'); history = xyz(chains(icomp, ichain)) // trim(history)
1331 case (
'sph'); history = sph(chains(icomp, ichain)) // trim(history)
1334 write (filename,
'(3A,I0,A,I0,A,SP,I0,A)')
'rawdip-', trim(history),
'-(', itarg,
',', lf,
',', mf,
').txt'
1335 open (newunit = u, file = filename, action =
'write', form =
'formatted')
1336 write (u,
'(2E25.15)') val
1355 use mpi_gbl,
only: mpi_reduce_inplace_sum_wp
1357 character(len=*),
intent(in) :: filename
1358 real(wp),
intent(in) :: cs(:, :)
1359 integer,
intent(in) :: nesc, erange(2)
1361 real(wp),
allocatable :: csg(:, :), buffer(:)
1363 integer :: u, ie, mye, nene, ntgt
1369 allocate (csg(ntgt, nesc))
1374 csg(:, ie) = cs(:, mye)
1378 buffer = reshape(csg, [
size(csg)])
1379 call mpi_reduce_inplace_sum_wp(buffer,
size(buffer))
1380 csg = reshape(buffer, shape(csg))
1383 if (
myproc == 1 .and. any(csg(2:, :) /= 0))
then
1384 open (newunit = u, file = filename, action =
'write', form =
'formatted')
1385 do ie = max(1, erange(1)), min(nesc, erange(2))
1386 write (u,
'(*(E25.15))') csg(:, ie)
I/O routines used by MULTIDIP.
subroutine get_kmatrix(km, kmat, skip)
Read single K-matrix from the K-matrix file.
subroutine read_bndcoeffs(bnd, Ei, lubnd, mgvn0, stot0)
Read inner bound wave function coefficients.
subroutine assert_status(message, errcode)
Check for error code.
subroutine write_raw_dipoles(M, chains, nesc, stem)
Write raw transition dipole moments.
subroutine read_wfncoeffs(ak, lusct)
Read wave function coefficients from files.
subroutine load_mapped_matrix(this, filename, u, offset, rows, cols)
Read or map a matrix from file.
subroutine write_partial_wave_moments(moldat, M, nesc, suffix)
Write partial wave moments.
subroutine get_wfncoeffs(ak, E, Re_Ak, Im_Ak, skip)
Read single Ak-matrix from the Ak-coeffs file.
subroutine reset_wfncoeffs_position(ak, skip)
Reset I/O pointer to start of Ak-coeffs.
subroutine read_kmatrix_file(km)
Read K-matrix file.
subroutine read_wfncoeffs_file(ak)
Read wave function coefficients for a single symmetry from a file.
subroutine destruct_mapped_matrix(this)
Finalize a (potentially mapped) matrix object.
subroutine scale_boundary_amplitudes(moldat, irr, v, vw)
Scale boundary amplitudes matrix by a diagonal matrix.
subroutine setup_angular_integrals(moldat)
Store the angular integrals in a more convenient shape.
subroutine get_diptrans(moldat, I, iidip, ifdip)
Return dipole transition descriptors.
subroutine write_cross_section(cs, nesc, erange, filename)
Write cross sections to a file.
integer function clip(x, a, b)
Clamp value in range.
subroutine apply_dipole_matrix(moldat, component, irrpair, transp, nf, nn, X, Y)
Multiply by dipole matrix.
subroutine reset_kmatrix_position(km, skip)
Reset I/O pointer to start of K-matrices.
subroutine apply_boundary_amplitudes(moldat, irr, transp, X, Y)
Multiply by boundary amplitudes.
subroutine read_molecular_data(moldat, filename, mpiio, read_wmat2)
Read RMT molecular_data file.
subroutine read_kmatrices(km, lukmt, nkset)
Read K-matrix files.
subroutine write_energy_grid(escat)
Write photoelectron energies to file.
Hard-coded parameters of MULTIDIP.
logical check_dipoles
Check that all dipole matrices in molecular_data are nonzero.
real(wp), parameter rzero
Special functions and objects used by MULTIDIP.
Auxiliary data structure for matrix (potentially memory-mapped, or distributed)
Photoionization wave function coefficients.