summaryrefslogtreecommitdiff
path: root/Dragon/src/MOCCHR.f
blob: dad21fb703b502d6dfa766941621741c8bde52b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
*DECK MOCCHR
      SUBROUTINE MOCCHR(NDIM,NANI,NFUNL,NMU,XMUANG,PHI1,PHI2,R)
*
*-----------------------------------------------------------------------
*
*Purpose:
* Generates all spherical harmonics R(L,M) at point (XMUANG,PHI1).
*
*Copyright:
* Copyright (C) 2002 Ecole Polytechnique de Montreal
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version
*
*Author(s): R. Roy
*
*Parameters: input
* NDIM    number of dimensions for the geometry.
* NANI    scattering anisotropy (=0 for isotropic scattering).
* NFUNL   number of spherical harmonics per polar angle.
* NMU     order of the polar quadrature in 2D and 1 in 3D.
* XMUANG  cosines of the different tracking polar angles
*         (polar quadrature in 2D and tracking angles in 3D).
* PHI1    first cosine of the tracking azimuthal angle.
* PHI2    second cosine of the tracking azimuthal angle.
*
*Parameters: output
* R       spherical harmonics.
*
*Comments:
*  for 0 <= L <= NANI (and for -L <= M <= L)
*  and for all angles (for 1 <= IMU <= NMU).
*    Definition of spherical harmonics R(L,M):
*    R(L, M)= FACT(L,M)*P(L,M)*COS(M*PHI1)  for 0 < M <= L
*    R(L, 0)=           P(L,0)
*    R(L,-M)= FACT(L,M)*P(L,M)*SIN(M*PHI1)  for 0 < M <= L
*    where FACT(L,M)= SQRT( 2*(L-M)!/(L+M)! )
*
*-----------------------------------------------------------------------
*
      IMPLICIT NONE
*----
*  SUBROUTINE ARGUMENTS
*----
      INTEGER          NDIM,NANI,NFUNL,NMU
      REAL             XMUANG(NMU),R(NMU,NFUNL)
      DOUBLE PRECISION PHI1,PHI2
*----
*  LOCAL VARIABLES
*----
      INTEGER          IMU,L,M,LPM,LMMP1,IND,NSELEC
      LOGICAL          LROK
      DOUBLE PRECISION DPHI,DCOP2,DSIP2,DL00,DL10,DL01,DL11,DM0,DM1,
     >                 DM2,DCOS,DSIN,DCOT,DFAC,DZERO,DONE
      DOUBLE PRECISION, ALLOCATABLE, DIMENSION(:,:) :: RWORK
      PARAMETER ( DZERO= 0.0D0, DONE= 1.0D0 )
*
*     INDEX FOR MATRIX 'RWORK'
      IND(L,M)= L*(L+1) + M + 1
*
***** FIRST, COMPUTES ALL SPHERICAL HARMONICS
*
*     GENERATES ALL LEGENDRE POLYNOMIALS P(L,M) AT POINT XMU
*               FOR 0 <= L <= NANI (AND FOR 0 <= M <= L)
*     USING THE RECURENCE RELATIONS:
*     P(L+1,M)= ((2*L+1)*XMU*P(L,M)-(L+M)*P(L-1,M))/(L-M+1)
*     P(L,M+1)= 2*M*XMU*P(L,M)/SQRT(1-XMU**2)-(L+M)*(L-M+1)*P(L,M-1)
*
*     ESTABLISH SIMPLE CASES
      ALLOCATE(RWORK(NMU,(NANI+1)*(NANI+1)))
      IF( NANI.GE.0 )THEN
         DO 10 IMU= 1, NMU
            RWORK(IMU,IND(0,0))= DONE
   10    CONTINUE
      ELSE
         CALL XABORT('MOCCHR: THE FIRST ARGUMENT MUST NON NEGATIVE')
      ENDIF
*
      IF( NANI.GE.1 )THEN
         DPHI  = SIGN(ACOS(PHI1),PHI2)
         DO 40 IMU= 1, NMU
            DCOS=   DBLE(XMUANG(IMU))
            DSIN=   SQRT( DONE - DCOS  *DCOS   )
            RWORK(IMU,IND(1,-1))= DSIN*PHI2
            RWORK(IMU,IND(1, 0))= DCOS
            RWORK(IMU,IND(1, 1))= DSIN*PHI1
*
            IF( NANI.GE.2 )THEN
*              RECURENCE PLG(IND(L,0)),PLG(IND(L,1) FOR 2 <= L <= NANI
               DCOT= DCOS/DSIN
               DL00= DONE
               DL10= DCOS
               DL01= DZERO
               DL11= DSIN
               DO 30 L= 1, NANI-1
*                 IF M=1, L=L+1 THEN L+M=L+2, L-M+1=L+1
                  LPM=   L + 2
                  LMMP1= L + 1
                  DFAC= (DONE+DONE)/DBLE(LPM*LMMP1)
                  DM0=(DBLE(2*L+1)*DCOS*DL10 - DBLE(L)*DL00)/DBLE(L+1)
                  DM1=(DBLE(2*L+1)*DCOS*DL11 - DBLE(L+1)*DL01)/DBLE(L)
*                 ESTABLISH RELATIONS FOR L=L+1, ABS(M)<=1
                  RWORK(IMU,IND(L+1,-1))= SQRT(DFAC)*DM1*PHI2
                  RWORK(IMU,IND(L+1, 0))= DM0
                  RWORK(IMU,IND(L+1, 1))= SQRT(DFAC)*DM1*PHI1
                  DL00= DL10
                  DL01= DL11
                  DL10= DM0
                  DL11= DM1
*                 RECURENCE PLG(IND(L,M)) FOR 2 <= M <= L
                  DO 20 M= 1, L
*                    HERE DM0=PLG(L+1,0), DM1=PLG(L+1,1)
*                    ESTABLISH RELATIONS FOR L=L+1, ABS(M)>1
                     DFAC= DFAC/DBLE((LMMP1-1)*(LPM+1))
                     DCOP2= COS(DBLE(M+1)*DPHI)
                     DSIP2= SIN(DBLE(M+1)*DPHI)
                     DM2= DBLE(2*M)*DCOT*DM1 - DBLE(LPM*LMMP1)*DM0
                     RWORK(IMU,IND(L+1,-(M+1)))= SQRT(DFAC)*DM2*DSIP2
                     RWORK(IMU,IND(L+1, M+1 ))= SQRT(DFAC)*DM2*DCOP2
                     DM0= DM1
                     DM1= DM2
                     LPM=   LPM   + 1
                     LMMP1= LMMP1 - 1
   20             CONTINUE
   30          CONTINUE
            ENDIF
   40    CONTINUE
      ENDIF
*
***** SELECTS THE GOOD SPHERICAL HARMONICS RWORK(L,M) FUNCTIONS
*             FOR NDIM=1(SLAB),2(TWO-D RECT),3(THREE-D).
*     COMPRESSES RWORK INTO R.
*
      NSELEC= 0
      LROK= .FALSE.
      DO 80 L= 0, NANI
         DO 70 M= -L, L
            IF( NDIM.EQ.1 )THEN
               LROK= M.EQ.0
            ELSEIF( NDIM.EQ.2 )THEN
               LROK= MOD(L+M,2).EQ.0
            ELSEIF( NDIM.EQ.3 )THEN
               LROK= .TRUE.
            ENDIF
            IF( LROK )THEN
               NSELEC= NSELEC+1
               DO 50 IMU= 1, NMU
                  R(IMU,NSELEC)= REAL(RWORK(IMU,IND(L,M)))
   50          CONTINUE
            ENDIF
   70   CONTINUE
   80 CONTINUE
      IF(NSELEC.NE.NFUNL) CALL XABORT('MOCCHR: INVALID NSELEC')
      DEALLOCATE(RWORK)
*
      RETURN
      END