1 | SUBROUTINE PSVFCJ(DTT,TTHETA,SL,HL,SIG,GAM,PRFUNC,DPRDT,SLPART, |
---|
2 | 1 HLPART,SIGPART,GAMPART) |
---|
3 | |
---|
4 | !PURPOSE: Compute function & derivatives for Pseudovoigt profile |
---|
5 | ! [W.I.F.David (1986), J. Appl. Cryst. 19, 63-64 & |
---|
6 | ! P. Thompson, D.E. Cox & J.B. Hastings (1987) J. Appl. Cryst.,20,79-83.] |
---|
7 | ! Finger-Cox-Jephcoat (FCJ94) asymmetry correction |
---|
8 | ! [L.W. Finger, D.E. Cox & A.P. Jephcoat (1994) J. Appl. Cryst.,27,892-900.] |
---|
9 | ! coded 11/95 by B. H. Toby (NIST). revised version |
---|
10 | ! parameterized as asym1=S/L asym2=H/L |
---|
11 | |
---|
12 | |
---|
13 | INCLUDE 'INCLDS/COPYRIGT.FOR' |
---|
14 | |
---|
15 | !CALLING ARGUMENTS: |
---|
16 | |
---|
17 | REAL*4 DTT !delta 2-theta in centidegrees |
---|
18 | REAL*4 TTHETA !2-theta in centidegrees |
---|
19 | REAL*4 SL,HL !S/L & H/L |
---|
20 | REAL*4 SIG,GAM |
---|
21 | REAL*4 PRFUNC |
---|
22 | REAL*4 DPRDT |
---|
23 | REAL*4 SLPART,HLPART |
---|
24 | REAL*4 SIGPART,GAMPART |
---|
25 | |
---|
26 | !INCLUDE STATEMENTS: |
---|
27 | real*4 sind,cosd,tand,acosd |
---|
28 | |
---|
29 | !LOCAL VARIABLES: |
---|
30 | |
---|
31 | REAL*4 R ! pseudo-voight intensity |
---|
32 | REAL*4 DRDT ! deriv R w/r theta |
---|
33 | REAL*4 DRDS ! deriv R w/r sig |
---|
34 | REAL*4 DRDG ! deriv R w/r gam |
---|
35 | REAL*4 F |
---|
36 | REAL*4 G |
---|
37 | REAL*4 DFDA |
---|
38 | REAL*4 DGDA |
---|
39 | REAL*4 DGDB |
---|
40 | REAL*4 DYDA |
---|
41 | REAL*4 DYDB |
---|
42 | REAL*4 SIN2THETA2 ! sin(2theta)**2 |
---|
43 | REAL*4 COS2THETA ! cos(2theta) |
---|
44 | REAL*4 SIN2THETA ! sin(2THETA) |
---|
45 | REAL*4 SINDELTA ! sin(Delta) |
---|
46 | REAL*4 COSDELTA ! cos(Delta) |
---|
47 | REAL*4 RCOSDELTA ! 1/cos(Delta) |
---|
48 | REAL*4 TANDELTA ! tan(Delta) |
---|
49 | REAL*4 COSDELTA2 ! cos(Delta)**2 |
---|
50 | REAL*4 A ! asym1 [coff(7)] |
---|
51 | REAL*4 B ! asym2 [coff(8)] |
---|
52 | REAL*4 APB ! (A+B) |
---|
53 | REAL*4 AMB ! (A-B) |
---|
54 | REAL*4 APB2 ! (A+B)**2 |
---|
55 | REAL*4 TTHETAD ! Two Theta in degrees |
---|
56 | |
---|
57 | ! Intermediate variables |
---|
58 | |
---|
59 | REAL*4 RSUMWG2 ! 1.0/(sum of w G)**2 |
---|
60 | REAL*4 SUMWG ! sum of w G |
---|
61 | REAL*4 WG ! w G |
---|
62 | REAL*4 RSUMWG ! 1.0/sum of w G |
---|
63 | REAL*4 SUMWRG ! sum of w G |
---|
64 | REAL*4 SUMWDGDA ! sum of w dGdA |
---|
65 | REAL*4 SUMWRDGDA ! sum of w R dGdA |
---|
66 | REAL*4 SUMWDGDB ! sum of w dGdB |
---|
67 | REAL*4 SUMWRDGDB ! sum of w R dGdB |
---|
68 | REAL*4 SUMWGDRD2T ! sum of w G dRd(2theta) |
---|
69 | REAL*4 SUMWGDRDSIG ! sum of w G dRdp(n) |
---|
70 | REAL*4 SUMWGDRDGAM ! sum of w G dRdp(n) |
---|
71 | REAL*4 SUMWGDRDA |
---|
72 | REAL*4 SUMWGDRDB |
---|
73 | REAL*4 EMIN ! 2phi minimum |
---|
74 | REAL*4 EINFL ! 2phi of inflection point |
---|
75 | REAL*4 DEMINDA ! Derivative of Emin wrt A |
---|
76 | REAL*4 DELTA ! Angle of integration for convolution |
---|
77 | REAL*4 DDELTADA |
---|
78 | REAL*4 TMP,TMP1,TMP2 ! intermediates |
---|
79 | INTEGER*4 I,K,IT ! Miscellaneous loop variables |
---|
80 | c |
---|
81 | c Local Variables for Gaussian Integration |
---|
82 | c |
---|
83 | INTEGER*4 NGT !number of terms in Gaussian quadrature |
---|
84 | INTEGER*4 NUMTAB ! number of pre-computed Gaussian tables |
---|
85 | parameter (numtab=34) |
---|
86 | INTEGER*4 NTERMS(NUMTAB) ! number of terms in each table - must be even |
---|
87 | INTEGER*4 FSTTERM(NUMTAB) ! location of 1st term: N.B. N/2 terms |
---|
88 | LOGICAL*4 CALCLFG(NUMTAB) ! true if table has previously been calculated |
---|
89 | INTEGER*4 ARRAYNUM ! number of selected array |
---|
90 | INTEGER*4 ARRAYSIZE ! size of complete array |
---|
91 | parameter (arraysize=1670) |
---|
92 | REAL*4 XP(ARRAYSIZE) !Gaussian abscissas |
---|
93 | REAL*4 WP(ARRAYSIZE) !Gaussian weights |
---|
94 | REAL*4 XPT(400) !temporary Gaussian abscissas |
---|
95 | REAL*4 WPT(400) !temporary Gaussian weights |
---|
96 | REAL*4 STOFW |
---|
97 | PARAMETER (STOFW=2.35482005) |
---|
98 | REAL*4 TODEG |
---|
99 | PARAMETER (todeg=57.2957795) |
---|
100 | save calclfg,xp,wp !Values to be saved across calls |
---|
101 | |
---|
102 | !FUNCTION DEFINITIONS: |
---|
103 | |
---|
104 | !DATA STATEMENTS: |
---|
105 | |
---|
106 | DATA NTERMS ! number of terms in each table - must be even |
---|
107 | 1 /2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,40,50,60,70,80,90 ! Numbers of terms changed May 2004 |
---|
108 | 2 ,100,110,120,140,160,180,200,220,240,260,280,300,400/ |
---|
109 | C note that nterms determines both arraysize and fstterm |
---|
110 | DATA FSTTERM ! loc. of 1st term: N.B. N/2 terms are saved |
---|
111 | 1 /0,1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,140,165,195,230, !FSTERM(1) should be 0 - indexing starts at 1+this number! |
---|
112 | 2 270,315,365,420,480,550,630,720,820,930,1050,1180,1320,1470/ |
---|
113 | DATA calclfg/numtab*.false./ ! true if table entry has been calculated |
---|
114 | |
---|
115 | !CODE: |
---|
116 | |
---|
117 | c |
---|
118 | C f(2theta) intermediates |
---|
119 | c |
---|
120 | TTHETAD = 0.01 * TTHETA |
---|
121 | SIN2THETA = SIND(TTHETAD) |
---|
122 | cos2THETA = COSD(TTHETAD) |
---|
123 | sin2theta2 = sin2THETA * sin2THETA |
---|
124 | cos2THETA2 = cos2THETA * cos2THETA |
---|
125 | c |
---|
126 | C Asymmetry terms |
---|
127 | c |
---|
128 | A = SL ! A = S/L in FCJ |
---|
129 | B = HL ! B = H/L in FCJ |
---|
130 | ApB = A+B |
---|
131 | AmB = A-B |
---|
132 | ApB2 = ApB*ApB |
---|
133 | c |
---|
134 | C handle the case where there is asymmetry |
---|
135 | c |
---|
136 | IF (A .ne. 0.0 .or. B .ne. 0.0) then |
---|
137 | Einfl = Acosd(SQRT(1.0 + AmB**2)*cos2THETA) ! 2phi(infl) FCJ eq 5 (degrees) |
---|
138 | tmp2 = 1.0 + ApB2 |
---|
139 | tmp = SQRT(tmp2)*cos2THETA |
---|
140 | c |
---|
141 | C Treat case where A or B is zero - Set Einfl = 2theta |
---|
142 | c |
---|
143 | if (A.eq.0.0 .or. B .eq. 0.0)Einfl = Acosd(cos2THETA) |
---|
144 | if (abs(tmp) .le. 1.0) then |
---|
145 | Emin = Acosd(tmp) ! 2phi(min) FCJ eq 4 (degrees) |
---|
146 | tmp1 = tmp2*(1.0 - tmp2*(1.0-sin2THETA2)) |
---|
147 | else |
---|
148 | tmp1 = 0.0 |
---|
149 | if (tmp .gt. 0.0) then |
---|
150 | Emin = 0.0 |
---|
151 | else |
---|
152 | Emin = 180.0 |
---|
153 | endif |
---|
154 | endif |
---|
155 | if (tmp1 .gt. 0 .and. abs(tmp) .le. 1.0) then |
---|
156 | dEmindA = -ApB*cos2THETA/SQRT(tmp1) ! N. B. symm w/r A,B |
---|
157 | ELSE |
---|
158 | dEmindA = 0.0 |
---|
159 | ENDIF |
---|
160 | |
---|
161 | c |
---|
162 | c Compute Gaussian Quadrature interval |
---|
163 | C Note that the number of points must be large enough so that the |
---|
164 | c interval between 2phi(min) and 2theta must be divided into steps no |
---|
165 | c larger than 0.005 degrees. LWF 8/10/95 |
---|
166 | c |
---|
167 | c Determine which Gauss-Legendre Table to use |
---|
168 | c |
---|
169 | arraynum = 1 |
---|
170 | c |
---|
171 | c Calculate desired number of intervals |
---|
172 | c |
---|
173 | tmp = abs(TTHETAD - emin) ! tmp in degrees |
---|
174 | IF ( GAM.LE.0.0 ) THEN |
---|
175 | K = INT(TMP*200.0) !RVD formulation |
---|
176 | ELSE |
---|
177 | k = int(300.0*tmp/GAM) !New formulation of May 2004 |
---|
178 | END IF |
---|
179 | c |
---|
180 | C Find the next largest set |
---|
181 | c |
---|
182 | do while (arraynum .lt. numtab .and. k.gt.nterms(arraynum)) |
---|
183 | arraynum = arraynum + 1 |
---|
184 | enddo |
---|
185 | ngt = nterms(arraynum) |
---|
186 | c |
---|
187 | C calculate the terms, if they have not been used before |
---|
188 | c |
---|
189 | if (.not. calclfg(arraynum)) then |
---|
190 | calclfg(arraynum) = .true. |
---|
191 | call gauleg(-1.,1.,xpt,wpt,ngt) |
---|
192 | it = fstterm(arraynum)-ngt/2 |
---|
193 | c |
---|
194 | C copy the ngt/2 terms from our working array to the stored array |
---|
195 | c |
---|
196 | do k=ngt/2+1,ngt |
---|
197 | xp(k+it) = xpt(k) |
---|
198 | wp(k+it) = wpt(k) |
---|
199 | enddo |
---|
200 | endif |
---|
201 | sumWG = 0. |
---|
202 | sumWRG = 0. |
---|
203 | sumWdGdA = 0. |
---|
204 | sumWRdGdA = 0. |
---|
205 | sumWdGdB = 0. |
---|
206 | sumWRdGdB = 0. |
---|
207 | sumWGdRd2t = 0. |
---|
208 | sumWGdRdsig = 0. |
---|
209 | sumWGdRdgam = 0. |
---|
210 | sumWGdRdA = 0. |
---|
211 | sumWGdRdB = 0. |
---|
212 | c |
---|
213 | c Compute Convolution integral for 2phi(min) <= delta <= 2theta |
---|
214 | c |
---|
215 | it = fstterm(arraynum)-ngt/2 |
---|
216 | do k=ngt/2+1,ngt |
---|
217 | delta = emin + (TTHETAD - emin) * xp(k+it) ! Delta in degrees |
---|
218 | CALL PSVOIGT(DTT+TTHETA-delta*100.,SIG,GAM,R,dRdT,dRdS,dRdG) |
---|
219 | |
---|
220 | dDELTAdA = (1. - xp(k+it))*dEmindA ! N. B. symm w/r A,B |
---|
221 | sinDELTA = sind(Delta) |
---|
222 | cosDELTA = cosd(Delta) |
---|
223 | RcosDELTA = 1. / cosDELTA |
---|
224 | tanDELTA = tand(Delta) |
---|
225 | cosDELTA2 = cosDELTA*cosDELTA |
---|
226 | tmp1 = cosDELTA2 - cos2THETA2 |
---|
227 | tmp2 = sin2THETA2 - sinDelta * sinDELTA |
---|
228 | tmp = tmp2 |
---|
229 | if ( ttheta.gt.4500.0 ) tmp = tmp1 |
---|
230 | if (tmp .gt. 0) then |
---|
231 | tmp1 = 1.0/SQRT(tmp) |
---|
232 | F = abs(cos2THETA) * tmp1 |
---|
233 | dFdA = cosDELTA*cos2THETA*sinDELTA*dDELTAdA * |
---|
234 | 1 (tmp1*tmp1*tmp1) |
---|
235 | else |
---|
236 | F = 1.0 |
---|
237 | dFdA = 0.0 |
---|
238 | endif |
---|
239 | c |
---|
240 | c Calculate G(Delta,2theta) [G = W /(h cos(delta) ] [ FCJ eq. 7(a) and 7(b) ] |
---|
241 | c |
---|
242 | if(abs(delta-emin) .gt. abs(einfl-emin))then |
---|
243 | if ( A.ge.B) then |
---|
244 | c |
---|
245 | C N.B. this is the only place where d()/dA <> d()/dB |
---|
246 | c |
---|
247 | G = 2.0*B*F*RcosDELTA |
---|
248 | dGdA = 2.0*B*RcosDELTA*(dFdA + F*tanDELTA*dDELTAdA) |
---|
249 | dGdB = dGdA + 2.0*F*RcosDELTA |
---|
250 | else |
---|
251 | G = 2.0*A*F*RcosDELTA |
---|
252 | dGdB = 2.0*A*RcosDELTA*(dFdA + F*tanDELTA*dDELTAdA) |
---|
253 | dGdA = dGdB + 2.0*F*RcosDELTA |
---|
254 | endif |
---|
255 | else ! delta .le. einfl .or. min(A,B) .eq. 0 |
---|
256 | G = (-1.0 + ApB*F) * RcosDELTA |
---|
257 | dGdA = RcosDELTA*(F - tanDELTA*dDELTAdA |
---|
258 | 1 + ApB*F*tanDELTA*dDELTAdA + ApB*dFdA) |
---|
259 | dGdB = dGdA |
---|
260 | endif |
---|
261 | |
---|
262 | WG = wp(k+it) * G |
---|
263 | sumWG = sumWG + WG |
---|
264 | sumWRG = sumWRG + WG * R |
---|
265 | sumWdGdA = sumWdGdA + wp(k+it) * dGdA |
---|
266 | sumWRdGdA = sumWRdGdA + wp(k+it) * R * dGdA |
---|
267 | sumWdGdB = sumWdGdB + wp(k+it) * dGdB |
---|
268 | sumWRdGdB = sumWRdGdB + wp(k+it) * R * dGdB |
---|
269 | sumWGdRd2t = sumWGdRd2t + WG * dRdT ! N.B. 1/centidegrees |
---|
270 | sumWGdRdsig = sumWGdRdsig + WG * dRdS |
---|
271 | sumWGdRdgam = sumWGdRdgam + WG * dRdG |
---|
272 | sumWGdRdA = sumWGdRdA + WG * dRdT * dDELTAdA ! N. B. symm w/r A,B |
---|
273 | enddo |
---|
274 | RsumWG = 1.0/sumWG |
---|
275 | RsumWG2 = RsumWG * RsumWG |
---|
276 | PRFUNC = sumWRG * RsumWG |
---|
277 | |
---|
278 | dydA = (-(sumWRG*sumWdGdA) + |
---|
279 | 1 sumWG*(sumWRdGdA- 100.0 * todeg * sumWGdRdA)) * RsumWG2 |
---|
280 | dydB = (-(sumWRG*sumWdGdB) + |
---|
281 | 1 sumWG*(sumWRdGdB- 100.0 * todeg * sumWGdRdA)) * RsumWG2 |
---|
282 | sigpart = sumWGdRdsig * RsumWG |
---|
283 | gampart = sumWGdRdgam * RsumWG |
---|
284 | DPRDT = -SumWGdRd2T * RsumWG |
---|
285 | else |
---|
286 | c |
---|
287 | C no asymmetry -- nice and simple! |
---|
288 | c |
---|
289 | CALL PSVOIGT(DTT,SIG,GAM,R,dRdT,dRdS,dRdG) |
---|
290 | PRFUNC = R |
---|
291 | dydA = 0.002 * sign(1.0,TTHETA - DTT) |
---|
292 | dydB = dydA |
---|
293 | sigpart = dRdS |
---|
294 | gampart = dRdG |
---|
295 | DPRDT = -dRdT |
---|
296 | END IF |
---|
297 | SLPART = DYDA |
---|
298 | HLPART = DYDB |
---|
299 | |
---|
300 | RETURN |
---|
301 | END |
---|
302 | |
---|