!-----------------------------------------------------------------------------------------! ! Copyright (c) 2018 Peter Grünberg Institut, Forschungszentrum Jülich, Germany ! ! This file is part of Jülich KKR code and available as free software under the conditions! ! of the MIT license as expressed in the LICENSE.md file in more detail. ! !-----------------------------------------------------------------------------------------! !------------------------------------------------------------------------------------ !> Summary: Wrapper module for the calculation of the T-matrix for the JM-KKR package !> Author: Philipp Rüssmann, Bernd Zimmermann, Phivos Mavropoulos, R. Zeller, !> and many others ... !> The code uses the information obtained in the main0 module, this is !> mostly done via the `get_params_1a()` call, that obtains parameters of the type !> `t_params` and passes them to local variables !------------------------------------------------------------------------------------ module mod_main1a private public :: main1a contains ! ---------------------------------------------------------------------------- !> Summary: Main subroutine regarding the calculation of the t-matrix !> Author: Philipp Rüssmann, Bernd Zimmermann, Phivos Mavropoulos, R. Zeller, !> and many others ... !> Category: single-site, potential, KKRhost !> Deprecated: False !> Main subroutine for the calculation of the t-matrix !> !> Calls routines that compute singe-site wavefunctions and t-matrices. !> Two modes are impleneted for old (Born-iteration) solver without SOC or !> non-collinear magnetism and new solver (Chebychev mesh) working with larger !> spin-coupled matrices for SOC. !> !> @note !> PR: The BdG solver will only be impleneted with the newsolver for the moment. !> @endnote ! ---------------------------------------------------------------------------- subroutine main1a() #ifdef CPP_MPI use :: mpi use :: mod_types, only: gather_tmat, gather_lly_dtmat, save_t_mpi_c_grid, get_ntot_pt_ioff_pt_2d use :: mod_mympi, only: find_dims_2d #endif #ifdef CPP_TIMING use :: mod_timing, only: timing_start, timing_stop #endif use :: mod_datatypes, only: dp use :: mod_runoptions, only: calc_exchange_couplings, disable_charge_neutrality, disable_reference_system, & impurity_operator_only, use_Chebychev_solver, use_decimation, use_rigid_Efermi, use_spherical_potential_only, & write_BdG_tests, write_green_imp use :: mod_constants, only: czero use :: mod_profiling, only: memocc use :: mod_tmatnewsolver, only: tmat_newsolver use :: mod_tbref, only: tbref use :: mod_getscratch, only: opendafile use :: mod_interpolate_poten, only: interpolate_poten use :: mod_initldau, only: initldau use :: mod_calctmat, only: calctmat use :: mod_types, only: t_tgmat, t_inc, t_lloyd, t_dtmatjij, init_t_dtmatjij, init_t_dtmatjij_at, t_mpi_c_grid use :: mod_mympi, only: nranks, master, myrank, distribute_work_atoms, distribute_work_energies, mpiatom use :: mod_wunfiles, only: get_params_1a, t_params !, read_angles use :: mod_jijhelp, only: set_jijcalc_flags ! array dimensions use :: global_variables, only: natypd, wlength, lmmaxd, nrmaxd, lmpotd, nspotd, irmd, naclsd, nclsd, nrefd, ncleb, nembd, & naezd, lm2d, krel, nspind, iemxd, ntotd, nrmaxd, irmind, lmpotd, nspotd, npotd, natomimpd, ipand, knosph, lpotd, irnsd, korbit #ifdef CPP_BdG use :: global_variables, only: mmaxd #endif ! stuff defined in main0 already use :: mod_main0, only: ielast, nspin, icst, ipan, ircut, lmax, ncls, nineq, idoldau, lly, atom, cls, icleb, loflm, nacls, & refpot, irws, iend, ez, vins, irmin, alat, drdi, rmesh, zat, rcls, visp, rmtref, vref, cleb, cscl, socscale, socscl, erefldau, & ueff, jeff, solver, deltae, tolrdif, npan_log_at, npan_eq_at, ncheb, npan_tot, ipan_intervall, rpan_intervall, rnew, r_log, & ntldau, jwsrel, zrel, itscf, natomimp, atomimp, iqat, naez, natyp, nref, nsra, ins, itldau, lopt, vtrel, btrel, drdirel, & r2drdirel, rmrel, itrunldau, wldau, uldau, phildau implicit none ! .. Local variables integer :: i1 integer :: ipot integer :: iltmp integer :: ispin integer :: itmpdir character (len=80) :: tmpdir logical :: lrefsys integer :: lrectmt integer :: lrectra ! .. Local arrays real (kind=dp), dimension (natypd) :: phi real (kind=dp), dimension (natypd) :: theta real (kind=dp), dimension (:, :, :), allocatable :: vinsnew #ifdef CPP_MPI integer :: ntot1, mytot, ii integer, dimension (0:nranks-1) :: ntot_pt, ioff_pt, ntot_all, ioff_all ! communication of dtmat in case of lloyd integer :: iwork complex (kind=dp), dimension (:, :, :, :), allocatable :: work_jij #endif integer :: i1_start, i1_end, ierr, i_stat, i_all ! .. ! data TOLRDIF /1.5D0/ ! Set free GF to zero if R<TOLRDIF in case of virtual atoms ! data LLY /0/ lly = 0 tolrdif = 1.5d0 ! LRECTMT=WLENGTH*kind(czero)*LMMAXD*LMMAXD ! LRECTRA=WLENGTH*kind(czero) lrectmt = wlength*4*lmmaxd*lmmaxd lrectra = wlength*4 allocate (vinsnew(nrmaxd,lmpotd,nspotd), stat=i_stat) call memocc(i_stat, product(shape(vinsnew))*kind(vinsnew), 'VINSNEW', 'main1a') vinsnew = 0.0d0 ! Consistency check if ((krel<0) .or. (krel>1)) stop ' set KREL=0/1 (non/fully) relativistic mode in the inputcard' if ((krel==1) .and. (nspind==2)) stop ' set NSPIN = 1 for KREL = 1 in the inputcard' ! ------------------------------------------------------------------------- ! This routine previously used to read from unformatted files created by ! the main0 module, now instead of unformatted files take parameters from ! types defined in wunfiles.F90 ! ------------------------------------------------------------------------- call get_params_1a(t_params,ipand,natypd,irmd,naclsd,ielast,nclsd,nrefd,ncleb, & nembd,naezd,lm2d,nsra,ins,nspin,icst,ipan,ircut,lmax,ncls,nineq,idoldau,lly, & krel,atom,cls,icleb,loflm,nacls,refpot,irws,iend,ez,vins,irmin,itmpdir,iltmp, & alat,drdi,rmesh,zat,rcls,iemxd,visp,rmtref,vref,cleb,cscl,socscale,socscl, & erefldau,ueff,jeff,solver,tmpdir,deltae,tolrdif,npan_log_at,npan_eq_at,ncheb, & npan_tot,ipan_intervall,rpan_intervall,rnew,ntotd,nrmaxd,r_log,ntldau,itldau, & lopt,vtrel,btrel,drdirel,r2drdirel,rmrel,irmind,lmpotd,nspotd,npotd,jwsrel, & zrel,itscf,natomimpd,natomimp,atomimp,iqat,naez,natyp,nref) if (use_spherical_potential_only) vins(irmind:irmd, 2:lmpotd, 1:nspotd) = 0.d0 ! ------------------------------------------------------------------------- ! End read in variables ! ------------------------------------------------------------------------- ! ------------------------------------------------------------------------- ! LDA+U treatment ! ------------------------------------------------------------------------- if (idoldau==1) then open (67, file='ldau.unformatted', form='unformatted') read (67) itrunldau, wldau, uldau, phildau close (67) ! !--------------------------------------------------------------------- ! Calculate Coulomb matrix ULDAU it calculates U matrix only once. ! Remove the next IF statement to have U calculated for each iteration anew. ! !--------------------------------------------------------------------- ! IF ( ITRUNLDAU.LE.0 ) THEN call initldau(nsra, ntldau, itldau, lopt, ueff, jeff, erefldau, visp, nspin, rmesh, drdi, zat, ipan, ircut, phildau, uldau) ! END IF end if ! ------------------------------------------------------------------------- ! End of LDA+U setup ! ------------------------------------------------------------------------- ! ------------------------------------------------------------------------- ! No need to recalculate the reference system in SCF decimation case ! ------------------------------------------------------------------------- ! ITSCF is initialised to 0 in main0 lrefsys = .true. if (use_decimation .and. (itscf>0)) lrefsys = .false. if (use_rigid_Efermi .and. (itscf>0)) lrefsys = .false. if (disable_charge_neutrality .and. (itscf>0)) lrefsys = .false. if (disable_charge_neutrality .and. (itscf>0)) lrefsys = .false. if (disable_reference_system) lrefsys = .false. if (t_tgmat%tmat_to_file) then call opendafile(69, 'tmat', 4, lrectmt, tmpdir, itmpdir, iltmp) end if if (lly/=0) then if (t_lloyd%dtmat_to_file) then call opendafile(691, 'dtmatde', 7, lrectmt, tmpdir, itmpdir, iltmp) ! LLY end if if (t_lloyd%tralpha_to_file) then call opendafile(692, 'tralpha', 7, lrectra, tmpdir, itmpdir, iltmp) ! LLY end if end if ! distribute atoms over ranks call distribute_work_atoms(natyp, i1_start, i1_end) #ifdef CPP_MPI call mpi_barrier(mpi_comm_world, ierr) #endif ! skip this part with GREENIMP option if (write_green_imp .or. impurity_operator_only) then if (myrank==master) write (*, *) 'Skipping atom loop in main1a' i1_start = 1 i1_end = 0 ! distribute IE dimension here if atom loop is skipped ! otherwise this would be done in tmat_newsolver/calctmat call distribute_work_energies(ielast) end if if (.not. use_Chebychev_solver) then do i1 = i1_start, i1_end do ispin = 1, nspin ipot = nspin*(i1-1) + ispin call calctmat(icst,ins,ielast,nsra,ispin,nspin,i1,ez,drdi(1,i1), & rmesh(1,i1),vins(irmind,1,knosph*ipot+(1-knosph)),visp(1,ipot),zat(i1), & irmin(i1),ipan(i1),ircut(0,i1),cleb,loflm,icleb,iend,solver, & socscl(1,krel*i1+(1-krel)),cscl(1,krel*i1+(1-krel)),vtrel(1,i1), & btrel(1,i1),rmrel(1,i1),drdirel(1,i1),r2drdirel(1,i1),zrel(i1), & jwsrel(i1),idoldau,lopt(i1),wldau(1,1,1,i1),lly,deltae) ! LLY end do end do else ! use_Chebychev_solver ! !--------------------------------------------------------------------- ! For calculation of Jij-tensor: create array for additional t-matrices and ! set atom-dependent flags which indicate if t-matrix is needed ! !--------------------------------------------------------------------- call init_t_dtmatjij(t_inc, t_dtmatjij) if (calc_exchange_couplings) then call set_jijcalc_flags(t_dtmatjij, natyp, natomimpd, natomimp, atomimp, iqat) end if ! OPT('XCPL') ! nonco angles: defined in mod_wunfiles ! call read_angles(t_params, natyp, theta, phi) theta(1:natyp) = t_params%theta(1:natyp) phi(1:natyp) = t_params%phi(1:natyp) ! Interpolate potential call interpolate_poten(lpotd,irmd,irnsd,natyp,ipand,lmpotd,nspotd,ntotd, & ntotd*(ncheb+1),nspin,rmesh,irmin,irws,ircut,vins,visp,npan_log_at, & npan_eq_at,npan_tot,rnew,ipan_intervall,vinsnew) do i1 = i1_start, i1_end do ispin = 1, nspin/(1+korbit) ! run spin-loop only if 'NOSOC' test option is not used ipot = nspin*(i1-1) + ispin #ifdef CPP_BdG if (write_BdG_tests) then call BdG_write_tmatnewsolver_inputs(nranks, i1, i1_start, ielast, & nspin, lmax, nsra, iend, lmpotd, lly, deltae, idoldau, ncleb, & ncheb, ntotd, mmaxd, nspind, iemxd, nrmaxd, nspotd, cleb, icleb, & ez, ipot, npan_tot, ipan_intervall, zat, phi, theta, & socscale, rnew, rpan_intervall, wldau, vinsnew, i1_end, natyp, lopt) end if #endif call tmat_newsolver(ielast, nspin, lmax, zat(i1), socscale(i1), ez, nsra, cleb(:,1), icleb, iend, ncheb, npan_tot(i1), rpan_intervall(:,i1), ipan_intervall(:,i1), & rnew(:,i1), vinsnew, theta(i1), phi(i1), i1, ipot, lmpotd, lly, deltae, idoldau, lopt(i1), wldau(:,:,:,i1), t_dtmatjij(i1), ispin) end do ! ispin end do ! i1_start, i1_end atom loop end if ! NEWSOSOL if (idoldau==1) then open (67, file='ldau.unformatted', form='unformatted') write (67) itrunldau, wldau, uldau, phildau close (67) end if close (69) if (lly/=0) then if (t_lloyd%dtmat_to_file) close (691) if (t_lloyd%tralpha_to_file) close (692) end if #ifdef CPP_MPI ! skip this part with GREENIMP option if (.not. (write_green_imp .or. impurity_operator_only)) then if (.not. t_tgmat%tmat_to_file) then do ii = 0, t_mpi_c_grid%nranks_ie - 1 ntot_all(ii) = t_mpi_c_grid%ntot_pt1(ii) ioff_all(ii) = t_mpi_c_grid%ioff_pt1(ii) end do mytot = t_mpi_c_grid%ntot_pt1(t_mpi_c_grid%myrank_ie) call gather_tmat(t_inc,t_tgmat,t_mpi_c_grid,ntot_all,ioff_all,mytot, & t_mpi_c_grid%mympi_comm_ie,t_mpi_c_grid%nranks_ie, nspin, lmmaxd, natypd) end if if (lly/=0 .and. .not. t_lloyd%dtmat_to_file) then if (mpiatom .and. t_mpi_c_grid%myrank_ie>(t_mpi_c_grid%dims(1)-1)) then ! reset tralpha and dtmat to zero for rest-ranks to avoid double counting ! for some reason this is only corect for mpiatom mode and not for ! mpienerg, I don't know why but this seems to fix it. P.R. 05.03.2019 t_lloyd%tralpha = czero t_lloyd%dtmat = czero end if call gather_lly_dtmat(t_mpi_c_grid,t_lloyd,lmmaxd,t_mpi_c_grid%mympi_comm_ie) end if ! ------------------------------------------------------------------------- ! for calculation of Jij-tensor ! ------------------------------------------------------------------------- if (calc_exchange_couplings .and. use_Chebychev_solver) then do i1 = 1, natypd ! initialize t_dtmatJij on other tasks ! t_dtmatJij was already allocated for certain atoms within the atom loop ! (in tmat_newsolver). This initialization cannot be made before tmat_newsolver, ! because the division of the enegry loop (done in there) influences t_dtmatJij. call init_t_dtmatjij_at(t_inc, t_mpi_c_grid, t_dtmatjij(i1)) ! communicate if (t_dtmatjij(i1)%calculate) then iwork = product(shape(t_dtmatjij(i1)%dtmat_xyz)) allocate (work_jij(iwork,1,1,1), stat=i_stat) call memocc(i_stat, product(shape(work_jij))*kind(work_jij), 'work_jij', 'main1a') call mpi_allreduce(t_dtmatjij(i1)%dtmat_xyz,work_jij,iwork, & mpi_double_complex, mpi_sum, t_mpi_c_grid%mympi_comm_ie, ierr) if (ierr/=mpi_success) stop 'error communicating t_dtmatJij' call zcopy(iwork, work_jij, 1, t_dtmatjij(i1)%dtmat_xyz, 1) i_all = -product(shape(work_jij))*kind(work_jij) deallocate (work_jij, stat=i_stat) call memocc(i_stat, i_all, 'work_jij', 'main1a') end if ! t_dtmatJij(I1)%calculate end do ! I1=1,t_inc%NATYP end if ! calc_exchange_couplings.and.use_Chebychev_solver end if ! .not.write_green_imp ! end skip this part with GREENIMP option #endif ! ------------------------------------------------------------------------- ! End of calculation of Jij-tensor ! ------------------------------------------------------------------------- #ifdef CPP_TIMING call timing_start('main1a - tbref') #endif if (lrefsys) then call tbref(ez, ielast,alat,vref,iend,lmax,ncls,nineq,nref,cleb,rcls,atom,cls, & icleb,loflm,nacls,refpot,rmtref,tolrdif,tmpdir,itmpdir,iltmp,naez,lly) ! LLY Lloyd end if #ifdef CPP_TIMING call timing_stop('main1a - tbref') #endif if (t_inc%i_write>0) write (1337, '(79("="),/,30X,"< KKR1a finished >",/,79("="),/)') ! Deallocate leftover arrays if (allocated(vinsnew)) then i_all = -product(shape(vinsnew))*kind(vinsnew) deallocate (vinsnew, stat=i_stat) call memocc(i_stat, i_all, 'VINSNEW', 'main1a') end if end subroutine main1a #ifdef CPP_BdG !------------------------------------------------------------------------------- !> Summary: Write out inputs for tmat_newsolver (BdG develop) !> Author: Philipp Ruessmann !> Deprecated: False !> Category: input-output, unit-test, KKRhost !> !> @note JC: not sure how this exactly works bur variables do not seem to need !> declaration before being run. Maybe it is a good idea to add it. !> @endnote !------------------------------------------------------------------------------- subroutine BdG_write_tmatnewsolver_inputs(nranks, i1, i1_start, ielast, & nspin, lmax, nsra, iend, lmpotd, lly, deltae, idoldau, ncleb, & ncheb, ntotd, mmaxd, nspind, iemxd, nrmaxd, nspotd, cleb, icleb, & ez, ipot, npan_tot, ipan_intervall, zat, phi, theta, & socscale, rnew, rpan_intervall, wldau, vinsnew, i1_end, natyp, lopt) ! write out inputs for tmat_newsolver to extract first BdG use mod_datatypes, only: dp use :: global_variables, only: nchebd implicit none integer, intent(in) :: nranks, i1, i1_start, ielast, nspin ,lmax, ncleb, nsra, natyp, iend, lmpotd, lly, idoldau, ncheb, mmaxd, nspind, iemxd, nrmaxd, nspotd, ipot, i1_end integer, intent(in) :: ntotd, icleb(ncleb,4), lopt(natyp), ipan_intervall(0:ntotd,natyp), npan_tot(natyp) real(kind=dp), intent(in) :: cleb(ncleb,2), zat(natyp), phi(natyp), theta(natyp), socscale(natyp), rnew(ntotd*(nchebd+1),natyp), rpan_intervall(0:ntotd,natyp) real(kind=dp), intent(in) :: wldau(:,:,:,:), vinsnew(:,:,:) complex(kind=dp), intent(in) :: deltae, ez(iemxd) if (nranks>1) stop 'test option BdG_dev can only be used in serial!' if (i1==i1_start) open (887766, file='BdG_tmat_inputs.txt', form='formatted') if (i1==1) then write (887766, '(A25)') 'global parameters:' write (887766, *) write (887766, '(A25,I9)') 'IELAST= ', ielast write (887766, '(A25,I9)') 'NSPIN= ', nspin write (887766, '(A25,I9)') 'LMAX= ', lmax write (887766, '(A25,I9)') 'NSRA= ', nsra write (887766, '(A25,I9)') 'IEND= ', iend write (887766, '(A25,I9)') 'LMPOTD= ', lmpotd write (887766, '(A25,I9)') 'LLY= ', lly write (887766, '(A25,2ES21.9)') 'DELTAE= ', deltae write (887766, '(A25,I9)') 'IDOLDAU= ', idoldau write (887766, '(A25,I9)') 'NCLEB= ', ncleb write (887766, '(A25,I9)') 'NCHEB= ', ncheb write (887766, '(A25,I9)') 'NTOTD= ', ntotd write (887766, '(A25,I9)') 'MMAXD= ', mmaxd write (887766, '(A25,I9)') 'NSPIND= ', nspind write (887766, '(A25,I9)') 'IEMXD= ', iemxd write (887766, '(A25,I9)') 'NRMAXD= ', nrmaxd write (887766, '(A25,I9)') 'NSPOTD= ', nspotd write (887766, '(A25)') 'CLEB= ' write (887766, '(999999999ES21.9)') cleb(:, 1) write (887766, '(A25)') 'ICLEB= ' write (887766, '(999999999I9)') icleb(:, :) write (887766, '(A25)') 'EZ= ' write (887766, '(2ES21.9)') ez write (887766, *) write (887766, '(A25)') 'atom-dependent input:' write (887766, *) end if write (887766, '(A25,I9)') 'I1= ', i1 write (887766, '(A25,I9)') 'IPOT= ', ipot write (887766, '(A25,I9)') 'NPAN_TOT= ', npan_tot(i1) write (887766, '(A25,I9)') 'LPOT= ', lopt(i1) write (887766, '(A25,999999999I9)') 'IPAN_INTERVALL= ', ipan_intervall(:, i1) write (887766, '(A25,ES21.9)') 'ZAT= ', zat(i1) write (887766, '(A25,ES21.9)') 'PHI= ', phi(i1) write (887766, '(A25,ES21.9)') 'THETA= ', theta(i1) write (887766, '(A25,ES21.9)') 'SOCSCALE= ', socscale(i1) write (887766, '(A25,999999999ES21.9)') 'RNEW= ', rnew(:, i1) write (887766, '(A25,999999999ES21.9)') 'RPAN_INTERVALL= ', rpan_intervall(:, i1) write (887766, '(A25,999999999ES21.9)') 'WLDAU= ', wldau(:, :, :, i1) write (887766, '(A25,999999999ES21.9)') 'VINSNEW= ', vinsnew write (887766, *) if (i1==i1_end) then close (887766) stop 'done writing tmat_newsolver input of test option BdG_dev' end if end subroutine bdg_write_tmatnewsolver_inputs #endif end module mod_main1a