!------------------------------------------------------------------------------- !> Summary: Computes Gaunt coefficients and spherical harmonics !> Author: !> Defines the variable for the gaunt coefficient and !> computes Gaunt coefficients and spherical harmonics !------------------------------------------------------------------------------- module mod_gauntharmonics use nrtype use mod_config, only: config_testflag use type_gauntcoeff use mod_types, only: t_inc type(GAUNTCOEFF_TYPE),allocatable :: gauntcoeff(:) !--------------------------------------------------------------------- ! old comment out !--------------------------------------------------------------------- ! type :: harmonicstype ! real(kind=dp),allocatable :: wg(:) ! real(kind=dp),allocatable :: yrg(:,:,:) ! end type harmonicstype ! type(HARMONICSTYPE),protected :: harmonics contains !------------------------------------------------------------------------------- !> Summary: Calculates the gaunt coefficients and sph. harmonics !> Author: !> Category: KKRimp, special-functions !> Deprecated: False !> Calculates the gaunt coefficients and sph. harmonics !------------------------------------------------------------------------------- subroutine gauntharmonics_set()!,lmaxatom) implicit none !local variables real(kind=dp),allocatable :: wg(:),yrg(:,:,:) integer,allocatable :: icleb(:,:) !: pointer array integer,allocatable :: loflm(:) !: l of lm=(l,m) (gaunt) real(kind=dp),allocatable :: cleb(:,:) !: gaunt coefficients (gaunt) integer :: iend !: number of nonzero gaunt coeffizients integer,allocatable :: jend(:,:,:) !: pointer array for icleb() integer :: ncleb integer :: lval integer :: lmaxbounds(2) integer :: lmaxd,lpotd,lmmaxd,lmpotd,lm2d lmaxbounds=0 ! call GAUNTHARMONICS_getlmaxbounds(lmaxatom,natom,lmaxbounds) lmaxbounds(1)=2 lmaxbounds(2)=4 allocate( gauntcoeff( lmaxbounds(1) : lmaxbounds(2) ) ) if (t_inc%i_write>0) write(1337,*) '------------------------------------------------------' if (t_inc%i_write>0) write(1337,*) '------- MODULE: GAUNTHAROMICS --------------' if (t_inc%i_write>0) write(1337,*) '------------------------------------------------------' if (t_inc%i_write>0) write(1337,*) ' min. LMAX VALUE = ',lmaxbounds(1) if (t_inc%i_write>0) write(1337,*) ' max. LMAX VALUE = ',lmaxbounds(2) if (t_inc%i_write>0) write(1337,*) ' creating GAUNTCOEFF in this range' do lval = lmaxbounds(1), lmaxbounds(2) lmaxd = lval lpotd = 2*lmaxd lmmaxd = (lmaxd+1)**2 lmpotd = (lpotd+1)**2 lm2d = (2*lmaxd+1)**2 ncleb = 2*(lmaxd*2+1)**2 * (lmaxd+1)**2 !bauer March 2012 allocate( icleb(ncleb,4), cleb(ncleb,2),& jend(lmpotd,0:lmaxd,0:lmaxd), loflm(lm2d),& wg(4*lmaxd), yrg(4*lmaxd,0:4*lmaxd,0:4*lmaxd) ) icleb=0;cleb=0;jend=0;loflm=0;wg=0;yrg=0 call gauntharmonics_gaunt2(wg,yrg,4*lmaxd) call gauntharmonics_gaunt1(lmaxd,lpotd,wg,yrg,cleb,loflm,& icleb,iend,jend, ncleb,lmaxd,lmmaxd,lmpotd) allocate( GAUNTcoeff(lval)%icleb(ncleb,4), GAUNTcoeff(lval)%cleb(ncleb,2), & GAUNTcoeff(lval)%jend(lmpotd,0:lmaxd,0:lmaxd), GAUNTcoeff(lval)%loflm(lm2d), & GAUNTcoeff(lval)%wg(4*lmaxd), GAUNTcoeff(lval)%yrg(4*lmaxd,0:4*lmaxd,0:4*lmaxd) ) GAUNTcoeff(lval) % cleb = cleb GAUNTcoeff(lval) % loflm = loflm GAUNTcoeff(lval) % icleb = icleb GAUNTcoeff(lval) % iend = iend GAUNTcoeff(lval) % jend = jend GAUNTcoeff(lval) % ncleb = ncleb GAUNTcoeff(lval) % wg = wg GAUNTcoeff(lval)%yrg = yrg deallocate( icleb, cleb, jend, loflm, wg, yrg ) ! open(unit=23982373,file='test_gauntcoeff_icleb') ! write(23982373,*) 'LVAL= ',lval ! do jj=1,GAUNTcoeff(lval) % iend ! write(23982373,*) gauntcoeff(lval)%ICLEB(jj,:) ! end do end do !lval !--------------------------------------------------------------------- ! if a testflag is set write out the gaunt coefficient data !--------------------------------------------------------------------- ! if (config_testflag('writegaunt')) then ! open(unit=435234,file='test_gaunt') ! write(*,*) 'Gaunt coefficients' ! write(*,*) 'GAUNTcoeff%ncleb' ! write(*,*) ncleb ! write(*,*) 'GAUNTcoeff%cleb(:,1)' ! write(*,*) cleb(:,1) ! write(*,*) 'GAUNTcoeff%cleb(:,2)' ! write(*,*) cleb(:,2) ! write(*,*) 'loflm' ! write(*,*) loflm ! write(*,*) 'icleb' ! write(*,*) icleb ! write(*,*) 'iend' ! write(*,*) iend ! write(*,*) 'jend' ! write(*,*) jend ! write(*,*) 'ncleb' ! write(*,*) ncleb ! close(435234) ! end if if (config_testflag('writefilegaunt')) then open(unit=3453453,file='gaunt.dat') write(3453453,*) 'WG' write(3453453,*) WG write(3453453,*) 'YRG' write(3453453,*) YRG write(3453453,*) 'CLEB' write(3453453,*) CLEB write(3453453,*) 'LOFLM' write(3453453,*) LOFLM write(3453453,*) 'ICLEB' write(3453453,*) ICLEB write(3453453,*) 'IEND' write(3453453,*) IEND write(3453453,*) 'JEND' write(3453453,*) JEND write(3453453,*) 'NCLEB' write(3453453,*) NCLEB close(3453453) end if end subroutine gauntharmonics_set !------------------------------------------------------------------------------- !> Summary: Get lmax bounds !> Author: B. Drittler !> Category: KKRimp !> Deprecated: True !> !------------------------------------------------------------------------------- subroutine GAUNTHARMONICS_getlmaxbounds(lmaxatom,natom,lmaxbounds) implicit none integer, intent(in) :: lmaxatom(natom) integer, intent(in) :: natom integer, intent(inout) :: lmaxbounds(2) integer :: iatom lmaxbounds=0 do iatom=1,natom if (lmaxbounds(1)==0 .and. lmaxbounds(2)==0) lmaxbounds=lmaxatom(iatom) if (lmaxatom(iatom)<lmaxbounds(1)) lmaxbounds(1)=lmaxatom(iatom) if (lmaxatom(iatom)>lmaxbounds(2)) lmaxbounds(2)=lmaxatom(iatom) end do !iatom end subroutine GAUNTHARMONICS_getlmaxbounds !------------------------------------------------------------------------------- !> Summary: Computes gaunt coefficients !> Author: B. Drittler !> Category: KKRimp, special-functions !> Deprecated: False !> !> - fills the array cleb with the gaunt coeffients ,i.e. !> the integral of y(l1,m1)*y(l2,m2)*y(l3,m3) !> but only for lm2.le.lm1 and lm3>1 !> - calculate the pointer array jend to project the indices !> array cleb with the same lm3,l1,l2 values - because of !> the special ordering of array cleb only the last index !> has to be determined. !> (the parameter n has to be chosen that l1+l2+l3 .lt. 2*n) !> using gaussian quadrature as given by !> M. Abramowitz and I.A. Stegun, Handbook of Mathematical Functions, !> NBS Applied Mathematics Series 55 (1968), pages 887 and 916 !> M. Weinert and E. Wimmer !> Northwestern University March 1980 !> !> An index array -icleb- is used to save storage place. !> fills the array loflm which is used to determine the !> l-value of a given lm-value. !> !> B. Drittler November 1987 !> !> modified gaunt coefficients are als calculated defined by !> the integral of y(l1,m1)*y(l2,m2)*y(l3,m3)*i**(l2-l1+l3) !> !------------------------------------------------------------------------------- !> @note !> This subroutine has to be called only once! !> @endnote !> @warning !> ncleb is an empirical factor - it has to be optimized !> @endwarning !------------------------------------------------------------------------------- SUBROUTINE GAUNTHARMONICS_GAUNT1(LMAX,LPOT,W,YR,CLEB,LOFLM,ICLEB,IEND,JEND, & NCLEB,LMAXD,LMGF0D,LMPOTD) ! ********************************************************************* ! * For KREL = 1 (relativistic mode) * ! * * ! * NPOTD = 2 * NATYPD * ! * LMMAXD = 2 * (LMAXD+1)^2 * ! * NSPIND = 1 * ! * LMGF0D = (LMAXD+1)^2 dimension of the reference system Green * ! * function, set up in the spin-independent non-relativstic * ! * (l,m_l)-representation * ! * * ! ********************************************************************* ! ! .. DOUBLE COMPLEX CI PARAMETER (CI= (0.0D0,1.0D0)) ! .. INTEGER LMPOTD,LMGF0D,LMAXD,NCLEB ! .. ! .. Scalar Arguments .. INTEGER IEND,LMAX,LPOT ! .. ! .. Array Arguments .. DOUBLE PRECISION CLEB(NCLEB,2),W(*), & YR(4*LMAXD,0:4*LMAXD,0:4*LMAXD) INTEGER ICLEB(NCLEB,4),JEND(LMPOTD,0:LMAXD,0:LMAXD),LOFLM(*) ! .. ! .. Local Scalars .. DOUBLE PRECISION CLECG,FACTOR,FCI,S INTEGER I,J,L,L1,L1P,L2,L2P,L3,LM1,LM2,LM3,LM3P,LMPOT,M,M1,M1A, & M1S,M2,M2A,M2S,M3,M3A,M3S ! .. ! .. Intrinsic Functions .. INTRINSIC ABS,DBLE,MOD,REAL,SIGN ! .. ! .. External Subroutines .. ! EXTERNAL RCSTOP ! .. I = 1 DO L = 0,2*LMAX DO M = -L,L LOFLM(I) = L I = I + 1 END DO END DO ! IF (LPOT.EQ.0) THEN IEND = 1 ICLEB(1,1) = (LMAX+1)**2 ICLEB(1,3) = 1 END IF ! IF (LPOT.NE.0) THEN ! !---> set up of the gaunt coefficients with an index field ! I = 1 DO L3 = 1,LPOT DO M3 = -L3,L3 ! DO L1 = 0,LMAX DO L2 = 0,L1 ! IF (MOD((L1+L2+L3),2).NE.1 .AND. (L1+L2-L3).GE.0 .AND. & (L1-L2+L3).GE.0 .AND. (L2-L1+L3).GE.0) THEN ! FCI = DBLE(CI** (L2-L1+L3)) DO M1 = -L1,L1 DO M2 = -L2,L2 ! !---> store only gaunt coeffients for lm2.le.lm1 ! LM1 = L1* (L1+1) + M1 + 1 LM2 = L2* (L2+1) + M2 + 1 IF (LM2.LE.LM1) THEN ! M1S = SIGN(1,M1) M2S = SIGN(1,M2) M3S = SIGN(1,M3) ! IF (M1S*M2S*M3S.GE.0) THEN ! M1A = ABS(M1) M2A = ABS(M2) M3A = ABS(M3) ! FACTOR = 0.0 ! IF (M1A+M2A.EQ.M3A) FACTOR = FACTOR + & REAL(3*M3S+SIGN(1,-M3))/8.0d0 IF (M1A-M2A.EQ.M3A) FACTOR = FACTOR + & REAL(M1S)/4.0d0 IF (M2A-M1A.EQ.M3A) FACTOR = FACTOR + & REAL(M2S)/4.0d0 ! IF (FACTOR.NE.0.0) THEN ! IF (M1S*M2S.NE.1 .OR. M2S*M3S.NE.1 .OR. & M1S*M3S.NE.1) FACTOR = -FACTOR ! S = 0.0 DO J = 1,4*LMAXD S = S + W(J)*YR(J,L1,M1A)*YR(J,L2,M2A)* & YR(J,L3,M3A) END DO !J CLECG = S*FACTOR IF (ABS(CLECG).GT.1.D-10) THEN CLEB(I,1) = CLECG CLEB(I,2) = FCI*CLECG ICLEB(I,1) = LM1 ICLEB(I,2) = LM2 ICLEB(I,3) = L3* (L3+1) + M3 + 1 ICLEB(I,4) = LM2*LMGF0D - & (LM2*LM2-LM2)/2 + LM1 - & LMGF0D I = I + 1 END IF END IF END IF END IF END DO !M2 END DO !M1 END IF END DO !L2 END DO !L1 END DO !M3 END DO !L3 IEND = I - 1 IF (NCLEB.LT.IEND) THEN WRITE (6,FMT=9000) NCLEB,IEND STOP '[GAUNT.f] stop' ELSE ! !---> set up of the pointer array jend,use explicitly ! the ordering of the gaunt coeffients ! LMPOT = (LPOT+1)* (LPOT+1) DO L1 = 0,LMAX DO L2 = 0,L1 DO LM3 = 2,LMPOT JEND(LM3,L1,L2) = 0 END DO !LM3 END DO !L2 END DO !L1 ! LM3 = ICLEB(1,3) L1 = LOFLM(ICLEB(1,1)) L2 = LOFLM(ICLEB(1,2)) ! DO J = 2,IEND LM3P = ICLEB(J,3) L1P = LOFLM(ICLEB(J,1)) L2P = LOFLM(ICLEB(J,2)) ! IF (LM3.NE.LM3P .OR. L1.NE.L1P .OR. L2.NE.L2P) THEN JEND(LM3,L1,L2) = J - 1 LM3 = LM3P L1 = L1P L2 = L2P END IF END DO !J JEND(LM3,L1,L2) = IEND ! ! END IF END IF ! ! 9000 FORMAT (13x,'error stop in gaunt : dimension of NCLEB = ',i10, & ' too small ',/, & 13x,'change NCLEB to ',i6) END SUBROUTINE GAUNTHARMONICS_GAUNT1 !------------------------------------------------------------------------------- !> Summary: Computes Gaunt coefficients !> Author: M. Weinert, B. Drittler !> Category: KKRimp, special-functions !> Deprecated: False !> !> Sets up values needed for gaunt !> m. weinert january 1982 !> !> Changed for calculating with real spherical harmonics !> b.drittler july 1987 !> !------------------------------------------------------------------------------- SUBROUTINE GAUNTHARMONICS_GAUNT2(W,YR,N) IMPLICIT NONE ! .. Arguments INTEGER N DOUBLE PRECISION W(*) !! integration weights on 4*LMAXD points in the interval (-1,0) (from routine GRULE) DOUBLE PRECISION YR(N,0:N,0:N) !! spherical harmonics on 4*LMAXD points to angular momentum indices (l,m) scaled with a factor of RF=(4*pi)**(1/3) ! .. ! .. Local Scalars .. DOUBLE PRECISION A,CD,CTH,FAC,FPI,RF,STH,T INTEGER K,L,LOMAX,M ! .. ! .. Local Arrays .. DOUBLE PRECISION P(0:N+1,0:N),X(N) ! .. ! .. External Subroutines .. ! EXTERNAL GRULE ! .. ! .. Intrinsic Functions .. INTRINSIC ATAN,SQRT ! .. FPI = 16D0*ATAN(1D0) RF = FPI**(1D0/3D0) LOMAX = N ! !---> obtain gauss-legendre points and weights ! CALL GAUNTHARMONICS_GRULE(2*N,X,W) ! !---> generate associated legendre functions for m.ge.0 ! DO K = 1,N CTH = X(K) STH = SQRT(1.D0-CTH*CTH) FAC = 1.D0 ! !---> loop over m values ! DO M = 0,LOMAX FAC = - DBLE(2*M-1)*FAC P(M,M) = FAC P(M+1,M) = DBLE(2*M+1)*CTH*FAC ! !---> recurse upward in l ! DO L = M + 2,LOMAX P(L,M) = ( DBLE(2*L-1)*CTH*P(L-1,M) & - DBLE(L+M-1) *P(L-2,M) ) / DBLE(L-M) END DO ! FAC = FAC*STH END DO ! !---> multiply in the normalization factors ! DO L = 0,LOMAX A = RF*SQRT((2*L+1)/FPI) CD = 1.D0 YR(K,L,0) = A*P(L,0) ! DO M = 1,L T = DBLE( (L+1-M)* (L+M)) CD = CD/T YR(K,L,M) = A*SQRT(2.D0*CD)*P(L,M) END DO END DO END DO END SUBROUTINE GAUNTHARMONICS_GAUNT2 !------------------------------------------------------------------------------- !> Summary: Generates Gauss-Legendre points and weights !> Author: P.J. Davis and P. Rabinowitz !> Category: KKRimp, special-functions !> Deprecated: False !> !> determines the (n+1)/2 nonnegative points x(i) and !> the corresponding weights w(i) of the n-point !> gauss-legendre integration rule, normalized to the !> interval [-1,1]. the x(i) appear in descending order. !> !------------------------------------------------------------------------------- !> @note !> This routine is from 'methods of numerical integration', !> P.J. Davis and P. Rabinowitz, page 369. !> @endnote !------------------------------------------------------------------------------- SUBROUTINE GAUNTHARMONICS_GRULE(N,X,W) ! !! .. Scalar Arguments .. INTEGER N ! .. ! .. Array Arguments .. DOUBLE PRECISION W(*),X(*) ! .. ! .. Local Scalars .. DOUBLE PRECISION D1,D2PN,D3PN,D4PN,DEN,DP,DPN,E1,FX,H,P,PI,PK, & PKM1,PKP1,T,T1,U,V,X0 INTEGER I,IT,K,M ! .. ! .. Intrinsic Functions .. INTRINSIC COS,ATAN ! .. PI = 4.D0*ATAN(1.D0) M = (N+1)/2 E1 = N* (N+1) DO I = 1,M T = (4*I-1)*PI/ (4*N+2) X0 = (1.0d0- (1.0d0-1.0d0/N)/ (8.0d0*N*N))*COS(T) ! !---> iterate on the value (m.w. jan. 1982) ! DO IT = 1,2 PKM1 = 1. PK = X0 DO K = 2,N T1 = X0*PK PKP1 = T1 - PKM1 - (T1-PKM1)/K + T1 PKM1 = PK PK = PKP1 END DO !K DEN = 1. - X0*X0 D1 = N* (PKM1-X0*PK) DPN = D1/DEN D2PN = (2.*X0*DPN-E1*PK)/DEN D3PN = (4.*X0*D2PN+ (2.-E1)*DPN)/DEN D4PN = (6.*X0*D3PN+ (6.-E1)*D2PN)/DEN U = PK/DPN V = D2PN/DPN H = -U* (1.+.5*U* (V+U* (V*V-U*D3PN/ (3.*DPN)))) P = PK + H* (DPN+.5*H* (D2PN+H/3.* (D3PN+.25*H*D4PN))) DP = DPN + H* (D2PN+.5*H* (D3PN+H*D4PN/3.)) H = H - P/DP X0 = X0 + H END DO !IT X(I) = X0 FX = D1 - H*E1* (PK+.5*H* (DPN+H/3.* (D2PN+.25*H* (D3PN+ & .2*H*D4PN)))) W(I) = 2.* (1.-X(I)*X(I))/ (FX*FX) END DO !I IF (M+M.GT.N) X(M) = 0. END SUBROUTINE GAUNTHARMONICS_GRULE end module mod_gauntharmonics