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