1! 2! Copyright (C) 1996-2016 The SIESTA group 3! This file is distributed under the terms of the 4! GNU General Public License: see COPYING in the top directory 5! or http://www.gnu.org/copyleft/gpl.txt. 6! See Docs/Contributors.txt for a list of contributors. 7! 8 module spher_harm 9 use precision 10 use sys 11 use alloc, only: re_alloc, de_alloc 12 13 implicit none 14 15 real(dp), pointer, private :: Y(:) => null() 16 real(dp), pointer, private :: DYDR(:,:) => null() 17 INTEGER, private :: MAX_LM=-1 18 19 public :: rlylm, ylmexp, ylmylm, lofilm 20 public :: reset_spher_harm 21 public :: gauleg !! for phirphi... 22 interface ylmexp 23 module procedure ylmexp_1, ylmexp_2 24 end interface 25 26 private 27 28 CONTAINS 29 30 subroutine rlylm( LMAX, R, RLY, GRLY ) 31 integer, intent(in) :: lmax 32 real(dp), intent(in) :: r(3) 33 real(dp), intent(out) :: rly(0:) 34! real(dp), intent(out) :: grly(3,0:) !!! Not accepted... 35 real(dp), intent(out) :: grly(1:,0:) 36 37C FINDS REAL SPHERICAL HARMONICS MULTIPLIED BY R**L: RLY=R**L*YLM, 38C AND THEIR GRADIENTS GRLY, AT POINT R: 39C YLM = C * PLM( COS(THETA) ) * SIN(M*PHI) FOR M < 0 40C YLM = C * PLM( COS(THETA) ) * COS(M*PHI) FOR M >= 0 41C WITH (THETA,PHI) THE POLAR ANGLES OF R, C A POSITIVE NORMALIZATION 42C CONSTANT AND PLM ASSOCIATED LEGENDRE POLYNOMIALS. 43C THE ORDER OF THE Y'S IS THAT IMPLICIT IN THE NESTED LOOPS 44C DO L=0,LMAX 45C DO M=-L,L 46C WITH A UNIFIED INDEX ILM=1,...,LMAX**2 INCREASING BY ONE UNIT IN THE 47C INNER LOOP. 48C WRITTEN BY J.M.SOLER. AUG/96 49C *********** INPUT *************************************************** 50C INTEGER LMAX : Maximum angular momentum quantum number required. 51C REAL*8 R(3) : Position at which Y and GY are required. 52C *********** OUTPUT ************************************************** 53C REAL*8 RLY(LMAX*LMAX) : Real spherical harmonics times r**l, 54C at point R, as explained above. 55C REAL*8 GRLY(3,LMAX*LMAX) : Gradient of the RLY's at point R. 56C *********** UNITS *************************************************** 57C Units of R are arbitrary. Units of RLY and GRLY are related to those 58C of R in the obvious way. 59C ********************************************************************* 60 61 62C Dimension parameters for internal variables 63 INTEGER MAXL, MAXLP1 64 PARAMETER ( MAXL = 10, MAXLP1 = MAXL+1 ) 65 66C Other internal parameters 67 REAL(DP) TINY, ZERO, HALF, ONE, TWO, THREE, SIX 68 PARAMETER (TINY=1.e-14_dp, ZERO=0._dp, HALF=0.5_dp, ONE=1._dp, 69 . TWO=2._dp, THREE=3._dp, SIX=6._dp) 70 71 real(dp), parameter :: pi = 3.14159265358979323846264338327950_dp 72 real(dp), parameter :: pi4 = 4 * pi 73 74C Internal variables 75 INTEGER 76 . I, ILM, ILM0, L, LMXMX, M 77 REAL(DP) 78 . C(0:MAXLP1*MAXLP1), COSM, COSMM1, COSPHI, 79 . ZP(0:MAXLP1,0:MAXLP1), FAC, GY(3), 80 . P(0:MAXLP1,0:MAXLP1), 81 . RL(-1:MAXL), RSIZE, RX, RY, RZ, RXY, 82 . SINM, SINMM1, SINPHI, YY 83 SAVE LMXMX, C 84 DATA LMXMX /-1/ 85 86C Evaluate normalization constants once and for all 87 IF (LMAX.GT.LMXMX) THEN 88 IF (LMAX.GT.MAXL) call die('YLM: MAXL too small') 89 DO 20 L=0,LMAX 90 ILM0=L*L+L 91 DO 15 M=0,L 92 FAC=(2*L+1)/pi4 93 DO 10 I=L-M+1,L+M 94 FAC=FAC/I 95 10 CONTINUE 96 C(ILM0+M)=SQRT(FAC) 97C Next line because YY's are real combinations of M and -M 98 IF (M.NE.0) C(ILM0+M)=C(ILM0+M)*SQRT(TWO) 99 C(ILM0-M)=C(ILM0+M) 100 15 CONTINUE 101 20 CONTINUE 102 LMXMX=LMAX 103 ENDIF 104 105C Initalize to zero 106 DO 25 ILM = 0,(LMAX+1)*(LMAX+1)-1 107 RLY(ILM) = ZERO 108 GRLY(1,ILM) = ZERO 109 GRLY(2,ILM) = ZERO 110 GRLY(3,ILM) = ZERO 111 25 CONTINUE 112 113C Explicit formulas up to L=2 114 IF (LMAX.LE.2) THEN 115 116 RLY(0) = C(0) 117 118C Label 999 is the exit point 119 IF (LMAX.EQ.0) GOTO 999 120 121 RLY(1) = -(C(1)*R(2)) 122 GRLY(2,1) = -C(1) 123 124 RLY(2) = C(2)*R(3) 125 GRLY(3,2) = C(2) 126 127 RLY(3) = -(C(3)*R(1)) 128 GRLY(1,3) = -C(3) 129 130 IF (LMAX.EQ.1) GOTO 999 131 132 RLY(4) = C(4)*SIX*R(1)*R(2) 133 GRLY(1,4) = C(4)*SIX*R(2) 134 GRLY(2,4) = C(4)*SIX*R(1) 135 136 RLY(5) = (-C(5))*THREE*R(2)*R(3) 137 GRLY(2,5) = (-C(5))*THREE*R(3) 138 GRLY(3,5) = (-C(5))*THREE*R(2) 139 140 RLY(6) = C(6)*HALF*(TWO*R(3)*R(3)-R(1)*R(1)-R(2)*R(2)) 141 GRLY(1,6) = (-C(6))*R(1) 142 GRLY(2,6) = (-C(6))*R(2) 143 GRLY(3,6) = C(6)*TWO*R(3) 144 145 RLY(7) = (-C(7))*THREE*R(1)*R(3) 146 GRLY(1,7) = (-C(7))*THREE*R(3) 147 GRLY(3,7) = (-C(7))*THREE*R(1) 148 149 RLY(8) = C(8)*THREE*(R(1)*R(1)-R(2)*R(2)) 150 GRLY(1,8) = C(8)*SIX*R(1) 151 GRLY(2,8) = (-C(8))*SIX*R(2) 152 153 GOTO 999 154 ENDIF 155 156C Special case for R=0 157 RSIZE = SQRT( R(1)*R(1)+R(2)*R(2)+R(3)*R(3) ) 158 IF ( RSIZE .LT. TINY ) THEN 159 RLY(0) = C(0) 160 GRLY(2,1) = -C(1) 161 GRLY(3,2) = C(2) 162 GRLY(1,3) = -C(3) 163 GOTO 999 164 ENDIF 165 166C Avoid z axis 167 RX = R(1) / RSIZE 168 RY = R(2) / RSIZE 169 RZ = R(3) / RSIZE 170 RXY = SQRT(RX*RX+RY*RY) 171 IF (RXY.LT.TINY) THEN 172 RX = TINY 173 RXY = SQRT(RX*RX+RY*RY) 174 ENDIF 175 176C General algorithm based on routine PLGNDR of 'Numerical Recipes' 177C See also J.M.Soler notes of 23/04/96. 178C Find associated Legendre polynomials and their derivative 179 DO 60 M=LMAX,0,-1 180 P(M,M+1)=ZERO 181 P(M,M)=ONE 182 FAC=ONE 183 DO 30 I=1,M 184 P(M,M)=-(P(M,M)*FAC*RXY) 185 FAC=FAC+TWO 186 30 CONTINUE 187 P(M+1,M)=RZ*(2*M+1)*P(M,M) 188 DO 40 L=M+2,LMAX 189 P(L,M)=(RZ*(2*L-1)*P(L-1,M)-(L+M-1)*P(L-2,M))/(L-M) 190 40 CONTINUE 191 DO 50 L=M,LMAX 192 ZP(L,M)=-((M*P(L,M)*RZ/RXY+P(L,M+1))/RXY) 193 50 CONTINUE 194 60 CONTINUE 195C Find spherical harmonics and their gradient 196 RL(-1) = ZERO 197 RL(0) = ONE 198 DO 70 L = 1,LMAX 199 RL(L) = RL(L-1)*RSIZE 200 70 CONTINUE 201 COSPHI=RX/RXY 202 SINPHI=RY/RXY 203 COSM=ONE 204 SINM=ZERO 205 DO 90 M=0,LMAX 206 DO 80 L=M,LMAX 207 ILM=L*L+L-M 208 GY(1)=(-ZP(L,M))*RX *RZ *SINM - P(L,M)*M*COSM*SINPHI/RXY 209 GY(2)=(-ZP(L,M))*RY *RZ *SINM + P(L,M)*M*COSM*COSPHI/RXY 210 GY(3)= ZP(L,M)*RXY*RXY*SINM 211 YY=C(ILM)*P(L,M)*SINM 212 RLY(ILM)=RL(L)*YY 213 GRLY(1,ILM)= RX*L*RL(L-1)*YY + RL(L)*GY(1)*C(ILM)/RSIZE 214 GRLY(2,ILM)= RY*L*RL(L-1)*YY + RL(L)*GY(2)*C(ILM)/RSIZE 215 GRLY(3,ILM)= RZ*L*RL(L-1)*YY + RL(L)*GY(3)*C(ILM)/RSIZE 216 217 ILM=L*L+L+M 218 GY(1)=(-ZP(L,M))*RX *RZ *COSM + P(L,M)*M*SINM*SINPHI/RXY 219 GY(2)=(-ZP(L,M))*RY *RZ *COSM - P(L,M)*M*SINM*COSPHI/RXY 220 GY(3)= ZP(L,M)*RXY*RXY*COSM 221 YY=C(ILM)*P(L,M)*COSM 222 RLY(ILM)=RL(L)*YY 223 GRLY(1,ILM)= RX*L*RL(L-1)*YY + RL(L)*GY(1)*C(ILM)/RSIZE 224 GRLY(2,ILM)= RY*L*RL(L-1)*YY + RL(L)*GY(2)*C(ILM)/RSIZE 225 GRLY(3,ILM)= RZ*L*RL(L-1)*YY + RL(L)*GY(3)*C(ILM)/RSIZE 226 75 CONTINUE 227 80 CONTINUE 228 COSMM1=COSM 229 SINMM1=SINM 230 COSM=COSMM1*COSPHI-SINMM1*SINPHI 231 SINM=COSMM1*SINPHI+SINMM1*COSPHI 232 90 CONTINUE 233 234 999 CONTINUE 235 END SUBROUTINE RLYLM 236 237 SUBROUTINE YLMYLM( ILM1, ILM2, R, YY, DYYDR ) 238 implicit none 239 INTEGER, intent(in) :: ILM1, ILM2 240 REAL(DP), intent(in) :: R(3) 241 REAL(DP), intent(out) :: YY, DYYDR(3) 242 243C Returns the product of two real spherical harmonics (SH), 244C times r**l each, and its gradient. 245C *********** INPUT *************************************************** 246C INTEGER ILM1, ILM2 : Combined SH indexes. ILM = L*L+L+M+1 247C REAL*8 R(3) : Vector towards the (theta,phi) direction. 248C *********** OUTPUT ************************************************** 249C REAL*8 YY : Product of the two SH. 250C REAL*8 DYYDR(3) : Derivative (gradient) of YY with respect to R 251C ********************************************************************* 252C Written by J.M.Soler. Feb' 96. 253C ********************************************************************* 254 INTEGER I, L, LM 255 256 L = MAX( LOFILM(ILM1), LOFILM(ILM2) ) 257 LM = (L+1)*(L+1) 258 259 if (LM.gt.MAX_LM) then 260 261 MAX_LM = LM 262 call re_alloc( Y, 0, MAX_LM, 'Y', 'spher_harm' ) 263 call re_alloc( DYDR, 1, 3, 0, MAX_LM, 'DYDR', 'spher_harm' ) 264 endif 265 266 CALL RLYLM( L, R, Y, DYDR ) 267 268 YY = Y(ILM1-1) * Y(ILM2-1) 269 do I = 1,3 270 DYYDR(I) = DYDR(I,ILM1-1)*Y(ILM2-1) + Y(ILM1-1)*DYDR(I,ILM2-1) 271 enddo 272 273 END SUBROUTINE YLMYLM 274 275 INTEGER FUNCTION LOFILM( ILM ) 276 integer, intent(in) :: ilm 277 278C Finds the total angular momentum quantum number L which corresponds 279C to the combined index ILM == (L,M) implicit in the nested loop 280C ILM = 0 281C DO L=0,LMAX 282C DO M=-L,L 283C ILM = ILM + 1 284C with ILM = 1,2,...,L**2 285C Written by J.M.Soler. April 1996. 286 287 INTEGER JLM, MAXL 288 PARAMETER ( MAXL = 100 ) 289 290 if ( ILM .LE. 0 ) call die('LOFILM: ILM not allowed') 291 JLM = 0 292 DO 10 LOFILM = 0,MAXL 293 JLM = JLM + 2*LOFILM + 1 294 IF ( JLM .GE. ILM ) RETURN 295 10 CONTINUE 296 call die('LOFILM: ILM too large') 297 END function lofilm 298 299! 300! There are now two implementations of ylmexp, with 301! one and two indexes for "func" 302! 303 SUBROUTINE YLMEXP_2( LMAX, RLYLM_F, FUNC, IS, IO, IR1, NR, RMAX, 304 . NY, ILM, FLM ) 305C Makes a radial times spherical-harmonic expansion of a function. 306 307 integer, intent(in) :: lmax 308 interface 309 subroutine rlylm_f(lmax,rvec,yy,grady) 310 use precision, only: dp 311 integer, intent(in) :: lmax 312 real(dp), intent(in) :: rvec(3) 313 real(dp), intent(out) :: yy(0:) 314 real(dp), intent(out) :: grady(1:,0:) 315 end subroutine rlylm_f 316 317 subroutine func(i1,i2,rvec,yy,grady) 318 use precision, only: dp 319 integer, intent(in) :: i1, i2 320 real(dp), intent(in) :: rvec(3) 321 real(dp), intent(out) :: yy, grady(3) 322 end subroutine func 323 end interface 324 325 integer, intent(in) :: is, io 326 integer, intent(in) :: ir1, nr 327 real(dp), intent(in) :: rmax 328 329 integer, intent(out) :: ny 330 integer, intent(out) :: ilm(:) 331 real(dp), dimension(ir1:,:), intent(out) :: flm 332 333C Written by J.M.Soler. September 1995. 334C ************************* INPUT *********************************** 335C INTEGER LMAX : Max. ang. momentum quantum number 336C EXTERNAL RLYLM_F(Lmax,Rvec,yy,GradY) : Returns spherical harmonics, 337C times r**l 338C EXTERNAL FUNC(IS,IO,Rvec,F,GradF) : Function to be expanded. 339C INTEGER IS, IO : Indexes to call FUNC. 340C INTEGER IR1 : First radial index. 341C INTEGER NR : Last radial index. 342C REAL*8 RMAX : Maximum radius: R(IR)=RMAX*IR/NR 343C ************************* OUTPUT ********************************** 344C INTEGER NY : Number of spherical harmonics required. 345C INTEGER ILM(NY) : Spherical harmonics indexes: ILM=L*L+L+M+1. 346C REAL*8 FLM(IR1:NR,NY): Radial expansion for each spherical harmonic: 347C F(Rvec) = Sum_iy( FLM(Rmod,iy) * YY(Rdir,ILM(iy)) ), 348C with Rmod = RMAX*IR/NR 349C ************************* UNITS *********************************** 350C RMAX must be in the same units of the argument Rvec in FUNC. 351C FLM is in the same units of the argument F in FUNC. 352C ************************* BEHAVIOUR ******************************* 353C If function FUNC contains angular components with L higher than LMAX, 354C they will corrupt those computed with lower L. 355C ******************************************************************* 356 357 358C Tolerance for FLM ------------------------------------------------- 359 REAL(DP) FTOL 360 PARAMETER ( FTOL = 1.e-12_dp ) 361C ------------------------------------------------------------------- 362 363C Dimension parameters for internal variables ----------------------- 364 INTEGER MAXL, MAXLM, MAXSP 365 PARAMETER ( MAXL = 8 ) 366 PARAMETER ( MAXLM = (MAXL+1) * (MAXL+1) ) 367 PARAMETER ( MAXSP = (MAXL+1) * (2*MAXL+1) ) 368C ------------------------------------------------------------------- 369 370C Declare internal variables ---------------------------------------- 371 INTEGER 372 . IM, IR, ISP, IZ, JLM, JR, JY, NLM, NSP 373 REAL(DP) 374 . DFDX(3), DYDX(3,MAXLM), 375 . F(MAXSP), FY, PHI, PI, R, RX(3), THETA, 376 . W(MAXL+1), WSP, 377 . X(3,MAXSP), YY(MAXLM), YSP(MAXSP,MAXLM), 378 . Z(MAXL+1) 379 EXTERNAL CHKDIM 380* EXTERNAL TIMER 381C ------------------------------------------------------------------- 382 383C Start time counter ------------------------------------------------ 384* CALL TIMER( 'YLMEXP', 1 ) 385C ------------------------------------------------------------------- 386 387C Check maximum angular momentum ------------------------------------ 388 CALL CHKDIM( 'YLMEXP', 'MAXL', MAXL, LMAX, 1 ) 389C ------------------------------------------------------------------- 390 391C Find special points and weights for gaussian quadrature ----------- 392 CALL GAULEG( -1._dp, 1._dp, Z, W, LMAX+1 ) 393C ------------------------------------------------------------------- 394 395C Find weighted spherical harmonics at special points --------------- 396 PI = 4._dp * ATAN(1._dp) 397 NLM = (LMAX+1)**2 398 NSP = 0 399 DO 30 IZ = 1,LMAX+1 400 THETA = ACOS( Z(IZ) ) 401 DO 20 IM = 0,2*LMAX 402 NSP = NSP + 1 403 PHI = IM * 2._dp * PI / (2*LMAX+1) 404 X(1,NSP) = SIN(THETA) * COS(PHI) 405 X(2,NSP) = SIN(THETA) * SIN(PHI) 406 X(3,NSP) = COS(THETA) 407 CALL RLYLM_F( LMAX, X(1,NSP), YY, DYDX ) 408 WSP = W(IZ) * (2._dp*PI) / (2*LMAX+1) 409 DO 10 JLM = 1,NLM 410 YSP(NSP,JLM) = WSP * YY(JLM) 411 10 CONTINUE 412 20 CONTINUE 413 30 CONTINUE 414C ------------------------------------------------------------------- 415 ILM = 0 416 417C Expand FUNC in spherical harmonics at each radius ----------------- 418 NY = 0 419 420C Loop on radial points 421 DO 80 IR = IR1,NR 422 R = IR * RMAX / NR 423 424C Find function at points on a sphere of radius R 425 DO 40 ISP = 1,NSP 426 RX(1) = R * X(1,ISP) 427 RX(2) = R * X(2,ISP) 428 RX(3) = R * X(3,ISP) 429 CALL FUNC( IS, IO, RX, F(ISP), DFDX ) 430 40 CONTINUE 431 432C Expand F(R) in spherical harmonics 433 DO 70 JLM = 1,NLM 434! FY = DDOT(NSP,F,1,YSP(1,JLM),1) 435 FY = dot_product(F(1:nsp),YSP(1:nsp,JLM)) 436 IF ( ABS(FY) .GT. FTOL ) THEN 437C Find JY corresponding to JLM 438 DO 50 JY = 1,NY 439 IF ( ILM(JY) .EQ. JLM ) THEN 440 FLM(IR,JY) = FY 441 GOTO 70 442 ENDIF 443 50 CONTINUE 444 445C New spherical harmonic required. 446 NY = NY + 1 447 ILM(NY) = JLM 448 DO 60 JR = IR1,NR 449 FLM(JR,NY) = 0._dp 450 60 CONTINUE 451 FLM(IR,NY) = FY 452 ENDIF 453 70 CONTINUE 454 455 80 CONTINUE 456C ------------------------------------------------------------------- 457 458C Special case for zero function ------------------------------------ 459 IF (NY .EQ. 0) THEN 460 NY = 1 461 ILM(1) = 1 462 DO 90 IR = IR1,NR 463 FLM(IR,1) = 0._dp 464 90 CONTINUE 465 ENDIF 466C ------------------------------------------------------------------- 467 468C Stop time counter ------------------------------------------------- 469* CALL TIMER( 'YLMEXP', 2 ) 470C ------------------------------------------------------------------- 471 472 end subroutine ylmexp_2 473! 474! Version with a single global index to call func 475! 476 SUBROUTINE YLMEXP_1( LMAX, RLYLM_F, FUNC, IG, IR1, NR, RMAX, 477 . NY, ILM, FLM ) 478C Makes a radial times spherical-harmonic expansion of a function. 479 480 integer, intent(in) :: lmax 481 interface 482 subroutine rlylm_f(lmax,rvec,yy,grady) 483 use precision, only: dp 484 integer, intent(in) :: lmax 485 real(dp), intent(in) :: rvec(3) 486 real(dp), intent(out) :: yy(0:) 487 real(dp), intent(out) :: grady(1:,0:) 488 end subroutine rlylm_f 489 490 subroutine func(ig,rvec,yy,grady) 491 use precision, only: dp 492 integer, intent(in) :: ig 493 real(dp), intent(in) :: rvec(3) 494 real(dp), intent(out) :: yy, grady(3) 495 end subroutine func 496 end interface 497 498 integer, intent(in) :: ig 499 integer, intent(in) :: ir1, nr 500 real(dp), intent(in) :: rmax 501 502 integer, intent(out) :: ny 503 integer, intent(out) :: ilm(:) 504 real(dp), dimension(ir1:,:), intent(out) :: flm 505 506C Written by J.M.Soler. September 1995. 507C ************************* INPUT *********************************** 508C INTEGER LMAX : Max. ang. momentum quantum number 509C EXTERNAL RLYLM_F(Lmax,Rvec,yy,GradY) : Returns spherical harmonics, 510C times r**l 511C EXTERNAL FUNC(IS,IO,Rvec,F,GradF) : Function to be expanded. 512C INTEGER IG : Global Index to call FUNC. 513C INTEGER IR1 : First radial index. 514C INTEGER NR : Last radial index. 515C REAL*8 RMAX : Maximum radius: R(IR)=RMAX*IR/NR 516C ************************* OUTPUT ********************************** 517C INTEGER NY : Number of spherical harmonics required. 518C INTEGER ILM(NY) : Spherical harmonics indexes: ILM=L*L+L+M+1. 519C REAL*8 FLM(IR1:NR,NY): Radial expansion for each spherical harmonic: 520C F(Rvec) = Sum_iy( FLM(Rmod,iy) * YY(Rdir,ILM(iy)) ), 521C with Rmod = RMAX*IR/NR 522C ************************* UNITS *********************************** 523C RMAX must be in the same units of the argument Rvec in FUNC. 524C FLM is in the same units of the argument F in FUNC. 525C ************************* BEHAVIOUR ******************************* 526C If function FUNC contains angular components with L higher than LMAX, 527C they will corrupt those computed with lower L. 528C ******************************************************************* 529 530 531C Tolerance for FLM ------------------------------------------------- 532 REAL(DP) FTOL 533 PARAMETER ( FTOL = 1.e-12_dp ) 534C ------------------------------------------------------------------- 535 536C Dimension parameters for internal variables ----------------------- 537 INTEGER MAXL, MAXLM, MAXSP 538 PARAMETER ( MAXL = 8 ) 539 PARAMETER ( MAXLM = (MAXL+1) * (MAXL+1) ) 540 PARAMETER ( MAXSP = (MAXL+1) * (2*MAXL+1) ) 541C ------------------------------------------------------------------- 542 543C Declare internal variables ---------------------------------------- 544 INTEGER 545 . IM, IR, ISP, IZ, JLM, JR, JY, NLM, NSP 546 REAL(DP) 547 . DFDX(3), DYDX(3,MAXLM), 548 . F(MAXSP), FY, PHI, PI, R, RX(3), THETA, 549 . W(MAXL+1), WSP, 550 . X(3,MAXSP), YY(MAXLM), YSP(MAXSP,MAXLM), 551 . Z(MAXL+1) 552 EXTERNAL CHKDIM 553* EXTERNAL TIMER 554C ------------------------------------------------------------------- 555 556C Start time counter ------------------------------------------------ 557* CALL TIMER( 'YLMEXP', 1 ) 558C ------------------------------------------------------------------- 559 560C Check maximum angular momentum ------------------------------------ 561 CALL CHKDIM( 'YLMEXP', 'MAXL', MAXL, LMAX, 1 ) 562C ------------------------------------------------------------------- 563 564C Find special points and weights for gaussian quadrature ----------- 565 CALL GAULEG( -1._dp, 1._dp, Z, W, LMAX+1 ) 566C ------------------------------------------------------------------- 567 568C Find weighted spherical harmonics at special points --------------- 569 PI = 4._dp * ATAN(1._dp) 570 NLM = (LMAX+1)**2 571 NSP = 0 572 DO 30 IZ = 1,LMAX+1 573 THETA = ACOS( Z(IZ) ) 574 DO 20 IM = 0,2*LMAX 575 NSP = NSP + 1 576 PHI = IM * 2._dp * PI / (2*LMAX+1) 577 X(1,NSP) = SIN(THETA) * COS(PHI) 578 X(2,NSP) = SIN(THETA) * SIN(PHI) 579 X(3,NSP) = COS(THETA) 580 CALL RLYLM_F( LMAX, X(1,NSP), YY, DYDX ) 581 WSP = W(IZ) * (2._dp*PI) / (2*LMAX+1) 582 DO 10 JLM = 1,NLM 583 YSP(NSP,JLM) = WSP * YY(JLM) 584 10 CONTINUE 585 20 CONTINUE 586 30 CONTINUE 587C ------------------------------------------------------------------- 588 ILM = 0 589 590C Expand FUNC in spherical harmonics at each radius ----------------- 591 NY = 0 592 593C Loop on radial points 594 DO 80 IR = IR1,NR 595 R = IR * RMAX / NR 596 597C Find function at points on a sphere of radius R 598 DO 40 ISP = 1,NSP 599 RX(1) = R * X(1,ISP) 600 RX(2) = R * X(2,ISP) 601 RX(3) = R * X(3,ISP) 602 CALL FUNC( IG, RX, F(ISP), DFDX ) 603 40 CONTINUE 604 605C Expand F(R) in spherical harmonics 606 DO 70 JLM = 1,NLM 607! FY = DDOT(NSP,F,1,YSP(1,JLM),1) 608 FY = dot_product(F(1:nsp),YSP(1:nsp,JLM)) 609 IF ( ABS(FY) .GT. FTOL ) THEN 610C Find JY corresponding to JLM 611 DO 50 JY = 1,NY 612 IF ( ILM(JY) .EQ. JLM ) THEN 613 FLM(IR,JY) = FY 614 GOTO 70 615 ENDIF 616 50 CONTINUE 617 618C New spherical harmonic required. 619 NY = NY + 1 620 ILM(NY) = JLM 621 DO 60 JR = IR1,NR 622 FLM(JR,NY) = 0._dp 623 60 CONTINUE 624 FLM(IR,NY) = FY 625 ENDIF 626 70 CONTINUE 627 628 80 CONTINUE 629C ------------------------------------------------------------------- 630 631C Special case for zero function ------------------------------------ 632 IF (NY .EQ. 0) THEN 633 NY = 1 634 ILM(1) = 1 635 DO 90 IR = IR1,NR 636 FLM(IR,1) = 0._dp 637 90 CONTINUE 638 ENDIF 639C ------------------------------------------------------------------- 640 641C Stop time counter ------------------------------------------------- 642* CALL TIMER( 'YLMEXP', 2 ) 643C ------------------------------------------------------------------- 644 645 end subroutine ylmexp_1 646 647 subroutine gauleg(X1,X2,X,W,N) 648! 649! Abscissas and weights for Gauss-Legendre quadrature formula 650! 651 integer, intent(in) :: N 652 real(dp), intent(in) :: X1,X2 653 real(dp), intent(out) :: X(N),W(N) 654 655 real(dp), PARAMETER :: EPS=3.e-14_dp 656 657 integer m, i, j 658 real(dp) xm, xl, z, p1, p2, p3, pp, z1 659 660 M = (N+1)/2 661 XM = 0.5_DP*(X2+X1) 662 XL = 0.5_DP*(X2-X1) 663 DO 12 I=1,M 664 Z=COS(3.141592654_DP*(I-.25_DP)/(N+.5_DP)) 6651 CONTINUE 666 P1=1._DP 667 P2=0._DP 668 DO 11 J=1,N 669 P3=P2 670 P2=P1 671 P1=((2._DP*J-1._DP)*Z*P2-(J-1._DP)*P3)/J 67211 CONTINUE 673 PP=N*(Z*P1-P2)/(Z*Z-1._DP) 674 Z1=Z 675 Z=Z1-P1/PP 676 IF(ABS(Z-Z1).GT.EPS)GO TO 1 677 X(I)=XM-XL*Z 678 W(I)=2._DP*XL/((1._DP-Z*Z)*PP*PP) 679 X(N+1-I)=XM+XL*Z 680 W(N+1-I)=W(I) 68112 CONTINUE 682 683 end subroutine gauleg 684 685 SUBROUTINE RESET_SPHER_HARM( ) 686 implicit none 687 if (MAX_LM.gt.0) then 688 MAX_LM = -1 689 call de_alloc( Y, 'Y', 'spher_harm' ) 690 call de_alloc( DYDR, 'DYDR', 'spher_harm' ) 691 endif 692 END SUBROUTINE RESET_SPHER_HARM 693 694 end module spher_harm 695