scalefree 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- README.md +585 -0
- fortran_src/scalefree.f +3323 -0
- scalefree/__init__.py +12 -0
- scalefree/vmoments.py +837 -0
- scalefree-0.1.2.dist-info/METADATA +609 -0
- scalefree-0.1.2.dist-info/RECORD +8 -0
- scalefree-0.1.2.dist-info/WHEEL +4 -0
- scalefree-0.1.2.dist-info/entry_points.txt +0 -0
fortran_src/scalefree.f
ADDED
|
@@ -0,0 +1,3323 @@
|
|
|
1
|
+
PROGRAM FLATPOWER
|
|
2
|
+
C
|
|
3
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
4
|
+
C
|
|
5
|
+
C Scale-free dynamical modeling software as discussed in the file README.
|
|
6
|
+
C
|
|
7
|
+
C All routines are written in double precision. Note that this requires
|
|
8
|
+
C the statement IMPLICIT REAL*8 (a-h,o-z) at the beginning of each
|
|
9
|
+
C program part. Don't mix single and real precision ! This generally leads
|
|
10
|
+
C to disaster.
|
|
11
|
+
C
|
|
12
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
13
|
+
C
|
|
14
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
15
|
+
C
|
|
16
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
17
|
+
C
|
|
18
|
+
PARAMETER (pi=3.14159265358979D0)
|
|
19
|
+
C
|
|
20
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
21
|
+
C
|
|
22
|
+
DIMENSION xmom(0:100),darr(0:100),harr(0:100),
|
|
23
|
+
& velar(101),vpval(101)
|
|
24
|
+
CHARACTER*256 outpath
|
|
25
|
+
INTEGER iout
|
|
26
|
+
C
|
|
27
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
28
|
+
C
|
|
29
|
+
COMMON /potent/ ipot
|
|
30
|
+
C
|
|
31
|
+
C ipot=1 for Kepler potential and ipot=2 for logarithmic potential
|
|
32
|
+
C
|
|
33
|
+
COMMON /DFcase/ icase
|
|
34
|
+
C
|
|
35
|
+
C icase=1 for the case I DFs, icase=2 for the case II DFs.
|
|
36
|
+
C
|
|
37
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
38
|
+
C
|
|
39
|
+
C Model parameters
|
|
40
|
+
C
|
|
41
|
+
COMMON /viewing/ xinc
|
|
42
|
+
C
|
|
43
|
+
C The inclination angle in radians
|
|
44
|
+
C
|
|
45
|
+
COMMON /howint/ iint
|
|
46
|
+
C
|
|
47
|
+
C Determines how the line of sight integration is done
|
|
48
|
+
C
|
|
49
|
+
COMMON /romoeps/ eps
|
|
50
|
+
C
|
|
51
|
+
C fractional accuracy for Romberg integration
|
|
52
|
+
C
|
|
53
|
+
COMMON /gleg/ qx(300),qw(300),nGL
|
|
54
|
+
C
|
|
55
|
+
C Common block with Gauss-Legendre coefficients for integration along the
|
|
56
|
+
C line of sight.
|
|
57
|
+
C
|
|
58
|
+
COMMON /reg/ xlam
|
|
59
|
+
C
|
|
60
|
+
C Common block with the regularization parameter used in calculating VPs
|
|
61
|
+
C
|
|
62
|
+
COMMON /smoo/ epsmoo
|
|
63
|
+
C
|
|
64
|
+
C Parameter that determines the requested smoothness, as fraction of
|
|
65
|
+
C the VP maximum.
|
|
66
|
+
C
|
|
67
|
+
COMMON /verbose/ iverb
|
|
68
|
+
C
|
|
69
|
+
COMMON /projcase/ iproj
|
|
70
|
+
C
|
|
71
|
+
C iproj=1 (LOS), 2 (POSR), 3 (POST)
|
|
72
|
+
C
|
|
73
|
+
C
|
|
74
|
+
C Determines whether verbose output should be generated for VP calculations
|
|
75
|
+
C
|
|
76
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
77
|
+
C
|
|
78
|
+
C Get the model parameters
|
|
79
|
+
C
|
|
80
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
81
|
+
C
|
|
82
|
+
WRITE (*,*) 'Please answer the following questions about'
|
|
83
|
+
WRITE (*,*) 'the parameters of the model:'
|
|
84
|
+
WRITE (*,*) ' '
|
|
85
|
+
C
|
|
86
|
+
WRITE (*,*) 'Kepler (1) or Logarithmic (2) Potential ?'
|
|
87
|
+
READ (*,*) ipot
|
|
88
|
+
WRITE (*,*) ' '
|
|
89
|
+
C
|
|
90
|
+
WRITE (*,*) 'Power-law slope gamma of the mass density'
|
|
91
|
+
READ (*,*) gamma
|
|
92
|
+
WRITE (*,*) ' '
|
|
93
|
+
C
|
|
94
|
+
WRITE (*,*) 'Intrinsic axial ratio q of the mass density'
|
|
95
|
+
READ (*,*) q
|
|
96
|
+
WRITE (*,*) ' '
|
|
97
|
+
C
|
|
98
|
+
WRITE (*,*) 'Case I (1) or Case II (2) DF ?'
|
|
99
|
+
READ (*,*) icase
|
|
100
|
+
WRITE (*,*) ' '
|
|
101
|
+
C
|
|
102
|
+
WRITE (*,*) 'Anisotropy parameter beta of the DF'
|
|
103
|
+
READ (*,*) beta
|
|
104
|
+
WRITE (*,*) ' '
|
|
105
|
+
C
|
|
106
|
+
C The parameters s and t of the odd part of the DF are called
|
|
107
|
+
C eta and alpha in the coding convention of this program.
|
|
108
|
+
C
|
|
109
|
+
WRITE (*,*) 'Odd part parameters s and t for the DF'
|
|
110
|
+
READ (*,*) eta, alpha
|
|
111
|
+
WRITE (*,*) ' '
|
|
112
|
+
C
|
|
113
|
+
WRITE (*,*) 'Viewing inclination i in degrees (90=edge-on)'
|
|
114
|
+
READ (*,*) xinc
|
|
115
|
+
WRITE (*,*) ' '
|
|
116
|
+
C
|
|
117
|
+
C Transform the inclination to radians
|
|
118
|
+
C
|
|
119
|
+
xinc = (xinc/180.0D0)*pi
|
|
120
|
+
C
|
|
121
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
122
|
+
C
|
|
123
|
+
C Get information on numerical details
|
|
124
|
+
C
|
|
125
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
126
|
+
C
|
|
127
|
+
WRITE (*,*) 'Please answer the following questions about'
|
|
128
|
+
WRITE (*,*) 'the numerical details of the calculations:'
|
|
129
|
+
WRITE (*,*) ' '
|
|
130
|
+
C
|
|
131
|
+
WRITE (*,*) 'Use Romberg (0) or Gauss-Legendre (1) integration'
|
|
132
|
+
WRITE (*,*) 'for line-of-sight projection and integration over'
|
|
133
|
+
WRITE (*,*) 'the meridional or sky plane? (default=1)'
|
|
134
|
+
READ (*,*) iint
|
|
135
|
+
WRITE (*,*) ' '
|
|
136
|
+
C
|
|
137
|
+
IF (iint.EQ.0) THEN
|
|
138
|
+
WRITE (*,*) 'Give the fractional accuracy epsilon (0.0=default)'
|
|
139
|
+
READ (*,*) eps
|
|
140
|
+
WRITE (*,*) ' '
|
|
141
|
+
IF (eps.EQ.0.0D0) eps = 1.0D-7
|
|
142
|
+
ELSE
|
|
143
|
+
WRITE (*,*) 'Give number of quadrature points (0=default)'
|
|
144
|
+
READ (*,*) nGL
|
|
145
|
+
WRITE (*,*) ' '
|
|
146
|
+
IF (nGL.EQ.0) nGL = 100
|
|
147
|
+
CALL GAULEG (0.0D0,1.0D0,qx,qw,nGL)
|
|
148
|
+
END IF
|
|
149
|
+
C
|
|
150
|
+
WRITE (*,*) 'Algorithm to calculate VPs and Gauss-Hermite moments'
|
|
151
|
+
WRITE (*,*) ' 1: Solve VanderMonde matrix directly without'
|
|
152
|
+
WRITE (*,*) ' regularization. Resulting VP will be nonsense'
|
|
153
|
+
WRITE (*,*) ' but the GH moments are generally well'
|
|
154
|
+
WRITE (*,*) ' determined.'
|
|
155
|
+
WRITE (*,*) ' 2: Use regularization with a fixed regularization'
|
|
156
|
+
WRITE (*,*) ' parameter.'
|
|
157
|
+
WRITE (*,*) ' 3: Use regularization. Increase regularization'
|
|
158
|
+
WRITE (*,*) ' parameter until the VP has no more than 3'
|
|
159
|
+
WRITE (*,*) ' significant local maxima. A local maximum is'
|
|
160
|
+
WRITE (*,*) ' significant if it exceeds the value of its'
|
|
161
|
+
WRITE (*,*) ' neighbors on the grid by eps times the'
|
|
162
|
+
WRITE (*,*) ' absolute VP maximum.'
|
|
163
|
+
WRITE (*,*) 'Choose 1 for default.'
|
|
164
|
+
READ (*,*) iVPfit
|
|
165
|
+
WRITE (*,*) ' '
|
|
166
|
+
C
|
|
167
|
+
IF (iVPfit.EQ.1) THEN
|
|
168
|
+
C
|
|
169
|
+
xlam = -1.0
|
|
170
|
+
C
|
|
171
|
+
WRITE (*,*) 'Give the maximum number of projected moments'
|
|
172
|
+
WRITE (*,*) 'to use (should be an even number)'
|
|
173
|
+
WRITE (*,*) '(0 yields default)'
|
|
174
|
+
READ (*,*) maxord
|
|
175
|
+
WRITE (*,*) ' '
|
|
176
|
+
C
|
|
177
|
+
ELSE IF (iVPfit.EQ.2) THEN
|
|
178
|
+
C
|
|
179
|
+
WRITE (*,*) 'Give the regularization parameter (> 0)'
|
|
180
|
+
READ (*,*) xlam
|
|
181
|
+
WRITE (*,*) ' '
|
|
182
|
+
C
|
|
183
|
+
WRITE (*,*) 'Give the number of projected moments'
|
|
184
|
+
WRITE (*,*) 'to use (should be an even number)'
|
|
185
|
+
WRITE (*,*) '(0 yields default)'
|
|
186
|
+
READ (*,*) maxord
|
|
187
|
+
WRITE (*,*) ' '
|
|
188
|
+
C
|
|
189
|
+
ELSE IF (iVPfit.EQ.3) THEN
|
|
190
|
+
C
|
|
191
|
+
xlam = 0.0
|
|
192
|
+
C
|
|
193
|
+
WRITE (*,*) 'Give smoothness factor eps (0.0 yields default)'
|
|
194
|
+
READ (*,*) epsmoo
|
|
195
|
+
WRITE (*,*) ' '
|
|
196
|
+
C
|
|
197
|
+
IF (epsmoo.EQ.0.0) epsmoo = 1.0D-3
|
|
198
|
+
|
|
199
|
+
WRITE (*,*) 'Give the number of projected moments'
|
|
200
|
+
WRITE (*,*) 'to use (should be an even number)'
|
|
201
|
+
WRITE (*,*) '(0 yields default)'
|
|
202
|
+
READ (*,*) maxord
|
|
203
|
+
WRITE (*,*) ' '
|
|
204
|
+
C
|
|
205
|
+
ELSE
|
|
206
|
+
C
|
|
207
|
+
STOP 'Wrong answer'
|
|
208
|
+
C
|
|
209
|
+
END IF
|
|
210
|
+
C
|
|
211
|
+
IF (maxord.EQ.0) maxord = 30
|
|
212
|
+
C
|
|
213
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
214
|
+
C
|
|
215
|
+
C Fill the arrays with the coefficients of the power series that yield
|
|
216
|
+
C the intrinsic velocity moments.
|
|
217
|
+
C
|
|
218
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
219
|
+
C
|
|
220
|
+
WRITE (*,*) 'Calculating all series coefficients up to'
|
|
221
|
+
WRITE (*,*) 'the selected (maximum) order ........'
|
|
222
|
+
CALL FILLARRAYS(maxord)
|
|
223
|
+
WRITE (*,*) ' '
|
|
224
|
+
C
|
|
225
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
226
|
+
C
|
|
227
|
+
C Now calculate anything that the user may be interested in
|
|
228
|
+
C
|
|
229
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
230
|
+
C
|
|
231
|
+
C
|
|
232
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
233
|
+
C
|
|
234
|
+
C Select where to write numerical results (table output)
|
|
235
|
+
C
|
|
236
|
+
iproj = 1
|
|
237
|
+
WRITE (*,*) 'Output file for results (blank = STDOUT)'
|
|
238
|
+
READ (*,'(A)') outpath
|
|
239
|
+
lout = LENSTR(outpath)
|
|
240
|
+
IF (lout.GT.0) THEN
|
|
241
|
+
iout = 20
|
|
242
|
+
OPEN(unit=iout,file=outpath(1:lout),status='unknown')
|
|
243
|
+
ELSE
|
|
244
|
+
iout = 6
|
|
245
|
+
END IF
|
|
246
|
+
WRITE (*,*) ' '
|
|
247
|
+
C
|
|
248
|
+
51 WRITE (*,*) 'Calculate intrinsic (0) or projected (1)'
|
|
249
|
+
WRITE (*,*) 'kinematical quantities ?'
|
|
250
|
+
WRITE (*,*) 'This gives results for a fixed angle in the'
|
|
251
|
+
WRITE (*,*) 'meridional or projected plane.'
|
|
252
|
+
WRITE (*,*) 'Instead, add 2 to get results mass-weighted'
|
|
253
|
+
WRITE (*,*) 'over angles between 0 and pi/2'
|
|
254
|
+
READ (*,*) iwhat
|
|
255
|
+
WRITE (*,*) ' '
|
|
256
|
+
C
|
|
257
|
+
WRITE (*,*) 'Note: all results are at an'
|
|
258
|
+
WRITE (*,*) '(intrinsic or projected) radius of 1 in'
|
|
259
|
+
WRITE (*,*) 'dimensionless units. Results can be scaled to other'
|
|
260
|
+
WRITE (*,*) 'radii using the scale-free nature of the models.'
|
|
261
|
+
WRITE (*,*) ' '
|
|
262
|
+
C
|
|
263
|
+
IF (iwhat.EQ.0) THEN
|
|
264
|
+
C
|
|
265
|
+
WRITE (*,*) 'Give angle theta in the meridional plane'
|
|
266
|
+
WRITE (*,*) '(in degrees) (0 = symmetry axis)'
|
|
267
|
+
READ (*,*) theta
|
|
268
|
+
WRITE (*,*) ' '
|
|
269
|
+
C
|
|
270
|
+
C Transform to radians
|
|
271
|
+
C
|
|
272
|
+
theta = (theta/180.0D0)*pi
|
|
273
|
+
rho = RHOVELMOM(theta,0,0,0)
|
|
274
|
+
C
|
|
275
|
+
WRITE (*,*) 'Intrinsic velocity moments:'
|
|
276
|
+
WRITE (*,'(5A12)') 'rho','<v_ph>','<v_r^2>','<v_th^2>',
|
|
277
|
+
& '<v_ph^2>'
|
|
278
|
+
WRITE (*,'(6F12.8)') rho,RHOVELMOM(theta,0,0,1)/rho,
|
|
279
|
+
& RHOVELMOM(theta,2,0,0)/rho,
|
|
280
|
+
& RHOVELMOM(theta,0,2,0)/rho,
|
|
281
|
+
& RHOVELMOM(theta,0,0,2)/rho
|
|
282
|
+
WRITE (*,*) ' '
|
|
283
|
+
C
|
|
284
|
+
ELSE IF (iwhat.EQ.2) THEN
|
|
285
|
+
C
|
|
286
|
+
rho = RHOVELMOMTHAV(0,0,0)
|
|
287
|
+
rhop1 = RHOVELMOMTHAV(0,0,1)
|
|
288
|
+
rhor2 = RHOVELMOMTHAV(2,0,0)
|
|
289
|
+
rhot2 = RHOVELMOMTHAV(0,2,0)
|
|
290
|
+
rhop2 = RHOVELMOMTHAV(0,0,2)
|
|
291
|
+
betav = 1.0D0 - ((rhot2+rhop2)/(2.0D0*rhor2))
|
|
292
|
+
C
|
|
293
|
+
WRITE (*,*) 'Intrinsic velocity moments:'
|
|
294
|
+
WRITE (*,*) 'Mass-weighted average spherical shell:'
|
|
295
|
+
WRITE (*,'(6A12)') 'rho','<v_ph>','<v_r^2>','<v_th^2>',
|
|
296
|
+
& '<v_ph^2>','beta'
|
|
297
|
+
WRITE (*,'(6F12.8)') rho, rhop1/rho,
|
|
298
|
+
& rhor2/rho, rhot2/rho, rhop2/rho, betav
|
|
299
|
+
WRITE (*,*) ' '
|
|
300
|
+
C
|
|
301
|
+
ELSE IF (iwhat.EQ.1) THEN
|
|
302
|
+
C
|
|
303
|
+
WRITE (*,*) 'Give angle on the projected plane'
|
|
304
|
+
WRITE (*,*) '(in degrees) (0 = major axis)'
|
|
305
|
+
READ (*,*) xi
|
|
306
|
+
WRITE (*,*) ' '
|
|
307
|
+
C
|
|
308
|
+
C Transform to radians
|
|
309
|
+
C
|
|
310
|
+
xi = (xi/180.0D0)*pi
|
|
311
|
+
C
|
|
312
|
+
rhop = RHOPROJ(xi)
|
|
313
|
+
WRITE (iout,'(A)') '# kind=projected_point'
|
|
314
|
+
WRITE (iout,'(A,F16.8)') '# xi_deg ', (xi*180.0D0/pi)
|
|
315
|
+
WRITE (iout,'(A)') '# columns: iproj rho_p v1 v2 v3 v4'
|
|
316
|
+
DO iproj=1,3
|
|
317
|
+
v1 = PROJMOM(xi,1)
|
|
318
|
+
v2 = PROJMOM(xi,2)
|
|
319
|
+
v3 = PROJMOM(xi,3)
|
|
320
|
+
v4 = PROJMOM(xi,4)
|
|
321
|
+
WRITE (iout,'(I3,1X,5E24.16)') iproj, rhop, v1, v2, v3, v4
|
|
322
|
+
END DO
|
|
323
|
+
WRITE (iout,*) ' '
|
|
324
|
+
C
|
|
325
|
+
ELSE IF (iwhat.EQ.3) THEN
|
|
326
|
+
C
|
|
327
|
+
rhop0 = RHOPROJMOMAV(0)
|
|
328
|
+
rhop1 = RHOPROJMOMAV(1)
|
|
329
|
+
rhop2 = RHOPROJMOMAV(2)
|
|
330
|
+
rhop3 = RHOPROJMOMAV(3)
|
|
331
|
+
rhop4 = RHOPROJMOMAV(4)
|
|
332
|
+
C
|
|
333
|
+
WRITE (iout,'(A)') '# kind=projected_circle_average'
|
|
334
|
+
WRITE (iout,'(A)') '# columns: iproj rho_p v1 v2 v3 v4'
|
|
335
|
+
DO iproj=1,3
|
|
336
|
+
rhop0 = RHOPROJMOMAV(0)
|
|
337
|
+
rhop1 = RHOPROJMOMAV(1)
|
|
338
|
+
rhop2 = RHOPROJMOMAV(2)
|
|
339
|
+
rhop3 = RHOPROJMOMAV(3)
|
|
340
|
+
rhop4 = RHOPROJMOMAV(4)
|
|
341
|
+
WRITE (iout,'(I3,1X,5E24.16)') iproj, rhop0, rhop1/rhop0,
|
|
342
|
+
& rhop2/rhop0, rhop3/rhop0, rhop4/rhop0
|
|
343
|
+
END DO
|
|
344
|
+
WRITE (iout,*) ' '
|
|
345
|
+
C
|
|
346
|
+
ELSE
|
|
347
|
+
C
|
|
348
|
+
STOP 'Wrong answer'
|
|
349
|
+
C
|
|
350
|
+
END IF
|
|
351
|
+
C
|
|
352
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
353
|
+
C
|
|
354
|
+
C If iwhat=1 or 3, then calculate and write also VP information
|
|
355
|
+
C
|
|
356
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
357
|
+
C
|
|
358
|
+
IF ((iwhat.EQ.1).OR.(iwhat.EQ.3)) THEN
|
|
359
|
+
C
|
|
360
|
+
C Set the number of GH moments to calculate
|
|
361
|
+
C
|
|
362
|
+
nord = 6
|
|
363
|
+
C
|
|
364
|
+
C Verbose ?
|
|
365
|
+
C
|
|
366
|
+
WRITE (*,*) 'Give verbose output of intermediate steps'
|
|
367
|
+
WRITE (*,*) 'for VP calculation ? (0/1)'
|
|
368
|
+
READ (*,*) iverb
|
|
369
|
+
WRITE (*,*) ' '
|
|
370
|
+
C
|
|
371
|
+
C Calculate the VP and VP coefficients for all projected components
|
|
372
|
+
C
|
|
373
|
+
WRITE (iout,'(A)') '# kind=vp'
|
|
374
|
+
WRITE (iout,'(A)') '# columns: iproj true_gam true_V true_sig'
|
|
375
|
+
WRITE (iout,'(A)') '# gauss_gam gauss_V gauss_sig'
|
|
376
|
+
WRITE (iout,'(A)') '# h0 h1 h2 h3 h4 h5 h6'
|
|
377
|
+
|
|
378
|
+
DO iproj=1,3
|
|
379
|
+
IF (xlam.LT.0.0) THEN
|
|
380
|
+
CALL VPANALYSE_CONV (iwhat,xi,nord,xmom,gam0,V0,sig0,darr,
|
|
381
|
+
& velar,vpval,nvel,gam,Vgau,sig,harr)
|
|
382
|
+
ELSE
|
|
383
|
+
CALL VPANALYSE_FIX (iwhat,xi,maxord,xmom,gam0,V0,sig0,darr,
|
|
384
|
+
& velar,vpval,nvel,gam,Vgau,sig,harr)
|
|
385
|
+
END IF
|
|
386
|
+
C
|
|
387
|
+
WRITE (iout,'(I3,1X,6E24.16,1X,7F10.5)') iproj, gam0, V0, sig0,
|
|
388
|
+
& gam, Vgau, sig, harr(0), harr(1), harr(2), harr(3),
|
|
389
|
+
& harr(4), harr(5), harr(6)
|
|
390
|
+
C
|
|
391
|
+
C Write the VP solution as a table block (v, VP)
|
|
392
|
+
C
|
|
393
|
+
WRITE (iout,'(A,I3)') '# vp_table iproj ', iproj
|
|
394
|
+
WRITE (iout,'(A)') '# columns: v vp'
|
|
395
|
+
DO j=1,nvel
|
|
396
|
+
WRITE (iout,'(2E24.16)') velar(j), vpval(j)
|
|
397
|
+
END DO
|
|
398
|
+
WRITE (iout,*) ' '
|
|
399
|
+
END DO
|
|
400
|
+
C
|
|
401
|
+
END IF
|
|
402
|
+
C
|
|
403
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
404
|
+
C
|
|
405
|
+
C Continue ?
|
|
406
|
+
C
|
|
407
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
408
|
+
C
|
|
409
|
+
WRITE (*,*) 'Calculate something else for this model ? (0/1)'
|
|
410
|
+
READ (*,*) imore
|
|
411
|
+
WRITE (*,*) ' '
|
|
412
|
+
C
|
|
413
|
+
IF (imore.EQ.1) GOTO 51
|
|
414
|
+
C
|
|
415
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
416
|
+
C
|
|
417
|
+
C End of program
|
|
418
|
+
C
|
|
419
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
420
|
+
C
|
|
421
|
+
END
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
SUBROUTINE FILLARRAYS (maxxord)
|
|
425
|
+
C
|
|
426
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
427
|
+
C
|
|
428
|
+
C Fill the arrays with the coefficients of the power series that yield
|
|
429
|
+
C the intrinsic velocity moments. It is assumed that moments up to order
|
|
430
|
+
C maxxord are required. After this subroutine has been called,
|
|
431
|
+
C the subroutines COFARR and KMAXARR can be used to recover the coefficients,
|
|
432
|
+
C without having to calculate them again.
|
|
433
|
+
C
|
|
434
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
435
|
+
C
|
|
436
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
437
|
+
C
|
|
438
|
+
PARAMETER (maxlength = 2000000 ,
|
|
439
|
+
& mord = 200 ,
|
|
440
|
+
& mev = mord/2 )
|
|
441
|
+
C
|
|
442
|
+
COMMON /all/ allcofs(1:maxlength),
|
|
443
|
+
& icstart(0:mev,0:mev,0:mord),
|
|
444
|
+
& kmaxall(0:mev,0:mev,0:mord), maxord
|
|
445
|
+
C
|
|
446
|
+
DIMENSION cofs(0:1000)
|
|
447
|
+
C
|
|
448
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
449
|
+
C
|
|
450
|
+
maxord = maxxord
|
|
451
|
+
C
|
|
452
|
+
IF (2*(maxord/2).NE.maxord) STOP 'maxord should be even'
|
|
453
|
+
IF (maxord.GT.mord) STOP 'maxord is too large for array'
|
|
454
|
+
C
|
|
455
|
+
C Fill the array which holds all the coefficients of the power series
|
|
456
|
+
C in e^2 SIN^2(theta), required to calculate the intrinsic velocity
|
|
457
|
+
C moments up to order maxord.
|
|
458
|
+
C
|
|
459
|
+
C WRITE (*,*)
|
|
460
|
+
C & 'Calculating series coefficients for the velocity moments ...'
|
|
461
|
+
C
|
|
462
|
+
ic = 1
|
|
463
|
+
DO ir=0,maxord,2
|
|
464
|
+
DO ith=0,maxord,2
|
|
465
|
+
DO iph=0,maxord
|
|
466
|
+
icstart(ir/2,ith/2,iph) = ic
|
|
467
|
+
CALL CALCCOEFFLN(cofs,kmax,ir,ith,iph)
|
|
468
|
+
kmaxall(ir/2,ith/2,iph) = kmax
|
|
469
|
+
DO k=0,kmax
|
|
470
|
+
allcofs(ic) = cofs(k)
|
|
471
|
+
ic = ic+1
|
|
472
|
+
END DO
|
|
473
|
+
IF (ic.GE.maxlength) STOP 'ic too large for array'
|
|
474
|
+
END DO
|
|
475
|
+
END DO
|
|
476
|
+
C WRITE (*,'(2I5,I10)') ir,maxord,ic-1
|
|
477
|
+
END DO
|
|
478
|
+
C WRITE (*,*) ' '
|
|
479
|
+
C
|
|
480
|
+
END
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
484
|
+
C
|
|
485
|
+
C The function SPHPROJMOM calculatates the results for spherical non-rotating
|
|
486
|
+
C models using the results of van der Marel & Franx, for the purpose of testing
|
|
487
|
+
C only.
|
|
488
|
+
C
|
|
489
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
490
|
+
|
|
491
|
+
REAL*8 FUNCTION SPHPROJMOM(nord)
|
|
492
|
+
C
|
|
493
|
+
C Calculate the projected moment of order nord at projected radius 1
|
|
494
|
+
C (in dimensionless units), using equation (B6a) or (B8a) of van der Marel
|
|
495
|
+
C & Franx (modified to correspond to the units used here).
|
|
496
|
+
C Useful for the purpose of testing.
|
|
497
|
+
C
|
|
498
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
499
|
+
C
|
|
500
|
+
COMMON /potent/ ipot
|
|
501
|
+
C
|
|
502
|
+
C ipot=1 for Kepler potential and ipot=2 for logarithmic potential
|
|
503
|
+
C
|
|
504
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
505
|
+
C
|
|
506
|
+
IF (2*(nord/2).NE.nord) STOP 'No vdM & F result for odd order'
|
|
507
|
+
C
|
|
508
|
+
no2 = nord/2
|
|
509
|
+
dnord = DBLE(nord)
|
|
510
|
+
dno2 = DBLE(no2)
|
|
511
|
+
C
|
|
512
|
+
sum = 0.0D0
|
|
513
|
+
DO k=0,no2
|
|
514
|
+
dk = DBLE(k)
|
|
515
|
+
facln = binomln(nord,2*k) +
|
|
516
|
+
& betaln(dno2-dk+0.5D0,0.5D0) - betaln(0.5D0,0.5D0) +
|
|
517
|
+
& betaln(dk+0.5D0,dno2-dk+1.0D0-beta) -
|
|
518
|
+
& betaln(0.5D0,1.0D0-beta) +
|
|
519
|
+
& gammaln(dno2+1.5D0-beta) - gammaln(1.5D0-beta)
|
|
520
|
+
IF (ipot.EQ.1) THEN
|
|
521
|
+
facln = facln +
|
|
522
|
+
& betaln(0.5D0*(gamma-1.0D0+dno2+dnord-(2.0D0*dk)),
|
|
523
|
+
& dk+0.5D0) - betaln(0.5D0*(gamma-1.0D0),0.5D0) +
|
|
524
|
+
& gammaln(gamma-(2.0D0*beta)+1.0D0) -
|
|
525
|
+
& gammaln(gamma+dno2-(2.0D0*beta)+1.0D0)
|
|
526
|
+
ELSE IF (ipot.EQ.2) THEN
|
|
527
|
+
facln = facln +
|
|
528
|
+
& betaln(0.5D0*(gamma-1.0D0+dnord-(2.0D0*dk)),
|
|
529
|
+
& dk+0.5D0) - betaln(0.5D0*(gamma-1.0D0),0.5D0) -
|
|
530
|
+
& (dno2*LOG(gamma-(2.0D0*beta)))
|
|
531
|
+
ELSE
|
|
532
|
+
STOP 'ipot wrong value'
|
|
533
|
+
END IF
|
|
534
|
+
sum = sum + EXPP(facln)
|
|
535
|
+
END DO
|
|
536
|
+
C
|
|
537
|
+
SPHPROJMOM = sum
|
|
538
|
+
C
|
|
539
|
+
END
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
543
|
+
C
|
|
544
|
+
C The subroutines VPANALYSE_* calculate properties of the VPs on the sky.
|
|
545
|
+
C They call FINDVP, which calculates the VP by solution of a
|
|
546
|
+
C (regularized) VanderMonde matrix, calculates the best fitting Gaussian by
|
|
547
|
+
C means of FITGAUSS and CHI2H, and calculates the Gauss-Hermite coefficients
|
|
548
|
+
C by means of GAUHERM. The routine GRAMCHARCOF calculates the
|
|
549
|
+
C coefficients of the Gram-Charlier series.
|
|
550
|
+
C
|
|
551
|
+
C VPANALYSE_FIX : uses a fixed number of projected moments.
|
|
552
|
+
C Can be used if the regularization is sufficient.
|
|
553
|
+
C VPANALYSE_CONV : Adds more or less projected momemnts until some
|
|
554
|
+
C sort of convergence is achieved. Works reasonable
|
|
555
|
+
C without regularization. The returned VP is nonsense,
|
|
556
|
+
C but the GH coefficients are reasonably OK.
|
|
557
|
+
C
|
|
558
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
SUBROUTINE VPANALYSE_FIX (iwhat,xi,nord,xmom,gam0,V0,sig0,darr,
|
|
562
|
+
& velar,vpval,nvel,gam,Vgau,sig,harr)
|
|
563
|
+
C
|
|
564
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
565
|
+
C
|
|
566
|
+
C If iwhat=1, then do calculations at a given an angle xi from the major axis.
|
|
567
|
+
C If iwhat=3, then integrated over all angles in the first sky quadrant.
|
|
568
|
+
C In either case, calculate at projected radius 1
|
|
569
|
+
C (in dimensionless units), given an integer nord:
|
|
570
|
+
C - the first nord projected moments, returned in xmom
|
|
571
|
+
C - the lowest order true moments (gam0,V0,sig0)
|
|
572
|
+
C - the first nord Gram-Charlier coefficients, returned in darr
|
|
573
|
+
C - the velocity profile, approximated at nord discrete velocities velar,
|
|
574
|
+
C returned in vpval
|
|
575
|
+
C - the parameters (gam,Vgau,sig) of the best fitting Gaussian
|
|
576
|
+
C - the first nord Gauss-Hermite moments, returned in harr.
|
|
577
|
+
C
|
|
578
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
579
|
+
C
|
|
580
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
581
|
+
C
|
|
582
|
+
PARAMETER (maxlength = 2000000 ,
|
|
583
|
+
& mord = 200 ,
|
|
584
|
+
& mev = mord/2 )
|
|
585
|
+
C
|
|
586
|
+
DIMENSION xmom(0:100),darr(0:100),velar(101),vpval(101),
|
|
587
|
+
& harr(0:100)
|
|
588
|
+
C
|
|
589
|
+
COMMON /all/ allcofs(1:maxlength),
|
|
590
|
+
& icstart(0:mev,0:mev,0:mord),
|
|
591
|
+
& kmaxall(0:mev,0:mev,0:mord), maxord
|
|
592
|
+
C
|
|
593
|
+
COMMON /potent/ ipot
|
|
594
|
+
C
|
|
595
|
+
C ipot=1 for Kepler potential and ipot=2 for logarithmic potential
|
|
596
|
+
C
|
|
597
|
+
COMMON /verbose/ iverb
|
|
598
|
+
C
|
|
599
|
+
C Determines whether verbose output should be generated for VP calculations
|
|
600
|
+
C
|
|
601
|
+
CCCCCCCCC
|
|
602
|
+
C
|
|
603
|
+
C Set nord to the nearest even integer
|
|
604
|
+
C
|
|
605
|
+
nordin = nord
|
|
606
|
+
IF (2*(nord/2).NE.nord) nord=nord-1
|
|
607
|
+
C
|
|
608
|
+
C Calculate the projected velocity moments
|
|
609
|
+
C
|
|
610
|
+
IF (iverb.EQ.1) THEN
|
|
611
|
+
WRITE (*,*) 'Calculating first', nord,
|
|
612
|
+
& ' projected velocity moments ...'
|
|
613
|
+
WRITE (*,*) ' '
|
|
614
|
+
END IF
|
|
615
|
+
C
|
|
616
|
+
rhopr0 = RHOPROJMOMAV(0)
|
|
617
|
+
DO i=0,nord
|
|
618
|
+
IF (iwhat.EQ.1) THEN
|
|
619
|
+
xmom(i) = PROJMOM(xi,i)
|
|
620
|
+
ELSE IF (iwhat.EQ.3) THEN
|
|
621
|
+
xmom(i) = RHOPROJMOMAV(i) / rhopr0
|
|
622
|
+
END IF
|
|
623
|
+
END DO
|
|
624
|
+
C
|
|
625
|
+
C Calculate the normalization, mean and dispersion
|
|
626
|
+
C
|
|
627
|
+
gam0 = xmom(0)
|
|
628
|
+
V0 = xmom(1)
|
|
629
|
+
sig0 = SQRT(xmom(2)-(xmom(1)**2.0D0))
|
|
630
|
+
C
|
|
631
|
+
C Set initial values for the best fitting Gaussian
|
|
632
|
+
C
|
|
633
|
+
gam = gam0 - (gam0*darr(4)*SQRT(24.0D0)/32.0D0)
|
|
634
|
+
Vgau = V0 - (sig0*darr(3)*SQRT(6.0D0)/4.0D0)
|
|
635
|
+
sig = sig0 - (sig0*darr(4)*SQRT(24.0D0)/8.0D0)
|
|
636
|
+
C
|
|
637
|
+
C Calculate the VP, best fitting Gaussian, and Gauss-Hermite coefficients.
|
|
638
|
+
C
|
|
639
|
+
CALL FINDVP (nord,xmom,velar,vpval,nvel,gam,Vgau,sig,harr)
|
|
640
|
+
C
|
|
641
|
+
C Write the resulting VP to the screen
|
|
642
|
+
C
|
|
643
|
+
IF (iverb.EQ.1) THEN
|
|
644
|
+
C WRITE (*,'(A31,I3,A9)')
|
|
645
|
+
C & 'VP reconstructed from the first',nord,'moments:'
|
|
646
|
+
C DO i=1,nvel
|
|
647
|
+
C WRITE (*,'(I5,2F20.8)') i,velar(i),vpval(i)
|
|
648
|
+
C END DO
|
|
649
|
+
C WRITE (*,*) ' '
|
|
650
|
+
END IF
|
|
651
|
+
C
|
|
652
|
+
C Calculate the Gram-Charlier coefficients
|
|
653
|
+
C
|
|
654
|
+
CALL GRAMCHARCOF (xmom,nord,V0,sig0,darr)
|
|
655
|
+
C
|
|
656
|
+
C Reset nord to its input value
|
|
657
|
+
C
|
|
658
|
+
nord = nordin
|
|
659
|
+
C
|
|
660
|
+
END
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
SUBROUTINE VPANALYSE_CONV (iwhat,xi,nord,xmom,gam0,V0,sig0,darr,
|
|
664
|
+
& velar,vpval,nvel,gam,Vgau,sig,harr)
|
|
665
|
+
C
|
|
666
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
667
|
+
C
|
|
668
|
+
C If iwhat=1, then do calculations at a given an angle xi from the major axis.
|
|
669
|
+
C If iwhat=3, then integrated over all angles in the first sky quadrant.
|
|
670
|
+
C In either case, calculate at projected radius 1
|
|
671
|
+
C (in dimensionless units), given an integer nord:
|
|
672
|
+
C - the first nord or more projected moments, returned in xmom
|
|
673
|
+
C - the lowest order true moments (gam0,V0,sig0)
|
|
674
|
+
C - the first nord or more Gram-Charlier coefficients, returned in darr
|
|
675
|
+
C - the velocity profile, approximated at nvel discrete velocities velar,
|
|
676
|
+
C returned in vpval
|
|
677
|
+
C - the parameters (gam,Vgau,sig) of the best fitting Gaussian
|
|
678
|
+
C - the first nord Gauss-Hermite moments, returned in harr.
|
|
679
|
+
C
|
|
680
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
681
|
+
C
|
|
682
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
683
|
+
C
|
|
684
|
+
PARAMETER (maxlength = 2000000 ,
|
|
685
|
+
& mord = 200 ,
|
|
686
|
+
& mev = mord/2 )
|
|
687
|
+
C
|
|
688
|
+
DIMENSION xmom(0:100),darr(0:100),velar(101),vpval(101),
|
|
689
|
+
& harr(0:100),hold(0:100)
|
|
690
|
+
C
|
|
691
|
+
COMMON /all/ allcofs(1:maxlength),
|
|
692
|
+
& icstart(0:mev,0:mev,0:mord),
|
|
693
|
+
& kmaxall(0:mev,0:mev,0:mord), maxord
|
|
694
|
+
C
|
|
695
|
+
COMMON /potent/ ipot
|
|
696
|
+
C
|
|
697
|
+
C ipot=1 for Kepler potential and ipot=2 for logarithmic potential
|
|
698
|
+
C
|
|
699
|
+
COMMON /verbose/ iverb
|
|
700
|
+
C
|
|
701
|
+
C Determines whether verbose output should be generated for VP calculations
|
|
702
|
+
C
|
|
703
|
+
CCCCCCCCC
|
|
704
|
+
C
|
|
705
|
+
C Calculate the lowest order moments
|
|
706
|
+
C
|
|
707
|
+
rhopr0 = RHOPROJMOMAV(0)
|
|
708
|
+
DO i=0,2
|
|
709
|
+
IF (iwhat.EQ.1) THEN
|
|
710
|
+
xmom(i) = PROJMOM(xi,i)
|
|
711
|
+
ELSE IF (iwhat.EQ.3) THEN
|
|
712
|
+
xmom(i) = RHOPROJMOMAV(i) / rhopr0
|
|
713
|
+
END IF
|
|
714
|
+
END DO
|
|
715
|
+
C
|
|
716
|
+
C Calculate the normalization, mean and dispersion
|
|
717
|
+
C
|
|
718
|
+
gam0 = xmom(0)
|
|
719
|
+
V0 = xmom(1)
|
|
720
|
+
sig0 = SQRT(xmom(2)-(xmom(1)**2.0D0))
|
|
721
|
+
C
|
|
722
|
+
C Set initial values for the best fitting Gaussian
|
|
723
|
+
C
|
|
724
|
+
gam = gam0 - (gam0*darr(4)*SQRT(24.0D0)/32.0D0)
|
|
725
|
+
Vgau = V0 - (sig0*darr(3)*SQRT(6.0D0)/4.0D0)
|
|
726
|
+
sig = sig0 - (sig0*darr(4)*SQRT(24.0D0)/8.0D0)
|
|
727
|
+
C
|
|
728
|
+
C Now calculate all moments up to order minord. The choice
|
|
729
|
+
C for minord is based on the criterium that delv (see FINDVP below)
|
|
730
|
+
C should be approximately equal to sig. It is never chosen smaller
|
|
731
|
+
C than either nord or neversmaller.
|
|
732
|
+
C
|
|
733
|
+
IF (ipot.EQ.1) THEN
|
|
734
|
+
vmin = -1.0D0
|
|
735
|
+
vmax = 1.0D0
|
|
736
|
+
ELSE
|
|
737
|
+
vmin = -3.0D0
|
|
738
|
+
vmax = 3.0D0
|
|
739
|
+
END IF
|
|
740
|
+
C
|
|
741
|
+
neversmaller = 10
|
|
742
|
+
minord = INT(1.0D0+((vmax-vmin)/(0.5*sig)))
|
|
743
|
+
ncur = MIN(maxord,MAX(minord,MAX(neversmaller,nord)))
|
|
744
|
+
C
|
|
745
|
+
C Use only even values for ncur
|
|
746
|
+
C
|
|
747
|
+
IF (2*(ncur/2).NE.ncur) ncur=ncur-1
|
|
748
|
+
C
|
|
749
|
+
IF (iverb.EQ.1) THEN
|
|
750
|
+
WRITE (*,*) 'Calculating first', ncur,
|
|
751
|
+
& ' projected velocity moments ...'
|
|
752
|
+
WRITE (*,*) ' '
|
|
753
|
+
END IF
|
|
754
|
+
C
|
|
755
|
+
DO i=3,ncur
|
|
756
|
+
IF (iwhat.EQ.1) THEN
|
|
757
|
+
xmom(i) = PROJMOM(xi,i)
|
|
758
|
+
ELSE IF (iwhat.EQ.3) THEN
|
|
759
|
+
xmom(i) = RHOPROJMOMAV(i) / rhopr0
|
|
760
|
+
END IF
|
|
761
|
+
END DO
|
|
762
|
+
C
|
|
763
|
+
gamold = gam
|
|
764
|
+
Vold = Vgau
|
|
765
|
+
sigold = sig
|
|
766
|
+
DO i=0,nord
|
|
767
|
+
hold(i) = 0.0D0
|
|
768
|
+
END DO
|
|
769
|
+
delold = 1.0D10
|
|
770
|
+
C
|
|
771
|
+
istop = -1
|
|
772
|
+
C
|
|
773
|
+
C Calculate the VP, best fitting Gaussian, and Gauss-Hermite coefficients.
|
|
774
|
+
C Iterate until convergence is reached.
|
|
775
|
+
C
|
|
776
|
+
71 CALL FINDVP (ncur,xmom,velar,vpval,nvel,gam,Vgau,sig,harr)
|
|
777
|
+
C
|
|
778
|
+
C Write the resulting VP to the screen
|
|
779
|
+
C
|
|
780
|
+
IF (iverb.EQ.1) THEN
|
|
781
|
+
C
|
|
782
|
+
C WRITE (*,'(A31,I3,A9)')
|
|
783
|
+
C & 'VP reconstructed from the first',ncur,'moments:'
|
|
784
|
+
C DO i=1,nvel
|
|
785
|
+
C WRITE (*,'(I5,2F20.8)') i,velar(i),vpval(i)
|
|
786
|
+
C END DO
|
|
787
|
+
C WRITE (*,*) ' '
|
|
788
|
+
C
|
|
789
|
+
WRITE (*,'(A44,I3,A9)')
|
|
790
|
+
& 'VP coefficients reconstructed from the first',ncur,'moments:'
|
|
791
|
+
WRITE (*,'(15F8.4)') gam,Vgau,sig,(harr(k),k=0,nord)
|
|
792
|
+
WRITE (*,*) ' '
|
|
793
|
+
C
|
|
794
|
+
END IF
|
|
795
|
+
C
|
|
796
|
+
C If this was the first try, check for large negative values in the VP,
|
|
797
|
+
C indicative of the fact that too many moments have been used.
|
|
798
|
+
C
|
|
799
|
+
IF (istop.EQ.-1) THEN
|
|
800
|
+
ineg = 0
|
|
801
|
+
DO i=1,nvel
|
|
802
|
+
IF (vpval(i).LE.-0.5D0) ineg=1
|
|
803
|
+
END DO
|
|
804
|
+
IF ((ineg.EQ.1).AND.(ncur.GE.10)) THEN
|
|
805
|
+
ncur = ncur-2
|
|
806
|
+
GOTO 71
|
|
807
|
+
END IF
|
|
808
|
+
END IF
|
|
809
|
+
C
|
|
810
|
+
IF (istop.NE.1) THEN
|
|
811
|
+
C
|
|
812
|
+
C Calculate how much the difference is from the previous estimate
|
|
813
|
+
C
|
|
814
|
+
del = (((gam-gamold)/gamold)**2.0D0) +
|
|
815
|
+
& (((Vgau-Vold)/sigold)**2.0D0) +
|
|
816
|
+
& (((sig-sigold)/sigold)**2.0D0)
|
|
817
|
+
DO i=0,nord
|
|
818
|
+
del = del + ((harr(i)-hold(i))**2.0D0)
|
|
819
|
+
END DO
|
|
820
|
+
del = SQRT(del/DBLE(nord+4))
|
|
821
|
+
C
|
|
822
|
+
IF (iverb.EQ.1) THEN
|
|
823
|
+
WRITE (*,'(A36,F12.8)')
|
|
824
|
+
& 'Change with respect to previous step',del
|
|
825
|
+
WRITE (*,*) ' '
|
|
826
|
+
END IF
|
|
827
|
+
C
|
|
828
|
+
IF (del.GT.delold) THEN
|
|
829
|
+
C
|
|
830
|
+
C Stop whenever things start diverging (the problem of recovering the VP
|
|
831
|
+
C from the moments is numerically unstable to round-off error if to many
|
|
832
|
+
C moments are used).
|
|
833
|
+
C
|
|
834
|
+
gam = gamold
|
|
835
|
+
Vgau = Vold
|
|
836
|
+
sig = sigold
|
|
837
|
+
IF (istop.EQ.-2) THEN
|
|
838
|
+
ncur = ncur-4
|
|
839
|
+
delold = 1.0D10
|
|
840
|
+
istop = -1
|
|
841
|
+
ELSE
|
|
842
|
+
ncur = ncur-2
|
|
843
|
+
istop = 1
|
|
844
|
+
END IF
|
|
845
|
+
GOTO 71
|
|
846
|
+
C
|
|
847
|
+
ELSE IF ((del.GE.1.0D-5).AND.(ncur+2.LE.maxord)) THEN
|
|
848
|
+
C
|
|
849
|
+
C Keep on going by including two more moments
|
|
850
|
+
C
|
|
851
|
+
gamold = gam
|
|
852
|
+
Vold = Vgau
|
|
853
|
+
sigold = sig
|
|
854
|
+
DO i=0,nord
|
|
855
|
+
hold(i) = harr(i)
|
|
856
|
+
END DO
|
|
857
|
+
delold = del
|
|
858
|
+
C
|
|
859
|
+
xmom(ncur+1) = PROJMOM(xi,ncur+1)
|
|
860
|
+
xmom(ncur+2) = PROJMOM(xi,ncur+2)
|
|
861
|
+
ncur = ncur+2
|
|
862
|
+
IF (istop.EQ.-1) THEN
|
|
863
|
+
istop = -2
|
|
864
|
+
ELSE
|
|
865
|
+
istop = 0
|
|
866
|
+
END IF
|
|
867
|
+
GOTO 71
|
|
868
|
+
C
|
|
869
|
+
END IF
|
|
870
|
+
C
|
|
871
|
+
END IF
|
|
872
|
+
C
|
|
873
|
+
C Calculate the Gram-Charlier coefficients
|
|
874
|
+
C
|
|
875
|
+
CALL GRAMCHARCOF (xmom,ncur,V0,sig0,darr)
|
|
876
|
+
C
|
|
877
|
+
END
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
SUBROUTINE FINDVP (nord,xmom,velar,vpval,nvel,
|
|
881
|
+
& gam,Vgau,sig,harr)
|
|
882
|
+
C
|
|
883
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
884
|
+
C
|
|
885
|
+
C Given nord projected moments xmom, calculate the VP as an array vpval
|
|
886
|
+
C at the nvel=nord+1 velocities velar, by solving the corresponding
|
|
887
|
+
C vanderMonde matrix. Calculate the parameters
|
|
888
|
+
C (gam,Vgau,sig) of the best fitting Gaussian (which must have been
|
|
889
|
+
C preset at appropriate initial guesses). The first nord Gauss-Hermite
|
|
890
|
+
C moments are returned in harr.
|
|
891
|
+
C
|
|
892
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
893
|
+
C
|
|
894
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
895
|
+
C
|
|
896
|
+
DIMENSION xmom(0:100),velar(101),vpval(101),harr(0:100)
|
|
897
|
+
DIMENSION qmom(101),weight(101)
|
|
898
|
+
C
|
|
899
|
+
COMMON /potent/ ipot
|
|
900
|
+
C
|
|
901
|
+
C ipot=1 for Kepler potential and ipot=2 for logarithmic potential
|
|
902
|
+
C
|
|
903
|
+
COMMON /vpcur/ vvelar(101),vvpval(101),wweight(101),nvvel
|
|
904
|
+
C
|
|
905
|
+
C Common block in which the current velocity profile is stored, for use in
|
|
906
|
+
C REAL FUNCTION CHI2H.
|
|
907
|
+
C
|
|
908
|
+
COMMON /reg/ xlam
|
|
909
|
+
C
|
|
910
|
+
COMMON /verbose/ iverb
|
|
911
|
+
C
|
|
912
|
+
C Determines whether verbose output should be generated for VP calculations
|
|
913
|
+
C
|
|
914
|
+
CCCCCCCCCCCCCCCCC
|
|
915
|
+
C
|
|
916
|
+
C We will approximate integrals with quadrature formulae of the form:
|
|
917
|
+
C INT f(x) dx = SUM_{n=0}^{N} w_n f(x_n)
|
|
918
|
+
C where the {x_n} are a set of abscissa, and the w_n a set of weights.
|
|
919
|
+
C
|
|
920
|
+
C For the Kepler potential the terminal velocities are -1 and 1. We
|
|
921
|
+
C choose Eulerian integration between these limits.
|
|
922
|
+
C For the Logarithmic potential we also use Eulerian integration, now
|
|
923
|
+
C with limits -3 and 3. Gaussian quadratures were tried, but didn't work
|
|
924
|
+
C satisfactorily.
|
|
925
|
+
C
|
|
926
|
+
nvel = nord+1
|
|
927
|
+
C
|
|
928
|
+
IF (ipot.EQ.1) THEN
|
|
929
|
+
vmin = -1.0D0
|
|
930
|
+
vmax = 1.0D0
|
|
931
|
+
delv = (vmax-vmin)/DBLE(nvel)
|
|
932
|
+
DO i=1,nvel
|
|
933
|
+
velar(i) = vmin + ((DBLE(i)-0.5D0)*delv)
|
|
934
|
+
weight(i) = delv
|
|
935
|
+
END DO
|
|
936
|
+
ELSE
|
|
937
|
+
vmin = -3.0D0
|
|
938
|
+
vmax = 3.0D0
|
|
939
|
+
delv = (vmax-vmin)/DBLE(nvel)
|
|
940
|
+
DO i=1,nvel
|
|
941
|
+
velar(i) = vmin + ((DBLE(i)-0.5D0)*delv)
|
|
942
|
+
weight(i) = delv
|
|
943
|
+
END DO
|
|
944
|
+
END IF
|
|
945
|
+
C
|
|
946
|
+
C Define a vector with the moments that are to be reproduced
|
|
947
|
+
C
|
|
948
|
+
DO i=1,nvel
|
|
949
|
+
qmom(i) = xmom(i-1)
|
|
950
|
+
END DO
|
|
951
|
+
C
|
|
952
|
+
C Now solve the corresponding Van der Monde matrix (Numerical
|
|
953
|
+
C Recipes, eq. 2.8.2). If xlam<0, then do not use regularization.
|
|
954
|
+
C If xlam>0, then use regularization. If xlam=0, then the
|
|
955
|
+
C regularization parameter is determined iteratively, so as to yield
|
|
956
|
+
C an acceptably smooth VP.
|
|
957
|
+
C
|
|
958
|
+
IF (xlam.LT.0.0D0) THEN
|
|
959
|
+
CALL VANDER(velar,vpval,qmom,nvel)
|
|
960
|
+
ELSE IF (xlam.GT.0.0D0) THEN
|
|
961
|
+
CALL REG_VANDER(velar,vpval,qmom,nvel,xlam)
|
|
962
|
+
ELSE
|
|
963
|
+
xlamreg = 1.0D-30
|
|
964
|
+
81 CALL REG_VANDER(velar,vpval,qmom,nvel,xlamreg)
|
|
965
|
+
CALL TESTSMOOTH(velar,vpval,nvel,iOK,Nmax)
|
|
966
|
+
IF (iverb.EQ.1) THEN
|
|
967
|
+
WRITE (*,'(A35,E15.7,I5)')
|
|
968
|
+
& 'Regularization, local maxima : ', xlamreg, Nmax
|
|
969
|
+
END IF
|
|
970
|
+
IF (iOK.EQ.0) THEN
|
|
971
|
+
xlamreg = xlamreg * 10.0D0
|
|
972
|
+
GOTO 81
|
|
973
|
+
END IF
|
|
974
|
+
IF (iverb.EQ.1) WRITE (*,*) ' '
|
|
975
|
+
END IF
|
|
976
|
+
C
|
|
977
|
+
C And divide by the weights to get the approximations to the VP
|
|
978
|
+
C
|
|
979
|
+
DO i=1,nvel
|
|
980
|
+
vpval(i) = vpval(i)/weight(i)
|
|
981
|
+
END DO
|
|
982
|
+
C
|
|
983
|
+
C Copy the results for use in FITGAUSS
|
|
984
|
+
C
|
|
985
|
+
nvvel = nvel
|
|
986
|
+
DO i=1,nvel
|
|
987
|
+
vvpval(i) = vpval(i)
|
|
988
|
+
vvelar(i) = velar(i)
|
|
989
|
+
wweight(i) = weight(i)
|
|
990
|
+
END DO
|
|
991
|
+
C
|
|
992
|
+
C Find the best fitting Gaussian (by searching for those values that
|
|
993
|
+
C come as closely as possible to generating h0=1, h1=h2=0).
|
|
994
|
+
C
|
|
995
|
+
CALL FITGAUSS (gam,Vgau,sig)
|
|
996
|
+
C
|
|
997
|
+
C Now get all the Gauss-Hermite coefficients up to order nord
|
|
998
|
+
C
|
|
999
|
+
CALL GAUHERM (velar,vpval,weight,nvel,gam,Vgau,sig,harr,nord)
|
|
1000
|
+
C
|
|
1001
|
+
END
|
|
1002
|
+
|
|
1003
|
+
|
|
1004
|
+
SUBROUTINE TESTSMOOTH(velar,vpval,nvel,iOK,Nmax)
|
|
1005
|
+
C
|
|
1006
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1007
|
+
C
|
|
1008
|
+
C Test whether a recoverd VP is acceptably smooth. The test crtiterion is
|
|
1009
|
+
C that there are no more than 3 `significant' local maxima in the VP.
|
|
1010
|
+
C
|
|
1011
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1012
|
+
C
|
|
1013
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1014
|
+
C
|
|
1015
|
+
DIMENSION velar(101),vpval(101)
|
|
1016
|
+
C
|
|
1017
|
+
COMMON /smoo/ epsmoo
|
|
1018
|
+
C
|
|
1019
|
+
C Parameter that determines the requested smoothness, as fraction of
|
|
1020
|
+
C the VP maximum.
|
|
1021
|
+
C
|
|
1022
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
1023
|
+
C
|
|
1024
|
+
C Find the maximum of ABS(VP)
|
|
1025
|
+
C
|
|
1026
|
+
vpmax = -1.0D30
|
|
1027
|
+
DO i=1,nvel
|
|
1028
|
+
IF (ABS(vpval(i)).GT.vpmax) THEN
|
|
1029
|
+
vpmax = ABS(vpval(i))
|
|
1030
|
+
END IF
|
|
1031
|
+
END DO
|
|
1032
|
+
C
|
|
1033
|
+
C Find the number of local maxima
|
|
1034
|
+
C
|
|
1035
|
+
dmax = epsmoo * vpmax
|
|
1036
|
+
Nmax = 0
|
|
1037
|
+
iOK = 1
|
|
1038
|
+
C
|
|
1039
|
+
DO i=2,nvel-1
|
|
1040
|
+
dvm = vpval(i)-vpval(i-1)
|
|
1041
|
+
dvp = vpval(i)-vpval(i+1)
|
|
1042
|
+
IF ((dvm.GT.dmax).AND.(dvp.GT.dmax)) Nmax = Nmax + 1
|
|
1043
|
+
END DO
|
|
1044
|
+
C
|
|
1045
|
+
IF (Nmax.GE.4) iOK=0
|
|
1046
|
+
C
|
|
1047
|
+
END
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
|
+
SUBROUTINE FITGAUSS (gam,Vgau,sig)
|
|
1051
|
+
C
|
|
1052
|
+
C Find the best fitting Gaussian parameters (gam,Vgau,sig) for
|
|
1053
|
+
C the VP in the common block /vpcur/. The parameters must be preset at
|
|
1054
|
+
C initial guesses. The function CHI2H below is minimized using the Numerical
|
|
1055
|
+
C Recipes routine amoeba.
|
|
1056
|
+
C
|
|
1057
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1058
|
+
C
|
|
1059
|
+
PARAMETER (eps = 1.0D-16)
|
|
1060
|
+
C
|
|
1061
|
+
DIMENSION P(4,3),Y(4),help(3)
|
|
1062
|
+
C
|
|
1063
|
+
C Starting simpleces for routine AMOEBA, and the function values
|
|
1064
|
+
C in the starting simpleces.
|
|
1065
|
+
C
|
|
1066
|
+
EXTERNAL CHI2H
|
|
1067
|
+
C
|
|
1068
|
+
C Initialize the fits
|
|
1069
|
+
C
|
|
1070
|
+
epsmal = 0.6D0
|
|
1071
|
+
epsmal = MIN(0.9D0,ABS(epsmal))
|
|
1072
|
+
pl1 = 1.0D0 + epsmal
|
|
1073
|
+
xmn1 = 1.0D0 - epsmal
|
|
1074
|
+
C
|
|
1075
|
+
C Determines the size of the starting simplex
|
|
1076
|
+
C
|
|
1077
|
+
P(1,1) = gam
|
|
1078
|
+
P(1,2) = Vgau
|
|
1079
|
+
P(1,3) = sig * pl1
|
|
1080
|
+
P(2,1) = gam * xmn1
|
|
1081
|
+
P(2,2) = Vgau - (sig*epsmal)
|
|
1082
|
+
P(2,3) = sig * xmn1
|
|
1083
|
+
P(3,1) = gam * pl1
|
|
1084
|
+
P(3,2) = Vgau - (sig*epsmal)
|
|
1085
|
+
P(3,3) = sig * xmn1
|
|
1086
|
+
P(4,1) = gam
|
|
1087
|
+
P(4,2) = Vgau + (sig*epsmal)
|
|
1088
|
+
P(4,3) = sig * xmn1
|
|
1089
|
+
C
|
|
1090
|
+
C Initialize
|
|
1091
|
+
C
|
|
1092
|
+
DO i=1,4
|
|
1093
|
+
DO j=1,3
|
|
1094
|
+
help(j) = P(i,j)
|
|
1095
|
+
END DO
|
|
1096
|
+
Y(i) = CHI2H(help)
|
|
1097
|
+
END DO
|
|
1098
|
+
C
|
|
1099
|
+
CALL AMOEBA(P,Y,4,3,3,eps,CHI2H,iter)
|
|
1100
|
+
C
|
|
1101
|
+
gam = (ABS(P(1,1))+ABS(P(2,1))+ABS(P(3,1))+
|
|
1102
|
+
& ABS(P(4,1)))/4.0D0
|
|
1103
|
+
Vgau = (P(1,2)+P(2,2)+P(3,2)+P(4,2))/4.0D0
|
|
1104
|
+
sig = (ABS(P(1,3))+ABS(P(2,3))+ABS(P(3,3))+
|
|
1105
|
+
& ABS(P(4,3)))/4.0D0
|
|
1106
|
+
C
|
|
1107
|
+
END
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
REAL*8 FUNCTION CHI2H (y)
|
|
1111
|
+
C
|
|
1112
|
+
C Calculates the chih^2 = (h0-1)^2 + (h1^2) + (h2^2) for a Gaussian
|
|
1113
|
+
C with parameters gam = |y(1)|, Vgau = y(2), sig = |y(3)|,
|
|
1114
|
+
C for the VP in the common block /vpcur/
|
|
1115
|
+
C
|
|
1116
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1117
|
+
C
|
|
1118
|
+
DIMENSION y(3),harr(0:100)
|
|
1119
|
+
C
|
|
1120
|
+
COMMON /vpcur/ velar(101),vpval(101),weight(101),nvel
|
|
1121
|
+
C
|
|
1122
|
+
C Avoid values of gamma and sigma too close to zero.
|
|
1123
|
+
C
|
|
1124
|
+
gam = MAX(1.0D-3,ABS(y(1)))
|
|
1125
|
+
Vgau = y(2)
|
|
1126
|
+
sig = MAX(1.0D-3,ABS(y(3)))
|
|
1127
|
+
C
|
|
1128
|
+
CALL GAUHERM (velar,vpval,weight,nvel,gam,Vgau,sig,harr,2)
|
|
1129
|
+
C
|
|
1130
|
+
CHI2H = 1.0D0 + ((harr(0)-1.0D0)**2.0D0) +
|
|
1131
|
+
& (harr(1)**2.0D0) + (harr(2)**2.0D0)
|
|
1132
|
+
C
|
|
1133
|
+
END
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
SUBROUTINE GAUHERM (velar,vpval,weight,nvel,
|
|
1137
|
+
& gam,Vgau,sig,harr,nhord)
|
|
1138
|
+
C
|
|
1139
|
+
C Given the VP as an array vpval, corrsponding to nvel velocities velar,
|
|
1140
|
+
C calculate the Gauss-Hermite coefficients harr up to order nhord that belong
|
|
1141
|
+
C to the given reference values gam,Vgau,sig.
|
|
1142
|
+
C
|
|
1143
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1144
|
+
C
|
|
1145
|
+
PARAMETER (pi=3.14159265358979D0)
|
|
1146
|
+
C
|
|
1147
|
+
DIMENSION velar(101),vpval(101),weight(101),harr(0:100)
|
|
1148
|
+
C
|
|
1149
|
+
DO l=0,nhord
|
|
1150
|
+
harr(l) = 0.0D0
|
|
1151
|
+
END DO
|
|
1152
|
+
C
|
|
1153
|
+
DO i=1,nvel
|
|
1154
|
+
w = (velar(i)-Vgau)/sig
|
|
1155
|
+
DO l=0,nhord
|
|
1156
|
+
harr(l) = harr(l) +
|
|
1157
|
+
& (vpval(i)*weight(i)*SDGAUSS(w)*H_POL(l,w))
|
|
1158
|
+
END DO
|
|
1159
|
+
END DO
|
|
1160
|
+
C
|
|
1161
|
+
DO l=0,nhord
|
|
1162
|
+
harr(l) = harr(l) * 2.0D0 * SQRT(pi) / gam
|
|
1163
|
+
END DO
|
|
1164
|
+
C
|
|
1165
|
+
END
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
SUBROUTINE GRAMCHARCOF (xmom,nord,V0,sig0,darr)
|
|
1169
|
+
C
|
|
1170
|
+
C Calculate the Gram-Charlier coefficients of the velocity profile, given
|
|
1171
|
+
C the array xmom, containing the first nord moments.
|
|
1172
|
+
C The reference values (V0,sig0) of the series are required at
|
|
1173
|
+
C input separately. These need not necessarily correspond to the true
|
|
1174
|
+
C mean and dispersion of the VP. The Gram-Charlier coefficients are
|
|
1175
|
+
C calculated up to order nord, and are returned in darr.
|
|
1176
|
+
C
|
|
1177
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1178
|
+
C
|
|
1179
|
+
DIMENSION xmom(0:100),darr(0:100)
|
|
1180
|
+
C
|
|
1181
|
+
DO l=0,nord
|
|
1182
|
+
dl = DBLE(l)
|
|
1183
|
+
darr(l) = 0.0D0
|
|
1184
|
+
DO j=0,l
|
|
1185
|
+
dj = DBLE(j)
|
|
1186
|
+
IF (2*((j+l)/2).EQ.(j+l)) THEN
|
|
1187
|
+
pfacln = (0.5D0*gammaln(dl+1.0D0)) - gammaln(dj+1.0D0) -
|
|
1188
|
+
& gammaln(dl-dj+1.0D0) +
|
|
1189
|
+
& (gammaln(0.5D0*(dl-dj+1.0D0))) - gammaln(0.5D0) +
|
|
1190
|
+
& (0.5D0*(dl-dj)*LOG(2.0D0))
|
|
1191
|
+
pfac = ((-1.0D0)**((l-j)/2)) * EXPP(pfacln)
|
|
1192
|
+
DO i=0,j
|
|
1193
|
+
darr(l) = darr(l) +
|
|
1194
|
+
& ( ((-1.0D0)**(j-i)) * (V0**(j-i)) *
|
|
1195
|
+
& ((1.0/sig0)**j) * xmom(i) * pfac *
|
|
1196
|
+
& EXPP(binomln(j,i)) )
|
|
1197
|
+
END DO
|
|
1198
|
+
END IF
|
|
1199
|
+
END DO
|
|
1200
|
+
END DO
|
|
1201
|
+
C
|
|
1202
|
+
END
|
|
1203
|
+
|
|
1204
|
+
|
|
1205
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1206
|
+
C
|
|
1207
|
+
C The function SDGAUSS, HE_POL and H_POL calculate the standard
|
|
1208
|
+
C Gaussian and Hermite polynomials.
|
|
1209
|
+
C
|
|
1210
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1211
|
+
|
|
1212
|
+
REAL*8 FUNCTION SDGAUSS (x)
|
|
1213
|
+
C
|
|
1214
|
+
C Returns the standard Gaussian as function of x
|
|
1215
|
+
C
|
|
1216
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1217
|
+
PARAMETER (pi=3.14159265358979D0)
|
|
1218
|
+
SDGAUSS = (1.0D0/SQRT(2.0D0*pi)) * EXPP(-0.5D0*x*x)
|
|
1219
|
+
END
|
|
1220
|
+
|
|
1221
|
+
|
|
1222
|
+
REAL*8 FUNCTION HE_POL (l,x)
|
|
1223
|
+
C
|
|
1224
|
+
C Returns the value of the Hermite polynomial He_l(x) as defined
|
|
1225
|
+
C in Appendix A of van der Marel & Franx.
|
|
1226
|
+
C
|
|
1227
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1228
|
+
C
|
|
1229
|
+
HE_POL = 0.0D0
|
|
1230
|
+
dl = DBLE(l)
|
|
1231
|
+
DO j=l,0,-1
|
|
1232
|
+
IF (2*((j+l)/2).EQ.j+l) THEN
|
|
1233
|
+
dj = DBLE(j)
|
|
1234
|
+
pfacln = (0.5D0*gammaln(dl+1.0D0)) -
|
|
1235
|
+
& gammaln(dj+1.0D0) - gammaln(dl-dj+1.0D0) +
|
|
1236
|
+
& gammaln(0.5D0*(dl-dj+1.0D0)) -
|
|
1237
|
+
& gammaln(0.5D0) + (0.5D0*(dl-dj)*LOG(2.0D0))
|
|
1238
|
+
pfac = ((-1.0D0)**((l-j)/2)) * EXPP(pfacln)
|
|
1239
|
+
ELSE
|
|
1240
|
+
pfac = 0.0D0
|
|
1241
|
+
END IF
|
|
1242
|
+
HE_POL = pfac + (x*HE_POL)
|
|
1243
|
+
END DO
|
|
1244
|
+
C
|
|
1245
|
+
END
|
|
1246
|
+
|
|
1247
|
+
|
|
1248
|
+
REAL*8 FUNCTION H_POL (l,x)
|
|
1249
|
+
C
|
|
1250
|
+
C Returns the value of the Hermite polynomial H_l(x) as defined
|
|
1251
|
+
C in Appendix A of van der Marel & Franx.
|
|
1252
|
+
C
|
|
1253
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1254
|
+
H_POL = HE_POL(l,x*SQRT(2.0D0))
|
|
1255
|
+
END
|
|
1256
|
+
|
|
1257
|
+
|
|
1258
|
+
REAL*8 FUNCTION RHOPROJMOMAV (nord)
|
|
1259
|
+
C
|
|
1260
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1261
|
+
C
|
|
1262
|
+
C The function RHOPROJMOMAV calculates the
|
|
1263
|
+
C projected rho times velocity moment of a given order, integrated along
|
|
1264
|
+
C a circle in the first quadrant of the sky.
|
|
1265
|
+
C
|
|
1266
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1267
|
+
C
|
|
1268
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1269
|
+
C
|
|
1270
|
+
PARAMETER (pi=3.14159265358979D0)
|
|
1271
|
+
C
|
|
1272
|
+
COMMON /howint/ iint
|
|
1273
|
+
C
|
|
1274
|
+
COMMON /curprojorder/ nordcur
|
|
1275
|
+
C
|
|
1276
|
+
C Common block that holds copies of the order with which this
|
|
1277
|
+
C function is called.
|
|
1278
|
+
C
|
|
1279
|
+
EXTERNAL TOINTPROJ,MIDPNTB
|
|
1280
|
+
C
|
|
1281
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
1282
|
+
C
|
|
1283
|
+
nordcur = nord
|
|
1284
|
+
C
|
|
1285
|
+
IF (iint.EQ.0) THEN
|
|
1286
|
+
CALL QROMOB (TOINTPROJ,0.0D0,0.5D0*pi,SS,MIDPNTB)
|
|
1287
|
+
ELSE
|
|
1288
|
+
CALL QGAUSLEGB (TOINTPROJ,0.0D0,0.5D0*pi,SS)
|
|
1289
|
+
END IF
|
|
1290
|
+
C
|
|
1291
|
+
RHOPROJMOMAV = SS / (0.5D0*pi)
|
|
1292
|
+
C
|
|
1293
|
+
END
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
REAL*8 FUNCTION TOINTPROJ (xi)
|
|
1297
|
+
C
|
|
1298
|
+
C The function that must be integrated to get the first-quadrant integral
|
|
1299
|
+
C over a circle on the sky of rho times projected velocity moment for the
|
|
1300
|
+
C order given by /curprojorder/.
|
|
1301
|
+
C
|
|
1302
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1303
|
+
C
|
|
1304
|
+
COMMON /curprojorder/ nordcur
|
|
1305
|
+
C
|
|
1306
|
+
TOINTPROJ = RHOPROJ(xi) * PROJMOM(xi,nordcur)
|
|
1307
|
+
C
|
|
1308
|
+
END
|
|
1309
|
+
|
|
1310
|
+
|
|
1311
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1312
|
+
C
|
|
1313
|
+
C The function RHOPROJ calculates the projected mass density analytically.
|
|
1314
|
+
C The function PROJMOM calculates the projected velocity momemnts by
|
|
1315
|
+
C numerical 1D integration over the function TOINT. This uses
|
|
1316
|
+
C RHOVPROJMOM, rho times the n-th projected velocity moment (selected
|
|
1317
|
+
C point in the galaxy.
|
|
1318
|
+
C
|
|
1319
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1320
|
+
|
|
1321
|
+
REAL*8 FUNCTION RHOPROJ (xi)
|
|
1322
|
+
C
|
|
1323
|
+
C The projected mass density at scaled projected radius equal to 1,
|
|
1324
|
+
C and angle xi from the major axis. The expression is known
|
|
1325
|
+
C analytically, because the 3D mass density is simply a power law on
|
|
1326
|
+
C spheroids.
|
|
1327
|
+
C
|
|
1328
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1329
|
+
C
|
|
1330
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
1331
|
+
COMMON /viewing/ xinc
|
|
1332
|
+
C
|
|
1333
|
+
qp2 = (COS(xinc)**2.0D0) + ((q*q)*(SIN(xinc)**2.0D0))
|
|
1334
|
+
qp = SQRT(qp2)
|
|
1335
|
+
C
|
|
1336
|
+
xacc = COS(xi)
|
|
1337
|
+
yacc = SIN(xi)
|
|
1338
|
+
C
|
|
1339
|
+
RHOPROJ = (q/qp) * EXPP(betaln(0.5D0,0.5D0*(gamma-1.0D0))) *
|
|
1340
|
+
& ( ((xacc**2.0D0)+((yacc**2.0D0)/qp2))**
|
|
1341
|
+
& (0.5D0*(1.0D0-gamma)) )
|
|
1342
|
+
C
|
|
1343
|
+
END
|
|
1344
|
+
|
|
1345
|
+
|
|
1346
|
+
REAL*8 FUNCTION PROJMOM (xi,nord)
|
|
1347
|
+
C
|
|
1348
|
+
C Calculate the projected n-th order velocity moment on the sky,
|
|
1349
|
+
C at scaled projected radius equal to 1, and angle xi from the
|
|
1350
|
+
C major axis.
|
|
1351
|
+
C
|
|
1352
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1353
|
+
C
|
|
1354
|
+
PARAMETER (pi=3.14159265358979D0)
|
|
1355
|
+
C
|
|
1356
|
+
COMMON /losmom/ xxi,nnord
|
|
1357
|
+
C
|
|
1358
|
+
COMMON /projcase/ iproj
|
|
1359
|
+
C
|
|
1360
|
+
C
|
|
1361
|
+
COMMON /howint/ iint
|
|
1362
|
+
C
|
|
1363
|
+
EXTERNAL TOINT,MIDPNT
|
|
1364
|
+
C
|
|
1365
|
+
IF ( ((2*(nord/2)).NE.nord) .AND.
|
|
1366
|
+
& (ABS(COS(xi)).LE.1.0D-12) ) THEN
|
|
1367
|
+
PROJMOM = 0.0D0
|
|
1368
|
+
RETURN
|
|
1369
|
+
END IF
|
|
1370
|
+
C
|
|
1371
|
+
IF (nord.EQ.0) THEN
|
|
1372
|
+
PROJMOM = 1.0D0
|
|
1373
|
+
RETURN
|
|
1374
|
+
END IF
|
|
1375
|
+
C
|
|
1376
|
+
xxi = xi
|
|
1377
|
+
nnord = nord
|
|
1378
|
+
C
|
|
1379
|
+
IF (iint.EQ.0) THEN
|
|
1380
|
+
CALL QROMO (TOINT,-0.5D0*pi,0.5D0*pi,SS,MIDPNT)
|
|
1381
|
+
ELSE
|
|
1382
|
+
CALL QGAUSLEG (TOINT,-0.5D0*pi,0.5D0*pi,SS)
|
|
1383
|
+
END IF
|
|
1384
|
+
C
|
|
1385
|
+
PROJMOM = SS / RHOPROJ(xi)
|
|
1386
|
+
C
|
|
1387
|
+
END
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
REAL*8 FUNCTION TOINT (tau)
|
|
1391
|
+
C
|
|
1392
|
+
C The function that must be integrated to get the n-th order velocity
|
|
1393
|
+
C moment on the sky.
|
|
1394
|
+
C
|
|
1395
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1396
|
+
C
|
|
1397
|
+
COMMON /losmom/ xi,nord
|
|
1398
|
+
C
|
|
1399
|
+
COMMON /projcase/ iproj
|
|
1400
|
+
C
|
|
1401
|
+
C
|
|
1402
|
+
COMMON /potent/ ipot
|
|
1403
|
+
C
|
|
1404
|
+
C ipot=1 for Kepler potential and ipot=2 for logarithmic potential
|
|
1405
|
+
C
|
|
1406
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
1407
|
+
COMMON /viewing/ xinc
|
|
1408
|
+
C
|
|
1409
|
+
xacc = COS(xi)
|
|
1410
|
+
yacc = SIN(xi)
|
|
1411
|
+
zacc = TAN(tau)
|
|
1412
|
+
C
|
|
1413
|
+
x = (-1.0D0*COS(xinc)*yacc) + (SIN(xinc)*zacc)
|
|
1414
|
+
y = xacc
|
|
1415
|
+
z = (SIN(xinc)*yacc) + (COS(xinc)*zacc)
|
|
1416
|
+
Rc = SQRT((x**2.0D0)+(y**2.0D0))
|
|
1417
|
+
r = SQRT((Rc**2.0D0)+(z**2.0D0))
|
|
1418
|
+
C
|
|
1419
|
+
theta = ACOS(z/r)
|
|
1420
|
+
phi = ACOS(x/Rc)
|
|
1421
|
+
C
|
|
1422
|
+
IF (ipot.EQ.1) THEN
|
|
1423
|
+
TOINT = (COS(tau)**(gamma-2.0D0+(0.5D0*DBLE(nord)))) *
|
|
1424
|
+
& RHOVPROJMOM(theta,phi,nord)
|
|
1425
|
+
ELSE IF (ipot.EQ.2) THEN
|
|
1426
|
+
TOINT = (COS(tau)**(gamma-2.0D0)) *
|
|
1427
|
+
& RHOVPROJMOM(theta,phi,nord)
|
|
1428
|
+
ELSE
|
|
1429
|
+
STOP 'ipot wrong value'
|
|
1430
|
+
END IF
|
|
1431
|
+
C
|
|
1432
|
+
END
|
|
1433
|
+
|
|
1434
|
+
|
|
1435
|
+
REAL*8 FUNCTION RHOVLOSMOM(theta,phi,nord)
|
|
1436
|
+
C
|
|
1437
|
+
C Returns rho times the nord-th line-of-sight velocity moment at the
|
|
1438
|
+
C point with polar coordinates (theta,phi) in radians, and radius 1
|
|
1439
|
+
C (in dimensionless units).
|
|
1440
|
+
C
|
|
1441
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1442
|
+
C
|
|
1443
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
1444
|
+
COMMON /viewing/ xinc
|
|
1445
|
+
C
|
|
1446
|
+
Afac = (COS(phi)*SIN(theta)*SIN(xinc)) + (COS(theta)*COS(xinc))
|
|
1447
|
+
Bfac = (COS(phi)*COS(theta)*SIN(xinc)) - (SIN(theta)*COS(xinc))
|
|
1448
|
+
Cfac = (-1.0D0*SIN(phi)*SIN(xinc))
|
|
1449
|
+
C
|
|
1450
|
+
IF (Afac.LT.0.0D0) THEN
|
|
1451
|
+
Asign = -1.0D0
|
|
1452
|
+
ELSE
|
|
1453
|
+
Asign = 1.0D0
|
|
1454
|
+
END IF
|
|
1455
|
+
Afac = MAX(1.0D-20,ABS(Afac))
|
|
1456
|
+
C
|
|
1457
|
+
IF (Bfac.LT.0.0D0) THEN
|
|
1458
|
+
Bsign = -1.0D0
|
|
1459
|
+
ELSE
|
|
1460
|
+
Bsign = 1.0D0
|
|
1461
|
+
END IF
|
|
1462
|
+
Bfac = MAX(1.0D-20,ABS(Bfac))
|
|
1463
|
+
C
|
|
1464
|
+
IF (Cfac.LT.0.0D0) THEN
|
|
1465
|
+
Csign = -1.0D0
|
|
1466
|
+
ELSE
|
|
1467
|
+
Csign = 1.0D0
|
|
1468
|
+
END IF
|
|
1469
|
+
Cfac = MAX(1.0D-20,ABS(Cfac))
|
|
1470
|
+
C
|
|
1471
|
+
RHOVLOSMOM = 0.0D0
|
|
1472
|
+
DO k=0,nord
|
|
1473
|
+
DO j=0,nord-k
|
|
1474
|
+
facln = binomln(nord,k) + binomln(nord-k,j) +
|
|
1475
|
+
& (DBLE(k)*LOG(Afac)) + (DBLE(j)*LOG(Bfac)) +
|
|
1476
|
+
& (DBLE(nord-k-j)*LOG(Cfac))
|
|
1477
|
+
RHOVLOSMOM = RHOVLOSMOM + ( EXPP(facln)*
|
|
1478
|
+
& (Asign**k)*(Bsign**j)*(Csign**(nord-k-j))*
|
|
1479
|
+
& RHOVELMOM(theta,k,j,nord-k-j) )
|
|
1480
|
+
END DO
|
|
1481
|
+
END DO
|
|
1482
|
+
C
|
|
1483
|
+
END
|
|
1484
|
+
|
|
1485
|
+
|
|
1486
|
+
REAL*8 FUNCTION RHOVPOSRMOM(theta,phi,nord)
|
|
1487
|
+
C
|
|
1488
|
+
C Returns rho times the nord-th line-of-sight velocity moment at the
|
|
1489
|
+
C point with polar coordinates (theta,phi) in radians, and radius 1
|
|
1490
|
+
C (in dimensionless units).
|
|
1491
|
+
C
|
|
1492
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1493
|
+
C
|
|
1494
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
1495
|
+
COMMON /viewing/ xinc
|
|
1496
|
+
C
|
|
1497
|
+
SP = SIN(phi)
|
|
1498
|
+
CP = COS(phi)
|
|
1499
|
+
ST = SIN(theta)
|
|
1500
|
+
CT = COS(theta)
|
|
1501
|
+
SX = SIN(xinc)
|
|
1502
|
+
CX = COS(xinc)
|
|
1503
|
+
CTT = COS(2.0D0*theta)
|
|
1504
|
+
C
|
|
1505
|
+
Afac = SQRT(ST*ST*SP*SP+(CT*SX - ST*CX*CP)**2.0D0)
|
|
1506
|
+
Bfac = (ST*CT*CX*CX*CP*CP + ST*CT*(SP*SP - SX*SX) -
|
|
1507
|
+
& CTT*SX*CX*CP)/Afac
|
|
1508
|
+
Cfac = SP*(ST*CP + ST*CX*CX*(-1.0D0*CP) +
|
|
1509
|
+
& CT*SX*CX)/Afac
|
|
1510
|
+
C
|
|
1511
|
+
IF (Afac.LT.0.0D0) THEN
|
|
1512
|
+
Asign = -1.0D0
|
|
1513
|
+
ELSE
|
|
1514
|
+
Asign = 1.0D0
|
|
1515
|
+
END IF
|
|
1516
|
+
Afac = MAX(1.0D-20,ABS(Afac))
|
|
1517
|
+
C
|
|
1518
|
+
IF (Bfac.LT.0.0D0) THEN
|
|
1519
|
+
Bsign = -1.0D0
|
|
1520
|
+
ELSE
|
|
1521
|
+
Bsign = 1.0D0
|
|
1522
|
+
END IF
|
|
1523
|
+
Bfac = MAX(1.0D-20,ABS(Bfac))
|
|
1524
|
+
C
|
|
1525
|
+
IF (Cfac.LT.0.0D0) THEN
|
|
1526
|
+
Csign = -1.0D0
|
|
1527
|
+
ELSE
|
|
1528
|
+
Csign = 1.0D0
|
|
1529
|
+
END IF
|
|
1530
|
+
Cfac = MAX(1.0D-20,ABS(Cfac))
|
|
1531
|
+
C
|
|
1532
|
+
RHOVPOSRMOM = 0.0D0
|
|
1533
|
+
DO k=0,nord
|
|
1534
|
+
DO j=0,nord-k
|
|
1535
|
+
facln = binomln(nord,k) + binomln(nord-k,j) +
|
|
1536
|
+
& (DBLE(k)*LOG(Afac)) + (DBLE(j)*LOG(Bfac)) +
|
|
1537
|
+
& (DBLE(nord-k-j)*LOG(Cfac))
|
|
1538
|
+
RHOVPOSRMOM = RHOVPOSRMOM + ( EXPP(facln)*
|
|
1539
|
+
& (Asign**k)*(Bsign**j)*(Csign**(nord-k-j))*
|
|
1540
|
+
& RHOVELMOM(theta,k,j,nord-k-j) )
|
|
1541
|
+
END DO
|
|
1542
|
+
END DO
|
|
1543
|
+
C
|
|
1544
|
+
END
|
|
1545
|
+
|
|
1546
|
+
|
|
1547
|
+
|
|
1548
|
+
REAL*8 FUNCTION RHOVPOSTMOM(theta,phi,nord)
|
|
1549
|
+
C
|
|
1550
|
+
C Returns rho times the nord-th line-of-sight velocity moment at the
|
|
1551
|
+
C point with polar coordinates (theta,phi) in radians, and radius 1
|
|
1552
|
+
C (in dimensionless units).
|
|
1553
|
+
C
|
|
1554
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1555
|
+
C
|
|
1556
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
1557
|
+
COMMON /viewing/ xinc
|
|
1558
|
+
C
|
|
1559
|
+
SP = SIN(phi)
|
|
1560
|
+
CP = COS(phi)
|
|
1561
|
+
ST = SIN(theta)
|
|
1562
|
+
CT = COS(theta)
|
|
1563
|
+
SX = SIN(xinc)
|
|
1564
|
+
CX = COS(xinc)
|
|
1565
|
+
DEN = SQRT(ST*ST*SP*SP+(CT*SX - ST*CX*CP)**2.0D0)
|
|
1566
|
+
C
|
|
1567
|
+
Bfac = SX*SP/DEN
|
|
1568
|
+
Cfac = (CT*SX*CP - ST*CX)/DEN
|
|
1569
|
+
C
|
|
1570
|
+
IF (Bfac.LT.0.0D0) THEN
|
|
1571
|
+
Bsign = -1.0D0
|
|
1572
|
+
ELSE
|
|
1573
|
+
Bsign = 1.0D0
|
|
1574
|
+
END IF
|
|
1575
|
+
Bfac = MAX(1.0D-20,ABS(Bfac))
|
|
1576
|
+
C
|
|
1577
|
+
IF (Cfac.LT.0.0D0) THEN
|
|
1578
|
+
Csign = -1.0D0
|
|
1579
|
+
ELSE
|
|
1580
|
+
Csign = 1.0D0
|
|
1581
|
+
END IF
|
|
1582
|
+
Cfac = MAX(1.0D-20,ABS(Cfac))
|
|
1583
|
+
C
|
|
1584
|
+
RHOVPOSTMOM = 0.0D0
|
|
1585
|
+
DO j=0,nord
|
|
1586
|
+
facln = binomln(nord,0) + binomln(nord,j) +
|
|
1587
|
+
& (DBLE(j)*LOG(Bfac)) +
|
|
1588
|
+
& (DBLE(nord-j)*LOG(Cfac))
|
|
1589
|
+
RHOVPOSTMOM = RHOVPOSTMOM + ( EXPP(facln)*
|
|
1590
|
+
& (Bsign**j)*(Csign**(nord-j))*
|
|
1591
|
+
& RHOVELMOM(theta,0,j,nord-j) )
|
|
1592
|
+
END DO
|
|
1593
|
+
C
|
|
1594
|
+
END
|
|
1595
|
+
|
|
1596
|
+
|
|
1597
|
+
REAL*8 FUNCTION RHOVPROJMOM(theta,phi,nord)
|
|
1598
|
+
C
|
|
1599
|
+
C Select the projected component (LOS=1, POSR=2, POST=3)
|
|
1600
|
+
C and return rho times the nord-th projected velocity moment at the
|
|
1601
|
+
C point with polar coordinates (theta,phi) in radians, and radius 1
|
|
1602
|
+
C (in dimensionless units).
|
|
1603
|
+
C
|
|
1604
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1605
|
+
C
|
|
1606
|
+
COMMON /projcase/ iproj
|
|
1607
|
+
C
|
|
1608
|
+
IF (iproj.EQ.1) THEN
|
|
1609
|
+
RHOVPROJMOM = RHOVLOSMOM(theta,phi,nord)
|
|
1610
|
+
ELSE IF (iproj.EQ.2) THEN
|
|
1611
|
+
RHOVPROJMOM = RHOVPOSRMOM(theta,phi,nord)
|
|
1612
|
+
ELSE IF (iproj.EQ.3) THEN
|
|
1613
|
+
RHOVPROJMOM = RHOVPOSTMOM(theta,phi,nord)
|
|
1614
|
+
ELSE
|
|
1615
|
+
STOP 'iproj wrong value'
|
|
1616
|
+
END IF
|
|
1617
|
+
C
|
|
1618
|
+
END
|
|
1619
|
+
|
|
1620
|
+
|
|
1621
|
+
|
|
1622
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1623
|
+
C
|
|
1624
|
+
C The subroutine VIRIALTENSORS calculates the virial tensors, using
|
|
1625
|
+
C the fact that the intrinsic moments are power series in e^2 SIN^2(theta).
|
|
1626
|
+
C
|
|
1627
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1628
|
+
|
|
1629
|
+
SUBROUTINE VIRIALTENSORS (potx,potz,xkinr,xkinth,xkinph,
|
|
1630
|
+
& xkinRc,xkinz,xkinx)
|
|
1631
|
+
C
|
|
1632
|
+
C Calculate the tensors for potential and kinemtic energy, and write
|
|
1633
|
+
C the results to the screen.
|
|
1634
|
+
C
|
|
1635
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1636
|
+
C
|
|
1637
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
1638
|
+
C
|
|
1639
|
+
e2 = 1.0D0 - (q*q)
|
|
1640
|
+
e2 = MAX(e2,1.0D-20)
|
|
1641
|
+
C
|
|
1642
|
+
potx = 0.0D0
|
|
1643
|
+
potz = 0.0D0
|
|
1644
|
+
prefln = PREFACLN(0,0,0)
|
|
1645
|
+
DO k=0,KMAXARR(0,0,0)
|
|
1646
|
+
dk = DBLE(k)
|
|
1647
|
+
addxln = prefln + COFARR(k,0,0,0) + (dk*LOG(e2)) +
|
|
1648
|
+
& betaln(2.0D0+dk,0.5D0)
|
|
1649
|
+
addzln = prefln + COFARR(k,0,0,0) + (dk*LOG(e2)) +
|
|
1650
|
+
& betaln(1.0D0+dk,1.5D0)
|
|
1651
|
+
potx = potx - (0.5D0*EXPP(addxln))
|
|
1652
|
+
potz = potz - EXPP(addzln)
|
|
1653
|
+
END DO
|
|
1654
|
+
C
|
|
1655
|
+
xkinr = 0.0D0
|
|
1656
|
+
xkinr1 = 0.0D0
|
|
1657
|
+
xkinr2 = 0.0D0
|
|
1658
|
+
prefln = PREFACLN(2,0,0)
|
|
1659
|
+
DO k=0,KMAXARR(2,0,0)
|
|
1660
|
+
dk = DBLE(k)
|
|
1661
|
+
addln = prefln + COFARR(k,2,0,0) + (dk*LOG(e2)) +
|
|
1662
|
+
& betaln(1.0D0+dk,0.5D0)
|
|
1663
|
+
addln1 = prefln + COFARR(k,2,0,0) + (dk*LOG(e2)) +
|
|
1664
|
+
& betaln(2.0D0+dk,0.5D0)
|
|
1665
|
+
addln2 = prefln + COFARR(k,2,0,0) + (dk*LOG(e2)) +
|
|
1666
|
+
& betaln(1.0D0+dk,1.5D0)
|
|
1667
|
+
xkinr = xkinr + EXPP(addln)
|
|
1668
|
+
xkinr1 = xkinr1 + EXPP(addln1)
|
|
1669
|
+
xkinr2 = xkinr2 + EXPP(addln2)
|
|
1670
|
+
END DO
|
|
1671
|
+
C
|
|
1672
|
+
xkinth = 0.0D0
|
|
1673
|
+
xkinth1 = 0.0D0
|
|
1674
|
+
xkinth2 = 0.0D0
|
|
1675
|
+
prefln = PREFACLN(0,2,0)
|
|
1676
|
+
DO k=0,KMAXARR(0,2,0)
|
|
1677
|
+
dk = DBLE(k)
|
|
1678
|
+
addln = prefln + COFARR(k,0,2,0) + (dk*LOG(e2)) +
|
|
1679
|
+
& betaln(1.0D0+dk,0.5D0)
|
|
1680
|
+
addln1 = prefln + COFARR(k,0,2,0) + (dk*LOG(e2)) +
|
|
1681
|
+
& betaln(2.0D0+dk,0.5D0)
|
|
1682
|
+
addln2 = prefln + COFARR(k,0,2,0) + (dk*LOG(e2)) +
|
|
1683
|
+
& betaln(1.0D0+dk,1.5D0)
|
|
1684
|
+
xkinth = xkinth + EXPP(addln)
|
|
1685
|
+
xkinth1 = xkinth1 + EXPP(addln1)
|
|
1686
|
+
xkinth2 = xkinth2 + EXPP(addln2)
|
|
1687
|
+
END DO
|
|
1688
|
+
C
|
|
1689
|
+
xkinph = 0.0D0
|
|
1690
|
+
prefln = PREFACLN(0,0,2)
|
|
1691
|
+
DO k=0,KMAXARR(0,0,2)
|
|
1692
|
+
dk = DBLE(k)
|
|
1693
|
+
addln = prefln + COFARR(k,0,0,2) + (dk*LOG(e2)) +
|
|
1694
|
+
& betaln(1.0D0+dk,0.5D0)
|
|
1695
|
+
xkinph = xkinph + EXPP(addln)
|
|
1696
|
+
END DO
|
|
1697
|
+
C
|
|
1698
|
+
xkinRc = xkinr1 + xkinth2
|
|
1699
|
+
xkinz = xkinr2 + xkinth1
|
|
1700
|
+
xkinx = 0.5D0 * (xkinRc+xkinph)
|
|
1701
|
+
C
|
|
1702
|
+
END
|
|
1703
|
+
|
|
1704
|
+
|
|
1705
|
+
REAL*8 FUNCTION RHOVELMOMTHAV(lr,lth,lph)
|
|
1706
|
+
C
|
|
1707
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1708
|
+
C
|
|
1709
|
+
C The function RHOVELMOMTHAV calculates rho times the
|
|
1710
|
+
C intrinsic velocity moment of a given order, integrated over
|
|
1711
|
+
C a spherical shell of unit radius.
|
|
1712
|
+
C
|
|
1713
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1714
|
+
C
|
|
1715
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1716
|
+
C
|
|
1717
|
+
PARAMETER (pi=3.14159265358979D0)
|
|
1718
|
+
C
|
|
1719
|
+
COMMON /howint/ iint
|
|
1720
|
+
C
|
|
1721
|
+
COMMON /curorders/ lrcur,lthcur,lphcur
|
|
1722
|
+
C
|
|
1723
|
+
C Common block that holds copies of the orders with which this
|
|
1724
|
+
C function is called.
|
|
1725
|
+
C
|
|
1726
|
+
EXTERNAL TOINTMER,MIDPNT
|
|
1727
|
+
C
|
|
1728
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
1729
|
+
C
|
|
1730
|
+
lrcur = lr
|
|
1731
|
+
lthcur = lth
|
|
1732
|
+
lphcur = lph
|
|
1733
|
+
C
|
|
1734
|
+
IF (iint.EQ.0) THEN
|
|
1735
|
+
CALL QROMO (TOINTMER,0.0D0,0.5D0*pi,SS,MIDPNT)
|
|
1736
|
+
ELSE
|
|
1737
|
+
CALL QGAUSLEG (TOINTMER,0.0D0,0.5D0*pi,SS)
|
|
1738
|
+
END IF
|
|
1739
|
+
C
|
|
1740
|
+
RHOVELMOMTHAV = SS
|
|
1741
|
+
C
|
|
1742
|
+
END
|
|
1743
|
+
|
|
1744
|
+
|
|
1745
|
+
REAL*8 FUNCTION TOINTMER (theta)
|
|
1746
|
+
C
|
|
1747
|
+
C The function that must be integrated to get the integral over a spherical
|
|
1748
|
+
C shell of rho times the intrinsic velocity moment of the orders given by
|
|
1749
|
+
C /curorders/.
|
|
1750
|
+
C
|
|
1751
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1752
|
+
C
|
|
1753
|
+
COMMON /curorders/ lrcur,lthcur,lphcur
|
|
1754
|
+
C
|
|
1755
|
+
TOINTMER = SIN(theta) * RHOVELMOM(theta,lrcur,lthcur,lphcur)
|
|
1756
|
+
C
|
|
1757
|
+
END
|
|
1758
|
+
|
|
1759
|
+
|
|
1760
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1761
|
+
C
|
|
1762
|
+
C The function RHOVELMOM calculates rho times intrinsic velocity momemnt
|
|
1763
|
+
C of a given order. This is a prefactor times a power series in
|
|
1764
|
+
C e^2 SIN^2(theta). The (ln of the) prefactor is calculated by PREFACLN.
|
|
1765
|
+
C The subroutines COFARR and KMAXARR allow the power series
|
|
1766
|
+
C to be reconstructed, by reading values from the arrays allcofs and
|
|
1767
|
+
C kmaxall, in the common block /all/. These arrays must have been filled
|
|
1768
|
+
C previously in the main program, using the subroutine CALCCOEFFLN.
|
|
1769
|
+
C This subroutine calls the function COEFFLN for each term in the series.
|
|
1770
|
+
C
|
|
1771
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
1772
|
+
|
|
1773
|
+
REAL*8 FUNCTION RHOVELMOM(theta,lr,lth,lph)
|
|
1774
|
+
C
|
|
1775
|
+
C Calculates the rho times velocity moment of order (lr,lth,lph).
|
|
1776
|
+
C The fractional accuracy is eps. The polar angle theta must be given
|
|
1777
|
+
C in radians. The dimensionless radius is assumed to be unity.
|
|
1778
|
+
C
|
|
1779
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1780
|
+
C
|
|
1781
|
+
PARAMETER (eps = 1.0D-10)
|
|
1782
|
+
C
|
|
1783
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
1784
|
+
C
|
|
1785
|
+
DIMENSION cofs(0:1000)
|
|
1786
|
+
C
|
|
1787
|
+
IF ((2*(lr/2).NE.lr).OR.(2*(lth/2).NE.lth)) THEN
|
|
1788
|
+
RHOVELMOM = 0.0D0
|
|
1789
|
+
RETURN
|
|
1790
|
+
END IF
|
|
1791
|
+
C
|
|
1792
|
+
kmax = KMAXARR(lr,lth,lph)
|
|
1793
|
+
DO k=0,kmax
|
|
1794
|
+
cofs(k) = COFARR(k,lr,lth,lph)
|
|
1795
|
+
END DO
|
|
1796
|
+
C
|
|
1797
|
+
prefln = PREFACLN(lr,lth,lph)
|
|
1798
|
+
C
|
|
1799
|
+
e2 = 1.0D0 - (q*q)
|
|
1800
|
+
s2 = (SIN(theta))**2.0D0
|
|
1801
|
+
C
|
|
1802
|
+
k = 0
|
|
1803
|
+
xnewadd = EXPP(cofs(0))
|
|
1804
|
+
sum = xnewadd
|
|
1805
|
+
epsab = eps*EXPP(cofs(0))
|
|
1806
|
+
C
|
|
1807
|
+
IF ((e2*s2).GE.1.0D-12) THEN
|
|
1808
|
+
C
|
|
1809
|
+
35 k = k+1
|
|
1810
|
+
oldadd = xnewadd
|
|
1811
|
+
xnewadd = EXPP(cofs(k)+(DBLE(k)*LOG(e2*s2)))
|
|
1812
|
+
sum = sum + xnewadd
|
|
1813
|
+
IF ( (.NOT.((ABS(xnewadd).LE.epsab).AND.
|
|
1814
|
+
& (ABS(oldadd).LE.epsab))) .AND.
|
|
1815
|
+
& (k.LE.kmax) ) THEN
|
|
1816
|
+
GOTO 35
|
|
1817
|
+
END IF
|
|
1818
|
+
C
|
|
1819
|
+
END IF
|
|
1820
|
+
C
|
|
1821
|
+
IF (2*(lph/2).EQ.lph) THEN
|
|
1822
|
+
RHOVELMOM = EXPP(prefln) * sum
|
|
1823
|
+
ELSE
|
|
1824
|
+
IF (s2.LE.1.0D-12) THEN
|
|
1825
|
+
RHOVELMOM = 0.0D0
|
|
1826
|
+
ELSE
|
|
1827
|
+
RHOVELMOM = EXPP(prefln) * sum * ((2.0D0*eta)-1.0D0) *
|
|
1828
|
+
& (s2**alpha)
|
|
1829
|
+
END IF
|
|
1830
|
+
END IF
|
|
1831
|
+
C
|
|
1832
|
+
END
|
|
1833
|
+
|
|
1834
|
+
|
|
1835
|
+
REAL*8 FUNCTION PREFACLN(lr,lth,lph)
|
|
1836
|
+
C
|
|
1837
|
+
C Calculates the logarithm of the pre-factor by which the relevant
|
|
1838
|
+
C series must be multiplied to get the velocity moment
|
|
1839
|
+
C of order (lr,lth,lph). This function does not take into account the factor
|
|
1840
|
+
C (2 eta - 1) * (sin^2(theta))^{alpha} that must be added for the odd
|
|
1841
|
+
C moments.
|
|
1842
|
+
C
|
|
1843
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1844
|
+
C
|
|
1845
|
+
COMMON /potent/ ipot
|
|
1846
|
+
C
|
|
1847
|
+
C ipot=1 for Kepler potential and ipot=2 for logarithmic potential
|
|
1848
|
+
C
|
|
1849
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
1850
|
+
C
|
|
1851
|
+
IF ((2*(lr/2).NE.lr).OR.(2*(lth/2).NE.lth)) THEN
|
|
1852
|
+
PREFACLN = -100.0D0
|
|
1853
|
+
RETURN
|
|
1854
|
+
END IF
|
|
1855
|
+
C
|
|
1856
|
+
IF (2*(lph/2).EQ.lph) THEN
|
|
1857
|
+
alp = 0.0D0
|
|
1858
|
+
ELSE
|
|
1859
|
+
alp = alpha
|
|
1860
|
+
END IF
|
|
1861
|
+
C
|
|
1862
|
+
dlr = DBLE(lr)
|
|
1863
|
+
dlth = DBLE(lth)
|
|
1864
|
+
dlph = DBLE(lph)
|
|
1865
|
+
C
|
|
1866
|
+
PREFACLN = (gamma*LOG(q)) +
|
|
1867
|
+
& betaln(1.0D0+alp-beta+(0.5D0*(dlth+dlph)),
|
|
1868
|
+
& (0.5D0*(dlr+1.0D0))) +
|
|
1869
|
+
& betaln(alp+(0.5D0*(dlph+1.0D0)),(0.5D0*(dlth+1.0D0))) -
|
|
1870
|
+
& betaln(1.0D0-beta,0.5D0) - betaln(0.5D0,0.5D0)
|
|
1871
|
+
C
|
|
1872
|
+
IF (ipot.EQ.1) THEN
|
|
1873
|
+
PREFACLN = PREFACLN + (alp*LOG(4.0D0)) +
|
|
1874
|
+
& betaln(1.5D0-beta+alp+(0.5D0*(dlr+dlth+dlph)),
|
|
1875
|
+
& gamma-beta-0.5D0+alp) -
|
|
1876
|
+
& betaln(1.5D0-beta,gamma-beta-0.5D0)
|
|
1877
|
+
ELSE IF (ipot.EQ.2) THEN
|
|
1878
|
+
PREFACLN = PREFACLN + (alp*(1.0D0+LOG(2.0D0))) +
|
|
1879
|
+
& gammaln(1.5D0-beta+alp+(0.5D0*(dlr+dlth+dlph))) -
|
|
1880
|
+
& gammaln(1.5D0-beta)
|
|
1881
|
+
ELSE
|
|
1882
|
+
STOP 'ipot wrong value'
|
|
1883
|
+
END IF
|
|
1884
|
+
C
|
|
1885
|
+
END
|
|
1886
|
+
|
|
1887
|
+
|
|
1888
|
+
REAL*8 FUNCTION COFARR(k,lr,lth,lph)
|
|
1889
|
+
C
|
|
1890
|
+
C Get a value from the array allcofs
|
|
1891
|
+
C
|
|
1892
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1893
|
+
C
|
|
1894
|
+
PARAMETER (maxlength = 2000000 ,
|
|
1895
|
+
& mord = 200 ,
|
|
1896
|
+
& mev = mord/2 )
|
|
1897
|
+
C
|
|
1898
|
+
COMMON /all/ allcofs(1:maxlength),
|
|
1899
|
+
& icstart(0:mev,0:mev,0:mord),
|
|
1900
|
+
& kmaxall(0:mev,0:mev,0:mord),maxord
|
|
1901
|
+
C
|
|
1902
|
+
IF ((lr.GT.maxord).OR.(lth.GT.maxord).OR.
|
|
1903
|
+
& (lph.GT.maxord)) THEN
|
|
1904
|
+
STOP 'order to large in cofarr'
|
|
1905
|
+
END IF
|
|
1906
|
+
C
|
|
1907
|
+
IF ((2*(lr/2).NE.lr).OR.(2*(lth/2).NE.lth)) THEN
|
|
1908
|
+
COFARR = -100.0D0
|
|
1909
|
+
ELSE
|
|
1910
|
+
COFARR = allcofs(k+icstart(lr/2,lth/2,lph))
|
|
1911
|
+
END IF
|
|
1912
|
+
C
|
|
1913
|
+
END
|
|
1914
|
+
|
|
1915
|
+
|
|
1916
|
+
INTEGER FUNCTION KMAXARR(lr,lth,lph)
|
|
1917
|
+
C
|
|
1918
|
+
C Get a value from the array kmaxall
|
|
1919
|
+
C
|
|
1920
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1921
|
+
C
|
|
1922
|
+
PARAMETER (maxlength = 2000000 ,
|
|
1923
|
+
& mord = 200 ,
|
|
1924
|
+
& mev = mord/2 )
|
|
1925
|
+
C
|
|
1926
|
+
COMMON /all/ allcofs(1:maxlength),
|
|
1927
|
+
& icstart(0:mev,0:mev,0:mord),
|
|
1928
|
+
& kmaxall(0:mev,0:mev,0:mord),maxord
|
|
1929
|
+
C
|
|
1930
|
+
IF ((lr.GT.maxord).OR.(lth.GT.maxord).OR.
|
|
1931
|
+
& (lph.GT.maxord)) THEN
|
|
1932
|
+
STOP 'order too large in kmaxarr'
|
|
1933
|
+
END IF
|
|
1934
|
+
C
|
|
1935
|
+
IF ((2*(lr/2).NE.lr).OR.(2*(lth/2).NE.lth)) THEN
|
|
1936
|
+
KMAXARR = 0
|
|
1937
|
+
ELSE
|
|
1938
|
+
KMAXARR = kmaxall(lr/2,lth/2,lph)
|
|
1939
|
+
END IF
|
|
1940
|
+
C
|
|
1941
|
+
END
|
|
1942
|
+
|
|
1943
|
+
|
|
1944
|
+
SUBROUTINE CALCCOEFFLN(cofs,kmax,lr,lth,lph)
|
|
1945
|
+
C
|
|
1946
|
+
C Calculates the logarithm of coefficients in the hypergeometric series
|
|
1947
|
+
C that occurs in the expression for the velocity moment
|
|
1948
|
+
C of order (lr,lth,lph). The array cofs is filled up to order kmax,
|
|
1949
|
+
C which is determined by this subroutine so as to allow the
|
|
1950
|
+
C power series to be evaluated to a fractional accuracy eps.
|
|
1951
|
+
C
|
|
1952
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
1953
|
+
C
|
|
1954
|
+
PARAMETER (eps = 1.0D-10)
|
|
1955
|
+
C
|
|
1956
|
+
DIMENSION cofs(0:1000)
|
|
1957
|
+
C
|
|
1958
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
1959
|
+
COMMON /order/ llr,llth,llph
|
|
1960
|
+
C
|
|
1961
|
+
C Fill the common block order
|
|
1962
|
+
C
|
|
1963
|
+
llr = lr
|
|
1964
|
+
llth = lth
|
|
1965
|
+
llph = lph
|
|
1966
|
+
C
|
|
1967
|
+
e2 = 1.0D0 - (q*q)
|
|
1968
|
+
C
|
|
1969
|
+
k = 0
|
|
1970
|
+
cofs(0) = COEFFLN(0)
|
|
1971
|
+
xnewadd = EXPP(cofs(0))
|
|
1972
|
+
sum = xnewadd
|
|
1973
|
+
epsab = eps*EXPP(cofs(0))
|
|
1974
|
+
C
|
|
1975
|
+
IF (e2.GE.1.0D-20) THEN
|
|
1976
|
+
15 k = k+1
|
|
1977
|
+
oldadd = xnewadd
|
|
1978
|
+
cofs(k) = COEFFLN(k)
|
|
1979
|
+
xnewadd = EXPP(cofs(k)+(DBLE(k)*LOG(e2)))
|
|
1980
|
+
sum = sum + xnewadd
|
|
1981
|
+
IF ( (.NOT.((ABS(xnewadd).LE.epsab).AND.
|
|
1982
|
+
& (ABS(oldadd).LE.epsab))) .AND.
|
|
1983
|
+
& (k.LE.1000) ) THEN
|
|
1984
|
+
GOTO 15
|
|
1985
|
+
ELSE
|
|
1986
|
+
kmax = k
|
|
1987
|
+
END IF
|
|
1988
|
+
ELSE
|
|
1989
|
+
kmax = 0
|
|
1990
|
+
END IF
|
|
1991
|
+
C
|
|
1992
|
+
END
|
|
1993
|
+
|
|
1994
|
+
|
|
1995
|
+
REAL*8 FUNCTION COEFFLN(k)
|
|
1996
|
+
C
|
|
1997
|
+
C The logarithm of the k-th coefficient in the hypergeometric series
|
|
1998
|
+
C that occurs in the expression for the velocity moment
|
|
1999
|
+
C of order (lr,lth,lph) (as contained in the common block /order/)
|
|
2000
|
+
C
|
|
2001
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2002
|
+
C
|
|
2003
|
+
COMMON /potent/ ipot
|
|
2004
|
+
C
|
|
2005
|
+
C ipot=1 for Kepler potential and ipot=2 for logarithmic potential
|
|
2006
|
+
C
|
|
2007
|
+
COMMON /DFcase/ icase
|
|
2008
|
+
C
|
|
2009
|
+
C icase=1 for the case I DFs, icase=2 for the case II DFs.
|
|
2010
|
+
C
|
|
2011
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
2012
|
+
COMMON /order/ lr,lth,lph
|
|
2013
|
+
C
|
|
2014
|
+
IF ((2*(lr/2).NE.lr).OR.(2*(lth/2).NE.lth)) THEN
|
|
2015
|
+
COEFFLN = 0.0D0
|
|
2016
|
+
RETURN
|
|
2017
|
+
END IF
|
|
2018
|
+
C
|
|
2019
|
+
IF (2*(lph/2).EQ.lph) THEN
|
|
2020
|
+
alp = 0.0D0
|
|
2021
|
+
ELSE
|
|
2022
|
+
alp = alpha
|
|
2023
|
+
END IF
|
|
2024
|
+
C
|
|
2025
|
+
dk = DBLE(k)
|
|
2026
|
+
dlr = DBLE(lr)
|
|
2027
|
+
dlth = DBLE(lth)
|
|
2028
|
+
dlph = DBLE(lph)
|
|
2029
|
+
C
|
|
2030
|
+
COEFFLN = pochln(0.5D0*gamma,k) - gammaln(dk+1.0D0) +
|
|
2031
|
+
& pochln(alp+(0.5D0*(dlph+1.0D0)),k) -
|
|
2032
|
+
& pochln(0.5D0,k) +
|
|
2033
|
+
& pochln(1.0D0,k) -
|
|
2034
|
+
& pochln(1.0D0+alp+(0.5D0*(dlth+dlph)),k)
|
|
2035
|
+
C
|
|
2036
|
+
IF (icase.EQ.1) THEN
|
|
2037
|
+
C
|
|
2038
|
+
IF (ipot.EQ.1) THEN
|
|
2039
|
+
COEFFLN = COEFFLN +
|
|
2040
|
+
& pochln(1.0D0-beta+alp+(0.5D0*(dlth+dlph)),k) -
|
|
2041
|
+
& pochln(1.0D0-beta,k) +
|
|
2042
|
+
& pochln(gamma-0.5D0-beta+alp,k) -
|
|
2043
|
+
& pochln(gamma-0.5D0-beta,k) +
|
|
2044
|
+
& pochln((0.5D0*(gamma+1.0D0))-beta,k) -
|
|
2045
|
+
& pochln((0.5D0*(gamma+1.0D0))-beta+alp+
|
|
2046
|
+
& (0.25D0*(dlr+dlth+dlph)),k) +
|
|
2047
|
+
& pochln(1.0D0-beta+(0.5D0*gamma),k) -
|
|
2048
|
+
& pochln(1.0D0-beta+(0.5D0*gamma)+alp+
|
|
2049
|
+
& (0.25D0*(dlr+dlth+dlph)),k)
|
|
2050
|
+
ELSE IF (ipot.EQ.2) THEN
|
|
2051
|
+
COEFFLN = COEFFLN +
|
|
2052
|
+
& pochln(1.0D0-beta+alp+(0.5D0*(dlth+dlph)),k) -
|
|
2053
|
+
& pochln(1.0D0-beta,k) +
|
|
2054
|
+
& ( (beta-1.5D0-dk-alp-(0.5D0*(dlr+dlth+dlph)))*
|
|
2055
|
+
& LOG(gamma-(2.0D0*beta)+(2.0D0*dk)+(2.0D0*alp)) ) -
|
|
2056
|
+
& ( (beta-1.5D0-dk)*
|
|
2057
|
+
& LOG(gamma-(2.0D0*beta)+(2.0D0*dk)) )
|
|
2058
|
+
ELSE
|
|
2059
|
+
STOP 'ipot wrong value'
|
|
2060
|
+
END IF
|
|
2061
|
+
C
|
|
2062
|
+
ELSE IF (icase.EQ.2) THEN
|
|
2063
|
+
C
|
|
2064
|
+
IF (ipot.EQ.1) THEN
|
|
2065
|
+
C
|
|
2066
|
+
C In this case the prefactor is the entire value of coeffln
|
|
2067
|
+
C
|
|
2068
|
+
ELSE IF (ipot.EQ.2) THEN
|
|
2069
|
+
C
|
|
2070
|
+
C Note that this factor could also be put in the prefactor PREFACLN because
|
|
2071
|
+
C it is independent of k (or dk=DOUBLE(k))
|
|
2072
|
+
C
|
|
2073
|
+
COEFFLN = COEFFLN +
|
|
2074
|
+
& ( (beta-1.5D0-alp-(0.5D0*(dlr+dlth+dlph)))*
|
|
2075
|
+
& LOG(gamma-(2.0D0*beta)+(2.0D0*alp)) ) -
|
|
2076
|
+
& ( (beta-1.5D0)*
|
|
2077
|
+
& LOG(gamma-(2.0D0*beta)) )
|
|
2078
|
+
C
|
|
2079
|
+
ELSE
|
|
2080
|
+
STOP 'ipot wrong value'
|
|
2081
|
+
END IF
|
|
2082
|
+
C
|
|
2083
|
+
ELSE
|
|
2084
|
+
C
|
|
2085
|
+
STOP 'icase wrong value'
|
|
2086
|
+
C
|
|
2087
|
+
END IF
|
|
2088
|
+
C
|
|
2089
|
+
END
|
|
2090
|
+
|
|
2091
|
+
|
|
2092
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2093
|
+
C
|
|
2094
|
+
C The functions gammaln, betaln, pochln and binomln calculate (the ln of)
|
|
2095
|
+
C mathematical expressions that are often needed. They are all based
|
|
2096
|
+
C indirectly on the function gammln in Numerical recipes which is accurate
|
|
2097
|
+
C approximately to 1.0D-10.
|
|
2098
|
+
C
|
|
2099
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2100
|
+
|
|
2101
|
+
|
|
2102
|
+
REAL*8 FUNCTION gammaln(x)
|
|
2103
|
+
C
|
|
2104
|
+
C The logarithm of the gamma function
|
|
2105
|
+
C
|
|
2106
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2107
|
+
PARAMETER (pi=3.14159265358979D0)
|
|
2108
|
+
IF (x.GE.1.0D0) THEN
|
|
2109
|
+
gammaln = gammln(x)
|
|
2110
|
+
ELSE IF (x.GE.0.0D0) THEN
|
|
2111
|
+
z = 1.0D0 - x
|
|
2112
|
+
gammaln = (LOG((pi*z)/SIN(pi*z))) - gammln(2.0D0-x)
|
|
2113
|
+
ELSE
|
|
2114
|
+
STOP 'x < 0 in gammaln'
|
|
2115
|
+
END IF
|
|
2116
|
+
END
|
|
2117
|
+
|
|
2118
|
+
|
|
2119
|
+
REAL*8 FUNCTION betaln(x,y)
|
|
2120
|
+
C
|
|
2121
|
+
C The logarithm of the beta function
|
|
2122
|
+
C
|
|
2123
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2124
|
+
betaln = gammaln(x) + gammaln(y) - gammaln(x+y)
|
|
2125
|
+
END
|
|
2126
|
+
|
|
2127
|
+
|
|
2128
|
+
REAL*8 FUNCTION pochln(x,k)
|
|
2129
|
+
C
|
|
2130
|
+
C The logarithm of Pochhammer's symbol
|
|
2131
|
+
C
|
|
2132
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2133
|
+
pochln = gammaln(x+DBLE(k)) - gammaln(x)
|
|
2134
|
+
END
|
|
2135
|
+
|
|
2136
|
+
|
|
2137
|
+
REAL*8 FUNCTION binomln(j,k)
|
|
2138
|
+
C
|
|
2139
|
+
C The logarithm of the binomial coefficient (j over k)
|
|
2140
|
+
C
|
|
2141
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2142
|
+
dj = DBLE(j)
|
|
2143
|
+
dk = DBLE(k)
|
|
2144
|
+
binomln = gammaln(dj+1.0D0) - gammaln(dk+1.0D0) -
|
|
2145
|
+
& gammaln(dj-dk+1.0D0)
|
|
2146
|
+
END
|
|
2147
|
+
|
|
2148
|
+
|
|
2149
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2150
|
+
C
|
|
2151
|
+
C The function EXPP is used throughout rather than the normal function
|
|
2152
|
+
C EXP, to avoid underflow.
|
|
2153
|
+
C
|
|
2154
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2155
|
+
|
|
2156
|
+
REAL*8 FUNCTION EXPP(x)
|
|
2157
|
+
C
|
|
2158
|
+
C Modified exponential function that will not underflow
|
|
2159
|
+
C
|
|
2160
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2161
|
+
IF (x.GE.-500D0) THEN
|
|
2162
|
+
EXPP = EXP(x)
|
|
2163
|
+
ELSE
|
|
2164
|
+
EXPP = 0.0D0
|
|
2165
|
+
END IF
|
|
2166
|
+
END
|
|
2167
|
+
|
|
2168
|
+
|
|
2169
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2170
|
+
C
|
|
2171
|
+
C A regularized vanderMonde matrix solver
|
|
2172
|
+
C
|
|
2173
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2174
|
+
|
|
2175
|
+
|
|
2176
|
+
SUBROUTINE REG_VANDER (x,w,q,n,xlam)
|
|
2177
|
+
C
|
|
2178
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2179
|
+
C
|
|
2180
|
+
C Solves a VanderMonde matrix with regularization.
|
|
2181
|
+
C Arguments are as in de subroutine VANDER from Numerical Recipes.
|
|
2182
|
+
C The input variable xlam is the regularization parameter.
|
|
2183
|
+
C
|
|
2184
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2185
|
+
C
|
|
2186
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2187
|
+
C
|
|
2188
|
+
INTEGER n,NMAX
|
|
2189
|
+
DIMENSION q(n),w(n),x(n)
|
|
2190
|
+
C
|
|
2191
|
+
PARAMETER (NMAX=101)
|
|
2192
|
+
C
|
|
2193
|
+
DIMENSION A(NMAX,NMAX), Anorm(NMAX,NMAX), H(NMAX,NMAX),
|
|
2194
|
+
& Areg(NMAX,NMAX), bnorm(NMAX), indx(NMAX)
|
|
2195
|
+
C
|
|
2196
|
+
CCCCCCCCCCCCCCCCCCCC
|
|
2197
|
+
C
|
|
2198
|
+
C Set up the matrix that occurs in the matrix equation that is to be solved.
|
|
2199
|
+
C
|
|
2200
|
+
DO i=1,n
|
|
2201
|
+
DO j=1,n
|
|
2202
|
+
A(i,j) = x(j)**(i-1)
|
|
2203
|
+
END DO
|
|
2204
|
+
END DO
|
|
2205
|
+
C
|
|
2206
|
+
C Calculate the matrix Atr*A that occurs in the normal equations.
|
|
2207
|
+
C
|
|
2208
|
+
DO i=1,n
|
|
2209
|
+
DO j=1,n
|
|
2210
|
+
Anorm(i,j) = 0.0D0
|
|
2211
|
+
DO k=1,n
|
|
2212
|
+
Anorm(i,j) = Anorm(i,j) + (A(k,i)*A(k,j))
|
|
2213
|
+
END DO
|
|
2214
|
+
END DO
|
|
2215
|
+
END DO
|
|
2216
|
+
C
|
|
2217
|
+
C Calculate the right-hand side vector Atr*q that occurs in the normal
|
|
2218
|
+
C equations.
|
|
2219
|
+
C
|
|
2220
|
+
DO i=1,n
|
|
2221
|
+
bnorm(i) = 0.0D0
|
|
2222
|
+
DO k=1,n
|
|
2223
|
+
bnorm(i) = bnorm(i) + (A(k,i)*q(k))
|
|
2224
|
+
END DO
|
|
2225
|
+
END DO
|
|
2226
|
+
C
|
|
2227
|
+
C Set up the desired regularization matrix H
|
|
2228
|
+
C
|
|
2229
|
+
CALL REGMAT2 (H,n,NMAX)
|
|
2230
|
+
C
|
|
2231
|
+
C Calculate the equipartition xlambda
|
|
2232
|
+
C
|
|
2233
|
+
Anormtr = 0.0D0
|
|
2234
|
+
Htr = 0.0D0
|
|
2235
|
+
DO i=1,n
|
|
2236
|
+
Anormtr = Anormtr + Anorm(i,i)
|
|
2237
|
+
Htr = Htr + H(i,i)
|
|
2238
|
+
END DO
|
|
2239
|
+
C
|
|
2240
|
+
xlameq = Anormtr / Htr
|
|
2241
|
+
C
|
|
2242
|
+
C Construct the regularized matrix
|
|
2243
|
+
C
|
|
2244
|
+
DO i=1,n
|
|
2245
|
+
DO j=1,n
|
|
2246
|
+
Areg(i,j) = Anorm(i,j) + (xlam*xlameq*H(i,j))
|
|
2247
|
+
END DO
|
|
2248
|
+
END DO
|
|
2249
|
+
C
|
|
2250
|
+
C The system to be solved is now: Areg*w = bnorm. The solution is found
|
|
2251
|
+
C with LU decomposition.
|
|
2252
|
+
C
|
|
2253
|
+
CALL LUDCMP (Areg,n,NMAX,indx,d)
|
|
2254
|
+
CALL LUBKSB (Areg,n,NMAX,indx,bnorm)
|
|
2255
|
+
C
|
|
2256
|
+
C The answer returned in bnorm is assigned to the vector w
|
|
2257
|
+
C
|
|
2258
|
+
DO i=1,n
|
|
2259
|
+
w(i) = bnorm(i)
|
|
2260
|
+
END DO
|
|
2261
|
+
C
|
|
2262
|
+
END
|
|
2263
|
+
|
|
2264
|
+
|
|
2265
|
+
SUBROUTINE REGMAT0 (H,n,np)
|
|
2266
|
+
C
|
|
2267
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2268
|
+
C
|
|
2269
|
+
C Set up a zeroth order regularization matrix
|
|
2270
|
+
C
|
|
2271
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2272
|
+
C
|
|
2273
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2274
|
+
C
|
|
2275
|
+
DIMENSION H(np,np)
|
|
2276
|
+
C
|
|
2277
|
+
IF (n.LE.2) STOP 'Matrix too small in REGMAT0'
|
|
2278
|
+
C
|
|
2279
|
+
DO i=1,n
|
|
2280
|
+
DO j=1,n
|
|
2281
|
+
H(i,j) = 0.0D0
|
|
2282
|
+
END DO
|
|
2283
|
+
END DO
|
|
2284
|
+
C
|
|
2285
|
+
H(1,1) = 1.0D0
|
|
2286
|
+
H(1,2) = -1.0D0
|
|
2287
|
+
C
|
|
2288
|
+
DO i=2,n-1
|
|
2289
|
+
H(i,i-1) = -1.0D0
|
|
2290
|
+
H(i,i) = 2.0D0
|
|
2291
|
+
H(i,i+1) = -1.0D0
|
|
2292
|
+
END DO
|
|
2293
|
+
C
|
|
2294
|
+
H(n,n-1) = -1.0D0
|
|
2295
|
+
H(n,n) = 1.0D0
|
|
2296
|
+
C
|
|
2297
|
+
END
|
|
2298
|
+
|
|
2299
|
+
|
|
2300
|
+
SUBROUTINE REGMAT1 (H,n,np)
|
|
2301
|
+
C
|
|
2302
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2303
|
+
C
|
|
2304
|
+
C Set up a first order regularization matrix
|
|
2305
|
+
C
|
|
2306
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2307
|
+
C
|
|
2308
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2309
|
+
C
|
|
2310
|
+
DIMENSION H(np,np)
|
|
2311
|
+
C
|
|
2312
|
+
IF (n.LE.4) STOP 'Matrix too small in REGMAT1'
|
|
2313
|
+
C
|
|
2314
|
+
DO i=1,n
|
|
2315
|
+
DO j=1,n
|
|
2316
|
+
H(i,j) = 0.0D0
|
|
2317
|
+
END DO
|
|
2318
|
+
END DO
|
|
2319
|
+
C
|
|
2320
|
+
H(1,1) = 1.0D0
|
|
2321
|
+
H(1,2) = -2.0D0
|
|
2322
|
+
H(1,3) = 1.0D0
|
|
2323
|
+
C
|
|
2324
|
+
H(2,1) = -2.0D0
|
|
2325
|
+
H(2,2) = 5.0D0
|
|
2326
|
+
H(2,3) = -4.0D0
|
|
2327
|
+
H(2,4) = 1.0D0
|
|
2328
|
+
C
|
|
2329
|
+
DO i=3,n-2
|
|
2330
|
+
H(i,i-2) = 1.0D0
|
|
2331
|
+
H(i,i-1) = -4.0D0
|
|
2332
|
+
H(i,i) = 6.0D0
|
|
2333
|
+
H(i,i+1) = -4.0D0
|
|
2334
|
+
H(i,i+2) = 1.0D0
|
|
2335
|
+
END DO
|
|
2336
|
+
C
|
|
2337
|
+
H(n-1,n-3) = 1.0D0
|
|
2338
|
+
H(n-1,n-2) = -4.0D0
|
|
2339
|
+
H(n-1,n-1) = 5.0D0
|
|
2340
|
+
H(n-1,n) = -2.0D0
|
|
2341
|
+
C
|
|
2342
|
+
H(n,n-2) = 1.0D0
|
|
2343
|
+
H(n,n-1) = -2.0D0
|
|
2344
|
+
H(n,n) = 1.0D0
|
|
2345
|
+
C
|
|
2346
|
+
END
|
|
2347
|
+
|
|
2348
|
+
|
|
2349
|
+
SUBROUTINE REGMAT2 (H,n,np)
|
|
2350
|
+
C
|
|
2351
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2352
|
+
C
|
|
2353
|
+
C Set up a second order regularization matrix
|
|
2354
|
+
C
|
|
2355
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2356
|
+
C
|
|
2357
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2358
|
+
C
|
|
2359
|
+
DIMENSION H(np,np)
|
|
2360
|
+
C
|
|
2361
|
+
IF (n.LE.6) STOP 'Matrix too small in REGMAT2'
|
|
2362
|
+
C
|
|
2363
|
+
DO i=1,n
|
|
2364
|
+
DO j=1,n
|
|
2365
|
+
H(i,j) = 0.0D0
|
|
2366
|
+
END DO
|
|
2367
|
+
END DO
|
|
2368
|
+
C
|
|
2369
|
+
H(1,1) = 1.0D0
|
|
2370
|
+
H(1,2) = -3.0D0
|
|
2371
|
+
H(1,3) = 3.0D0
|
|
2372
|
+
H(1,4) = -1.0D0
|
|
2373
|
+
C
|
|
2374
|
+
H(2,1) = -3.0D0
|
|
2375
|
+
H(2,2) = 10.0D0
|
|
2376
|
+
H(2,3) = -12.0D0
|
|
2377
|
+
H(2,4) = 6.0D0
|
|
2378
|
+
H(2,5) = -1.0D0
|
|
2379
|
+
C
|
|
2380
|
+
H(3,1) = 3.0D0
|
|
2381
|
+
H(3,2) = -12.0D0
|
|
2382
|
+
H(3,3) = 19.0D0
|
|
2383
|
+
H(3,4) = -15.0D0
|
|
2384
|
+
H(3,5) = 6.0D0
|
|
2385
|
+
H(3,6) = -1.0D0
|
|
2386
|
+
C
|
|
2387
|
+
DO i=4,n-3
|
|
2388
|
+
H(i,i-3) = -1.0D0
|
|
2389
|
+
H(i,i-2) = 6.0D0
|
|
2390
|
+
H(i,i-1) = -15.0D0
|
|
2391
|
+
H(i,i) = 20.0D0
|
|
2392
|
+
H(i,i+1) = -15.0D0
|
|
2393
|
+
H(i,i+2) = 6.0D0
|
|
2394
|
+
H(i,i+3) = -1.0D0
|
|
2395
|
+
END DO
|
|
2396
|
+
C
|
|
2397
|
+
H(n-2,n-5) = -1.0D0
|
|
2398
|
+
H(n-2,n-4) = 6.0D0
|
|
2399
|
+
H(n-2,n-3) = -15.0D0
|
|
2400
|
+
H(n-2,n-2) = 19.0D0
|
|
2401
|
+
H(n-2,n-1) = -12.0D0
|
|
2402
|
+
H(n-2,n) = 3.0D0
|
|
2403
|
+
C
|
|
2404
|
+
H(n-1,n-4) = -1.0D0
|
|
2405
|
+
H(n-1,n-3) = 6.0D0
|
|
2406
|
+
H(n-1,n-2) = -12.0D0
|
|
2407
|
+
H(n-1,n-1) = 10.0D0
|
|
2408
|
+
H(n-1,n) = -3.0D0
|
|
2409
|
+
C
|
|
2410
|
+
H(n,n-3) = -1.0D0
|
|
2411
|
+
H(n,n-2) = 3.0D0
|
|
2412
|
+
H(n,n-1) = -3.0D0
|
|
2413
|
+
H(n,n) = 1.0D0
|
|
2414
|
+
C
|
|
2415
|
+
END
|
|
2416
|
+
|
|
2417
|
+
|
|
2418
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2419
|
+
C
|
|
2420
|
+
C Required routines from Numerical recipes. All were modified to
|
|
2421
|
+
C be double precision. The parameter eps in QROMO determines the
|
|
2422
|
+
C speed of the program in calculating the VP parameters. Best results
|
|
2423
|
+
C are obtained with eps=1.0D-8, but this leads to a slow program.
|
|
2424
|
+
C
|
|
2425
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2426
|
+
|
|
2427
|
+
|
|
2428
|
+
REAL*8 FUNCTION gammln(x)
|
|
2429
|
+
C
|
|
2430
|
+
C Modified to be double precision
|
|
2431
|
+
C
|
|
2432
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2433
|
+
INTEGER j
|
|
2434
|
+
DIMENSION cof(6)
|
|
2435
|
+
SAVE cof,stp
|
|
2436
|
+
DATA cof,stp/76.18009172947146d0,-86.50532032941677d0,
|
|
2437
|
+
*24.01409824083091d0,-1.231739572450155d0,.1208650973866179d-2,
|
|
2438
|
+
*-.5395239384953d-5,2.5066282746310005d0/
|
|
2439
|
+
y=x
|
|
2440
|
+
tmp=x+5.5d0
|
|
2441
|
+
tmp=(x+0.5d0)*log(tmp)-tmp
|
|
2442
|
+
ser=1.000000000190015d0
|
|
2443
|
+
do 11 j=1,6
|
|
2444
|
+
y=y+1.d0
|
|
2445
|
+
ser=ser+cof(j)/y
|
|
2446
|
+
11 continue
|
|
2447
|
+
gammln=tmp+log(stp*ser/x)
|
|
2448
|
+
return
|
|
2449
|
+
END
|
|
2450
|
+
|
|
2451
|
+
|
|
2452
|
+
SUBROUTINE qgausleg(func,a,b,ss)
|
|
2453
|
+
C
|
|
2454
|
+
C Modified version of qgaus. Common block /gleg/ must have been
|
|
2455
|
+
C filled previously
|
|
2456
|
+
C
|
|
2457
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2458
|
+
REAL*8 a,b,ss,func
|
|
2459
|
+
EXTERNAL func
|
|
2460
|
+
COMMON /gleg/ qx(300),qw(300),nGL
|
|
2461
|
+
ss = 0.0D0
|
|
2462
|
+
DO i=1,nGL
|
|
2463
|
+
ss = ss + (qw(i)*func(a+(qx(i)*(b-a))))
|
|
2464
|
+
END DO
|
|
2465
|
+
ss = ss*(b-a)
|
|
2466
|
+
END
|
|
2467
|
+
|
|
2468
|
+
|
|
2469
|
+
SUBROUTINE gauleg(x1,x2,x,w,n)
|
|
2470
|
+
C
|
|
2471
|
+
C Modified to be double precision
|
|
2472
|
+
C
|
|
2473
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2474
|
+
INTEGER n
|
|
2475
|
+
REAL*8 x1,x2,x(n),w(n)
|
|
2476
|
+
PARAMETER (EPS=3.0D-14)
|
|
2477
|
+
INTEGER i,j,m
|
|
2478
|
+
m=(n+1)/2
|
|
2479
|
+
xm=0.5d0*(x2+x1)
|
|
2480
|
+
xl=0.5d0*(x2-x1)
|
|
2481
|
+
do 12 i=1,m
|
|
2482
|
+
z=cos(3.141592654d0*(i-.25d0)/(n+.5d0))
|
|
2483
|
+
1 continue
|
|
2484
|
+
p1=1.d0
|
|
2485
|
+
p2=0.d0
|
|
2486
|
+
do 11 j=1,n
|
|
2487
|
+
p3=p2
|
|
2488
|
+
p2=p1
|
|
2489
|
+
p1=((2.d0*j-1.d0)*z*p2-(j-1.d0)*p3)/j
|
|
2490
|
+
11 continue
|
|
2491
|
+
pp=n*(z*p1-p2)/(z*z-1.d0)
|
|
2492
|
+
z1=z
|
|
2493
|
+
z=z1-p1/pp
|
|
2494
|
+
if(abs(z-z1).gt.EPS)goto 1
|
|
2495
|
+
x(i)=xm-xl*z
|
|
2496
|
+
x(n+1-i)=xm+xl*z
|
|
2497
|
+
w(i)=2.d0*xl/((1.d0-z*z)*pp*pp)
|
|
2498
|
+
w(n+1-i)=w(i)
|
|
2499
|
+
12 continue
|
|
2500
|
+
return
|
|
2501
|
+
END
|
|
2502
|
+
|
|
2503
|
+
|
|
2504
|
+
SUBROUTINE qromo(func,a,b,ss,choose)
|
|
2505
|
+
C
|
|
2506
|
+
C Modified to be double precision, and to receive eps from common block
|
|
2507
|
+
C
|
|
2508
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2509
|
+
INTEGER JMAX,JMAXP,K,KM
|
|
2510
|
+
REAL*8 a,b,func,ss,EPS
|
|
2511
|
+
COMMON /romoeps/ eps
|
|
2512
|
+
EXTERNAL func,choose
|
|
2513
|
+
PARAMETER (JMAX=14, JMAXP=JMAX+1, K=5, KM=K-1)
|
|
2514
|
+
CU USES polint
|
|
2515
|
+
INTEGER j
|
|
2516
|
+
REAL*8 dss,h(JMAXP),s(JMAXP)
|
|
2517
|
+
h(1)=1.0D0
|
|
2518
|
+
do 11 j=1,JMAX
|
|
2519
|
+
call choose(func,a,b,s(j),j)
|
|
2520
|
+
if (j.ge.K) then
|
|
2521
|
+
call polint(h(j-KM),s(j-KM),K,0.0D0,ss,dss)
|
|
2522
|
+
if (abs(dss).le.EPS*abs(ss)) return
|
|
2523
|
+
endif
|
|
2524
|
+
s(j+1)=s(j)
|
|
2525
|
+
h(j+1)=h(j)/9.0D0
|
|
2526
|
+
11 continue
|
|
2527
|
+
STOP 'too many steps in qromo'
|
|
2528
|
+
END
|
|
2529
|
+
|
|
2530
|
+
|
|
2531
|
+
SUBROUTINE trapzd(func,a,b,s,n)
|
|
2532
|
+
C
|
|
2533
|
+
C Modified to be double precision
|
|
2534
|
+
C
|
|
2535
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2536
|
+
INTEGER n
|
|
2537
|
+
REAL*8 a,b,s,func
|
|
2538
|
+
EXTERNAL func
|
|
2539
|
+
INTEGER it,j
|
|
2540
|
+
REAL*8 del,sum,tnm,x
|
|
2541
|
+
if (n.eq.1) then
|
|
2542
|
+
s=0.5D0*(b-a)*(func(a)+func(b))
|
|
2543
|
+
else
|
|
2544
|
+
it=2**(n-2)
|
|
2545
|
+
tnm=it
|
|
2546
|
+
del=(b-a)/tnm
|
|
2547
|
+
x=a+0.5D0*del
|
|
2548
|
+
sum=0.0D0
|
|
2549
|
+
do 11 j=1,it
|
|
2550
|
+
sum=sum+func(x)
|
|
2551
|
+
x=x+del
|
|
2552
|
+
11 continue
|
|
2553
|
+
s=0.5D0*(s+(b-a)*sum/tnm)
|
|
2554
|
+
endif
|
|
2555
|
+
return
|
|
2556
|
+
END
|
|
2557
|
+
|
|
2558
|
+
|
|
2559
|
+
SUBROUTINE polint(xa,ya,n,x,y,dy)
|
|
2560
|
+
C
|
|
2561
|
+
C Modified to be double precision
|
|
2562
|
+
C
|
|
2563
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2564
|
+
INTEGER n,NMAX
|
|
2565
|
+
REAL*8 dy,x,y,xa(n),ya(n)
|
|
2566
|
+
PARAMETER (NMAX=10)
|
|
2567
|
+
INTEGER i,m,ns
|
|
2568
|
+
REAL*8 den,dif,dift,ho,hp,w,c(NMAX),d(NMAX)
|
|
2569
|
+
ns=1
|
|
2570
|
+
dif=abs(x-xa(1))
|
|
2571
|
+
do 11 i=1,n
|
|
2572
|
+
dift=abs(x-xa(i))
|
|
2573
|
+
if (dift.lt.dif) then
|
|
2574
|
+
ns=i
|
|
2575
|
+
dif=dift
|
|
2576
|
+
endif
|
|
2577
|
+
c(i)=ya(i)
|
|
2578
|
+
d(i)=ya(i)
|
|
2579
|
+
11 continue
|
|
2580
|
+
y=ya(ns)
|
|
2581
|
+
ns=ns-1
|
|
2582
|
+
do 13 m=1,n-1
|
|
2583
|
+
do 12 i=1,n-m
|
|
2584
|
+
ho=xa(i)-x
|
|
2585
|
+
hp=xa(i+m)-x
|
|
2586
|
+
w=c(i+1)-d(i)
|
|
2587
|
+
den=ho-hp
|
|
2588
|
+
if(den.eq.0.0D0)STOP 'failure in polint'
|
|
2589
|
+
den=w/den
|
|
2590
|
+
d(i)=hp*den
|
|
2591
|
+
c(i)=ho*den
|
|
2592
|
+
12 continue
|
|
2593
|
+
if (2*ns.lt.n-m)then
|
|
2594
|
+
dy=c(ns+1)
|
|
2595
|
+
else
|
|
2596
|
+
dy=d(ns)
|
|
2597
|
+
ns=ns-1
|
|
2598
|
+
endif
|
|
2599
|
+
y=y+dy
|
|
2600
|
+
13 continue
|
|
2601
|
+
return
|
|
2602
|
+
END
|
|
2603
|
+
|
|
2604
|
+
|
|
2605
|
+
SUBROUTINE midpnt(func,a,b,s,n)
|
|
2606
|
+
C
|
|
2607
|
+
C Modified to be double precision
|
|
2608
|
+
C
|
|
2609
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2610
|
+
INTEGER n
|
|
2611
|
+
REAL*8 a,b,s,func
|
|
2612
|
+
EXTERNAL func
|
|
2613
|
+
INTEGER it,j
|
|
2614
|
+
REAL*8 ddel,del,sum,tnm,x
|
|
2615
|
+
if (n.eq.1) then
|
|
2616
|
+
s=(b-a)*func(0.5D0*(a+b))
|
|
2617
|
+
else
|
|
2618
|
+
it=3**(n-2)
|
|
2619
|
+
tnm=it
|
|
2620
|
+
del=(b-a)/(3.0D0*tnm)
|
|
2621
|
+
ddel=del+del
|
|
2622
|
+
x=a+0.5D0*del
|
|
2623
|
+
sum=0.0D0
|
|
2624
|
+
do 11 j=1,it
|
|
2625
|
+
sum=sum+func(x)
|
|
2626
|
+
x=x+ddel
|
|
2627
|
+
sum=sum+func(x)
|
|
2628
|
+
x=x+del
|
|
2629
|
+
11 continue
|
|
2630
|
+
s=(s+(b-a)*sum/tnm)/3.0D0
|
|
2631
|
+
endif
|
|
2632
|
+
return
|
|
2633
|
+
END
|
|
2634
|
+
|
|
2635
|
+
|
|
2636
|
+
SUBROUTINE vander(x,w,q,n)
|
|
2637
|
+
C
|
|
2638
|
+
C Modified to be double precision
|
|
2639
|
+
C
|
|
2640
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2641
|
+
INTEGER n,NMAX
|
|
2642
|
+
DIMENSION q(n),w(n),x(n)
|
|
2643
|
+
PARAMETER (NMAX=101)
|
|
2644
|
+
INTEGER i,j,k,k1
|
|
2645
|
+
DOUBLE PRECISION b,s,t,xx,c(NMAX)
|
|
2646
|
+
if(n.eq.1)then
|
|
2647
|
+
w(1)=q(1)
|
|
2648
|
+
else
|
|
2649
|
+
do 11 i=1,n
|
|
2650
|
+
c(i)=0.d0
|
|
2651
|
+
11 continue
|
|
2652
|
+
c(n)=-x(1)
|
|
2653
|
+
do 13 i=2,n
|
|
2654
|
+
xx=-x(i)
|
|
2655
|
+
do 12 j=n+1-i,n-1
|
|
2656
|
+
c(j)=c(j)+xx*c(j+1)
|
|
2657
|
+
12 continue
|
|
2658
|
+
c(n)=c(n)+xx
|
|
2659
|
+
13 continue
|
|
2660
|
+
do 15 i=1,n
|
|
2661
|
+
xx=x(i)
|
|
2662
|
+
t=1.d0
|
|
2663
|
+
b=1.d0
|
|
2664
|
+
s=q(n)
|
|
2665
|
+
k=n
|
|
2666
|
+
do 14 j=2,n
|
|
2667
|
+
k1=k-1
|
|
2668
|
+
b=c(k)+xx*b
|
|
2669
|
+
s=s+q(k1)*b
|
|
2670
|
+
t=xx*t+b
|
|
2671
|
+
k=k1
|
|
2672
|
+
14 continue
|
|
2673
|
+
w(i)=s/t
|
|
2674
|
+
15 continue
|
|
2675
|
+
endif
|
|
2676
|
+
return
|
|
2677
|
+
END
|
|
2678
|
+
|
|
2679
|
+
|
|
2680
|
+
SUBROUTINE amoeba(p,y,mp,np,ndim,ftol,funk,iter)
|
|
2681
|
+
C
|
|
2682
|
+
C Modified to be double precision
|
|
2683
|
+
C
|
|
2684
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2685
|
+
INTEGER iter,mp,ndim,np,NMAX,ITMAX
|
|
2686
|
+
REAL*8 ftol,p(mp,np),y(mp),funk
|
|
2687
|
+
PARAMETER (NMAX=20,ITMAX=5000)
|
|
2688
|
+
EXTERNAL funk
|
|
2689
|
+
CU USES amotry,funk
|
|
2690
|
+
INTEGER i,ihi,ilo,inhi,j,m,n
|
|
2691
|
+
REAL*8 rtol,sum,swap,ysave,ytry,psum(NMAX),amotry
|
|
2692
|
+
iter=0
|
|
2693
|
+
1 do 12 n=1,ndim
|
|
2694
|
+
sum=0.0D0
|
|
2695
|
+
do 11 m=1,ndim+1
|
|
2696
|
+
sum=sum+p(m,n)
|
|
2697
|
+
11 continue
|
|
2698
|
+
psum(n)=sum
|
|
2699
|
+
12 continue
|
|
2700
|
+
2 ilo=1
|
|
2701
|
+
if (y(1).gt.y(2)) then
|
|
2702
|
+
ihi=1
|
|
2703
|
+
inhi=2
|
|
2704
|
+
else
|
|
2705
|
+
ihi=2
|
|
2706
|
+
inhi=1
|
|
2707
|
+
endif
|
|
2708
|
+
do 13 i=1,ndim+1
|
|
2709
|
+
if(y(i).le.y(ilo)) ilo=i
|
|
2710
|
+
if(y(i).gt.y(ihi)) then
|
|
2711
|
+
inhi=ihi
|
|
2712
|
+
ihi=i
|
|
2713
|
+
else if(y(i).gt.y(inhi)) then
|
|
2714
|
+
if(i.ne.ihi) inhi=i
|
|
2715
|
+
endif
|
|
2716
|
+
13 continue
|
|
2717
|
+
rtol=2.0D0*abs(y(ihi)-y(ilo))/(abs(y(ihi))+abs(y(ilo)))
|
|
2718
|
+
if (rtol.lt.ftol) then
|
|
2719
|
+
swap=y(1)
|
|
2720
|
+
y(1)=y(ilo)
|
|
2721
|
+
y(ilo)=swap
|
|
2722
|
+
do 14 n=1,ndim
|
|
2723
|
+
swap=p(1,n)
|
|
2724
|
+
p(1,n)=p(ilo,n)
|
|
2725
|
+
p(ilo,n)=swap
|
|
2726
|
+
14 continue
|
|
2727
|
+
return
|
|
2728
|
+
endif
|
|
2729
|
+
C
|
|
2730
|
+
C Possibility to write intermediate results
|
|
2731
|
+
C
|
|
2732
|
+
C WRITE (*,'(I5,4F15.8)') iter,(p(ilo,j),j=1,3),y(ilo)
|
|
2733
|
+
C
|
|
2734
|
+
if (iter.ge.ITMAX) then
|
|
2735
|
+
write (*,*) 'ITMAX exceeded in amoeba'
|
|
2736
|
+
return
|
|
2737
|
+
endif
|
|
2738
|
+
iter=iter+2
|
|
2739
|
+
ytry=amotry(p,y,psum,mp,np,ndim,funk,ihi,-1.0D0)
|
|
2740
|
+
if (ytry.le.y(ilo)) then
|
|
2741
|
+
ytry=amotry(p,y,psum,mp,np,ndim,funk,ihi,2.0D0)
|
|
2742
|
+
else if (ytry.ge.y(inhi)) then
|
|
2743
|
+
ysave=y(ihi)
|
|
2744
|
+
ytry=amotry(p,y,psum,mp,np,ndim,funk,ihi,0.5D0)
|
|
2745
|
+
if (ytry.ge.ysave) then
|
|
2746
|
+
do 16 i=1,ndim+1
|
|
2747
|
+
if(i.ne.ilo)then
|
|
2748
|
+
do 15 j=1,ndim
|
|
2749
|
+
psum(j)=0.5D0*(p(i,j)+p(ilo,j))
|
|
2750
|
+
p(i,j)=psum(j)
|
|
2751
|
+
15 continue
|
|
2752
|
+
y(i)=funk(psum)
|
|
2753
|
+
endif
|
|
2754
|
+
16 continue
|
|
2755
|
+
iter=iter+ndim
|
|
2756
|
+
goto 1
|
|
2757
|
+
endif
|
|
2758
|
+
else
|
|
2759
|
+
iter=iter-1
|
|
2760
|
+
endif
|
|
2761
|
+
goto 2
|
|
2762
|
+
END
|
|
2763
|
+
|
|
2764
|
+
|
|
2765
|
+
REAL*8 FUNCTION amotry(p,y,psum,mp,np,ndim,funk,ihi,fac)
|
|
2766
|
+
C
|
|
2767
|
+
C Modified to be double precision
|
|
2768
|
+
C
|
|
2769
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2770
|
+
INTEGER ihi,mp,ndim,np,NMAX
|
|
2771
|
+
REAL*8 fac,p(mp,np),psum(np),y(mp),funk
|
|
2772
|
+
PARAMETER (NMAX=20)
|
|
2773
|
+
EXTERNAL funk
|
|
2774
|
+
CU USES funk
|
|
2775
|
+
INTEGER j
|
|
2776
|
+
REAL*8 fac1,fac2,ytry,ptry(NMAX)
|
|
2777
|
+
fac1=(1.0D0-fac)/ndim
|
|
2778
|
+
fac2=fac1-fac
|
|
2779
|
+
do 11 j=1,ndim
|
|
2780
|
+
ptry(j)=psum(j)*fac1-p(ihi,j)*fac2
|
|
2781
|
+
11 continue
|
|
2782
|
+
ytry=funk(ptry)
|
|
2783
|
+
if (ytry.lt.y(ihi)) then
|
|
2784
|
+
y(ihi)=ytry
|
|
2785
|
+
do 12 j=1,ndim
|
|
2786
|
+
psum(j)=psum(j)-p(ihi,j)+ptry(j)
|
|
2787
|
+
p(ihi,j)=ptry(j)
|
|
2788
|
+
12 continue
|
|
2789
|
+
endif
|
|
2790
|
+
amotry=ytry
|
|
2791
|
+
return
|
|
2792
|
+
END
|
|
2793
|
+
|
|
2794
|
+
|
|
2795
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2796
|
+
C
|
|
2797
|
+
C Numerical Recipes routines, transformed to double precision, for
|
|
2798
|
+
C Regularized VanderMonde matrix solution.
|
|
2799
|
+
C
|
|
2800
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2801
|
+
|
|
2802
|
+
SUBROUTINE ludcmp(a,n,np,indx,d)
|
|
2803
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2804
|
+
INTEGER n,np,indx(n),NMAX
|
|
2805
|
+
REAL*8 d,a(np,np),TINY
|
|
2806
|
+
PARAMETER (NMAX=500,TINY=1.0D-20)
|
|
2807
|
+
INTEGER i,imax,j,k
|
|
2808
|
+
REAL*8 aamax,dum,sum,vv(NMAX)
|
|
2809
|
+
d=1.0D0
|
|
2810
|
+
do 12 i=1,n
|
|
2811
|
+
aamax=0.0D0
|
|
2812
|
+
do 11 j=1,n
|
|
2813
|
+
if (abs(a(i,j)).gt.aamax) aamax=abs(a(i,j))
|
|
2814
|
+
11 continue
|
|
2815
|
+
if (aamax.eq.0.0D0) STOP 'singular matrix in ludcmp'
|
|
2816
|
+
vv(i)=1.0D0/aamax
|
|
2817
|
+
12 continue
|
|
2818
|
+
do 19 j=1,n
|
|
2819
|
+
do 14 i=1,j-1
|
|
2820
|
+
sum=a(i,j)
|
|
2821
|
+
do 13 k=1,i-1
|
|
2822
|
+
sum=sum-a(i,k)*a(k,j)
|
|
2823
|
+
13 continue
|
|
2824
|
+
a(i,j)=sum
|
|
2825
|
+
14 continue
|
|
2826
|
+
aamax=0.0D0
|
|
2827
|
+
do 16 i=j,n
|
|
2828
|
+
sum=a(i,j)
|
|
2829
|
+
do 15 k=1,j-1
|
|
2830
|
+
sum=sum-a(i,k)*a(k,j)
|
|
2831
|
+
15 continue
|
|
2832
|
+
a(i,j)=sum
|
|
2833
|
+
dum=vv(i)*abs(sum)
|
|
2834
|
+
if (dum.ge.aamax) then
|
|
2835
|
+
imax=i
|
|
2836
|
+
aamax=dum
|
|
2837
|
+
endif
|
|
2838
|
+
16 continue
|
|
2839
|
+
if (j.ne.imax)then
|
|
2840
|
+
do 17 k=1,n
|
|
2841
|
+
dum=a(imax,k)
|
|
2842
|
+
a(imax,k)=a(j,k)
|
|
2843
|
+
a(j,k)=dum
|
|
2844
|
+
17 continue
|
|
2845
|
+
d=-d
|
|
2846
|
+
vv(imax)=vv(j)
|
|
2847
|
+
endif
|
|
2848
|
+
indx(j)=imax
|
|
2849
|
+
if(a(j,j).eq.0.0D0)a(j,j)=TINY
|
|
2850
|
+
if(j.ne.n)then
|
|
2851
|
+
dum=1.0D0/a(j,j)
|
|
2852
|
+
do 18 i=j+1,n
|
|
2853
|
+
a(i,j)=a(i,j)*dum
|
|
2854
|
+
18 continue
|
|
2855
|
+
endif
|
|
2856
|
+
19 continue
|
|
2857
|
+
return
|
|
2858
|
+
END
|
|
2859
|
+
|
|
2860
|
+
|
|
2861
|
+
SUBROUTINE lubksb(a,n,np,indx,b)
|
|
2862
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2863
|
+
INTEGER n,np,indx(n)
|
|
2864
|
+
REAL*8 a(np,np),b(n)
|
|
2865
|
+
INTEGER i,ii,j,ll
|
|
2866
|
+
REAL*8 sum
|
|
2867
|
+
ii=0
|
|
2868
|
+
do 12 i=1,n
|
|
2869
|
+
ll=indx(i)
|
|
2870
|
+
sum=b(ll)
|
|
2871
|
+
b(ll)=b(i)
|
|
2872
|
+
if (ii.ne.0)then
|
|
2873
|
+
do 11 j=ii,i-1
|
|
2874
|
+
sum=sum-a(i,j)*b(j)
|
|
2875
|
+
11 continue
|
|
2876
|
+
else if (sum.ne.0.0D0) then
|
|
2877
|
+
ii=i
|
|
2878
|
+
endif
|
|
2879
|
+
b(i)=sum
|
|
2880
|
+
12 continue
|
|
2881
|
+
do 14 i=n,1,-1
|
|
2882
|
+
sum=b(i)
|
|
2883
|
+
do 13 j=i+1,n
|
|
2884
|
+
sum=sum-a(i,j)*b(j)
|
|
2885
|
+
13 continue
|
|
2886
|
+
b(i)=sum/a(i,i)
|
|
2887
|
+
14 continue
|
|
2888
|
+
return
|
|
2889
|
+
END
|
|
2890
|
+
|
|
2891
|
+
|
|
2892
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2893
|
+
C
|
|
2894
|
+
C All routines below are obsolete. However, they were kept because they
|
|
2895
|
+
C might turn out to be useful one day.
|
|
2896
|
+
C
|
|
2897
|
+
C The function densradius defines the relation r(theta) for an isodensity
|
|
2898
|
+
C surface. The SUBROUTINE CONTOUR_ANALYSIS finds the best-fitting ellipse
|
|
2899
|
+
C and does a Fourier analysis. In doing so it uses the Numerical Recipes
|
|
2900
|
+
C routines cosft1, four1 and realft, which were kept at single precision.
|
|
2901
|
+
C
|
|
2902
|
+
C The calling sequence from the main program is:
|
|
2903
|
+
C EXTERNAL DENSRADIUS
|
|
2904
|
+
C CALL CONTOUR_ANALYSIS (DENSRADIUS)
|
|
2905
|
+
C
|
|
2906
|
+
C In our model the density is always perfectly spheroidal, so the results
|
|
2907
|
+
C are rather uninteresting. However, CONTOUR_ANALYSIS can be used for any
|
|
2908
|
+
C function r(theta), so it could be used, e.g., to determine the shape
|
|
2909
|
+
C of the contours of the projected velocity dispersion on the sky.
|
|
2910
|
+
C
|
|
2911
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
2912
|
+
|
|
2913
|
+
REAL*8 FUNCTION DENSRADIUS (theta)
|
|
2914
|
+
C
|
|
2915
|
+
C The radius r of a point at polar angle theta, on the isodensity
|
|
2916
|
+
C surface with rho = 1.
|
|
2917
|
+
C
|
|
2918
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2919
|
+
C
|
|
2920
|
+
COMMON /param/ gamma, beta, q, alpha, eta
|
|
2921
|
+
C
|
|
2922
|
+
DENSRADIUS = RHOVELMOM(theta,0,0,0)**(1.0/gamma)
|
|
2923
|
+
C
|
|
2924
|
+
END
|
|
2925
|
+
|
|
2926
|
+
|
|
2927
|
+
SUBROUTINE CONTOUR_ANALYSIS (RADIUS)
|
|
2928
|
+
C
|
|
2929
|
+
C Given a function RADIUS, that returns a radius as function of polar angle
|
|
2930
|
+
C theta, do a shape analysis of the contour defined by this function. Four-fold
|
|
2931
|
+
C symmetry is assumed.
|
|
2932
|
+
C
|
|
2933
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
2934
|
+
C
|
|
2935
|
+
PARAMETER (pi=3.14159265358979D0)
|
|
2936
|
+
C
|
|
2937
|
+
EXTERNAL RADIUS
|
|
2938
|
+
C
|
|
2939
|
+
DIMENSION radarr(10000)
|
|
2940
|
+
REAL radreal(10000)
|
|
2941
|
+
C
|
|
2942
|
+
C Estimate the axis ratio by taking the ratio of points on the
|
|
2943
|
+
C major and minor axis
|
|
2944
|
+
C
|
|
2945
|
+
qest = RADIUS(0.0D0)/RADIUS(pi/2.0D0)
|
|
2946
|
+
C
|
|
2947
|
+
C We now write the radius to an array and Fourier analyse it.
|
|
2948
|
+
C Rather than using the conventional polar coordinates (r,theta), we
|
|
2949
|
+
C use elliptical coordinates, such that
|
|
2950
|
+
C R = s sin(tau)
|
|
2951
|
+
C z = s qcoord cos(tau)
|
|
2952
|
+
C
|
|
2953
|
+
N2pow = 256
|
|
2954
|
+
qcoord = qest
|
|
2955
|
+
C
|
|
2956
|
+
25 DO i=1,N2pow+1
|
|
2957
|
+
C
|
|
2958
|
+
C Choose tau, spaced linearly between 0 and pi/2.
|
|
2959
|
+
C
|
|
2960
|
+
tau = ((pi/2.0D0)/(DBLE(N2pow)))*DBLE(i-1)
|
|
2961
|
+
C
|
|
2962
|
+
C Calculate the correspinding theta
|
|
2963
|
+
C
|
|
2964
|
+
theta = ATAN(TAN(tau)/qcoord)
|
|
2965
|
+
st = SIN(theta)
|
|
2966
|
+
ct = COS(theta)
|
|
2967
|
+
C
|
|
2968
|
+
C Calculate the corresponding radius
|
|
2969
|
+
C
|
|
2970
|
+
radthet = RADIUS(theta)
|
|
2971
|
+
C
|
|
2972
|
+
C Calculate and store the corresponding elliptical radius
|
|
2973
|
+
C
|
|
2974
|
+
radarr(i) = radthet *
|
|
2975
|
+
& SQRT((st**2.0D0)+((ct/qcoord)**2.0D0))
|
|
2976
|
+
radreal(i) = REAL(radarr(i))
|
|
2977
|
+
C
|
|
2978
|
+
END DO
|
|
2979
|
+
C
|
|
2980
|
+
C Get the Fourier cosine decomposition of the array radarr. If the
|
|
2981
|
+
C contour is a perfect ellipse, the only the lowest order (constant)
|
|
2982
|
+
C term in the transfrom is non-zero. If the cos (2 tau) is non-zero, then
|
|
2983
|
+
C we should choose a different qcoord, and iterate.
|
|
2984
|
+
C
|
|
2985
|
+
CALL COSFT1(radreal,N2pow)
|
|
2986
|
+
C
|
|
2987
|
+
C radarr now contains the Fourier cosine series, which we properly normalize,
|
|
2988
|
+
C and make double precision again.
|
|
2989
|
+
C
|
|
2990
|
+
semimajor = DBLE(radreal(1))/DBLE(N2pow)
|
|
2991
|
+
radarr(1) = 1.0D0
|
|
2992
|
+
DO i=2,N2pow+1
|
|
2993
|
+
radarr(i) = 2.0D0*DBLE(radreal(i))/(DBLE(N2pow)*semimajor)
|
|
2994
|
+
END DO
|
|
2995
|
+
C
|
|
2996
|
+
C No verbose output on the screen please
|
|
2997
|
+
C
|
|
2998
|
+
iverb = 0
|
|
2999
|
+
IF (iverb.EQ.1) THEN
|
|
3000
|
+
WRITE (*,'(A5,F12.8)') ' ', semimajor
|
|
3001
|
+
DO i=1,5
|
|
3002
|
+
WRITE (*,'(I5,F12.8)') 2*(i-1),radarr(i)
|
|
3003
|
+
END DO
|
|
3004
|
+
WRITE (*,*) ' '
|
|
3005
|
+
END IF
|
|
3006
|
+
C
|
|
3007
|
+
C If the COS(2 tau) coefficient is too big, then change qcoord.
|
|
3008
|
+
C The formula for doing this is obtained by writing the equations
|
|
3009
|
+
C for a pure ellipse with axial ratio q, in elliptical coordinates
|
|
3010
|
+
C with axial ratio q'. After Fourier expanding the equation s'(tau'),
|
|
3011
|
+
C the cos(2 tau') coefficient is to lowest order directly related to (q/q').
|
|
3012
|
+
C
|
|
3013
|
+
IF (ABS(radarr(2)).GE.1.0D-8) THEN
|
|
3014
|
+
qcoord = qcoord * (1.0D0 + (2.0D0*radarr(2)))
|
|
3015
|
+
qcoord = MAX(0.0D0,MIN(qcoord,1.0D0))
|
|
3016
|
+
GOTO 25
|
|
3017
|
+
END IF
|
|
3018
|
+
C
|
|
3019
|
+
C Write results to the screen
|
|
3020
|
+
C
|
|
3021
|
+
WRITE (*,'(A45,F15.8)') 'Ratio major/minor of contour',qest
|
|
3022
|
+
WRITE (*,'(A45,F15.8)') 'axial ratio best fitting ellipse',
|
|
3023
|
+
& qcoord
|
|
3024
|
+
WRITE (*,'(A45,F15.8)') 'semi-major axis best fitting ellipse',
|
|
3025
|
+
& semimajor
|
|
3026
|
+
WRITE (*,'(A45,F15.8)') 'cos(4 theta) coefficient',
|
|
3027
|
+
& radarr(3)/radarr(1)
|
|
3028
|
+
WRITE (*,'(A45,F15.8)') 'cos(6 theta) coefficient',
|
|
3029
|
+
& radarr(4)/radarr(1)
|
|
3030
|
+
WRITE (*,'(A45,F15.8)') 'cos(8 theta) coefficient',
|
|
3031
|
+
& radarr(5)/radarr(1)
|
|
3032
|
+
C
|
|
3033
|
+
END
|
|
3034
|
+
|
|
3035
|
+
|
|
3036
|
+
SUBROUTINE realft(data,n,isign)
|
|
3037
|
+
INTEGER isign,n
|
|
3038
|
+
REAL data(n)
|
|
3039
|
+
CU USES four1
|
|
3040
|
+
INTEGER i,i1,i2,i3,i4,n2p3
|
|
3041
|
+
REAL c1,c2,h1i,h1r,h2i,h2r,wis,wrs
|
|
3042
|
+
DOUBLE PRECISION theta,wi,wpi,wpr,wr,wtemp
|
|
3043
|
+
theta=3.141592653589793d0/dble(n/2)
|
|
3044
|
+
c1=0.5
|
|
3045
|
+
if (isign.eq.1) then
|
|
3046
|
+
c2=-0.5
|
|
3047
|
+
call four1(data,n/2,+1)
|
|
3048
|
+
else
|
|
3049
|
+
c2=0.5
|
|
3050
|
+
theta=-theta
|
|
3051
|
+
endif
|
|
3052
|
+
wpr=-2.0d0*sin(0.5d0*theta)**2
|
|
3053
|
+
wpi=sin(theta)
|
|
3054
|
+
wr=1.0d0+wpr
|
|
3055
|
+
wi=wpi
|
|
3056
|
+
n2p3=n+3
|
|
3057
|
+
do 11 i=2,n/4
|
|
3058
|
+
i1=2*i-1
|
|
3059
|
+
i2=i1+1
|
|
3060
|
+
i3=n2p3-i2
|
|
3061
|
+
i4=i3+1
|
|
3062
|
+
wrs=sngl(wr)
|
|
3063
|
+
wis=sngl(wi)
|
|
3064
|
+
h1r=c1*(data(i1)+data(i3))
|
|
3065
|
+
h1i=c1*(data(i2)-data(i4))
|
|
3066
|
+
h2r=-c2*(data(i2)+data(i4))
|
|
3067
|
+
h2i=c2*(data(i1)-data(i3))
|
|
3068
|
+
data(i1)=h1r+wrs*h2r-wis*h2i
|
|
3069
|
+
data(i2)=h1i+wrs*h2i+wis*h2r
|
|
3070
|
+
data(i3)=h1r-wrs*h2r+wis*h2i
|
|
3071
|
+
data(i4)=-h1i+wrs*h2i+wis*h2r
|
|
3072
|
+
wtemp=wr
|
|
3073
|
+
wr=wr*wpr-wi*wpi+wr
|
|
3074
|
+
wi=wi*wpr+wtemp*wpi+wi
|
|
3075
|
+
11 continue
|
|
3076
|
+
if (isign.eq.1) then
|
|
3077
|
+
h1r=data(1)
|
|
3078
|
+
data(1)=h1r+data(2)
|
|
3079
|
+
data(2)=h1r-data(2)
|
|
3080
|
+
else
|
|
3081
|
+
h1r=data(1)
|
|
3082
|
+
data(1)=c1*(h1r+data(2))
|
|
3083
|
+
data(2)=c1*(h1r-data(2))
|
|
3084
|
+
call four1(data,n/2,-1)
|
|
3085
|
+
endif
|
|
3086
|
+
return
|
|
3087
|
+
END
|
|
3088
|
+
|
|
3089
|
+
|
|
3090
|
+
SUBROUTINE four1(data,nn,isign)
|
|
3091
|
+
INTEGER isign,nn
|
|
3092
|
+
REAL data(2*nn)
|
|
3093
|
+
INTEGER i,istep,j,m,mmax,n
|
|
3094
|
+
REAL tempi,tempr
|
|
3095
|
+
DOUBLE PRECISION theta,wi,wpi,wpr,wr,wtemp
|
|
3096
|
+
n=2*nn
|
|
3097
|
+
j=1
|
|
3098
|
+
do 11 i=1,n,2
|
|
3099
|
+
if(j.gt.i)then
|
|
3100
|
+
tempr=data(j)
|
|
3101
|
+
tempi=data(j+1)
|
|
3102
|
+
data(j)=data(i)
|
|
3103
|
+
data(j+1)=data(i+1)
|
|
3104
|
+
data(i)=tempr
|
|
3105
|
+
data(i+1)=tempi
|
|
3106
|
+
endif
|
|
3107
|
+
m=n/2
|
|
3108
|
+
1 if ((m.ge.2).and.(j.gt.m)) then
|
|
3109
|
+
j=j-m
|
|
3110
|
+
m=m/2
|
|
3111
|
+
goto 1
|
|
3112
|
+
endif
|
|
3113
|
+
j=j+m
|
|
3114
|
+
11 continue
|
|
3115
|
+
mmax=2
|
|
3116
|
+
2 if (n.gt.mmax) then
|
|
3117
|
+
istep=2*mmax
|
|
3118
|
+
theta=6.28318530717959d0/(isign*mmax)
|
|
3119
|
+
wpr=-2.d0*sin(0.5d0*theta)**2
|
|
3120
|
+
wpi=sin(theta)
|
|
3121
|
+
wr=1.d0
|
|
3122
|
+
wi=0.d0
|
|
3123
|
+
do 13 m=1,mmax,2
|
|
3124
|
+
do 12 i=m,n,istep
|
|
3125
|
+
j=i+mmax
|
|
3126
|
+
tempr=sngl(wr)*data(j)-sngl(wi)*data(j+1)
|
|
3127
|
+
tempi=sngl(wr)*data(j+1)+sngl(wi)*data(j)
|
|
3128
|
+
data(j)=data(i)-tempr
|
|
3129
|
+
data(j+1)=data(i+1)-tempi
|
|
3130
|
+
data(i)=data(i)+tempr
|
|
3131
|
+
data(i+1)=data(i+1)+tempi
|
|
3132
|
+
12 continue
|
|
3133
|
+
wtemp=wr
|
|
3134
|
+
wr=wr*wpr-wi*wpi+wr
|
|
3135
|
+
wi=wi*wpr+wtemp*wpi+wi
|
|
3136
|
+
13 continue
|
|
3137
|
+
mmax=istep
|
|
3138
|
+
goto 2
|
|
3139
|
+
endif
|
|
3140
|
+
return
|
|
3141
|
+
END
|
|
3142
|
+
|
|
3143
|
+
|
|
3144
|
+
SUBROUTINE cosft1(y,n)
|
|
3145
|
+
INTEGER n
|
|
3146
|
+
REAL y(n+1)
|
|
3147
|
+
CU USES realft
|
|
3148
|
+
INTEGER j
|
|
3149
|
+
REAL sum,y1,y2
|
|
3150
|
+
DOUBLE PRECISION theta,wi,wpi,wpr,wr,wtemp
|
|
3151
|
+
theta=3.141592653589793d0/n
|
|
3152
|
+
wr=1.0d0
|
|
3153
|
+
wi=0.0d0
|
|
3154
|
+
wpr=-2.0d0*sin(0.5d0*theta)**2
|
|
3155
|
+
wpi=sin(theta)
|
|
3156
|
+
sum=0.5*(y(1)-y(n+1))
|
|
3157
|
+
y(1)=0.5*(y(1)+y(n+1))
|
|
3158
|
+
do 11 j=1,n/2-1
|
|
3159
|
+
wtemp=wr
|
|
3160
|
+
wr=wr*wpr-wi*wpi+wr
|
|
3161
|
+
wi=wi*wpr+wtemp*wpi+wi
|
|
3162
|
+
y1=0.5*(y(j+1)+y(n-j+1))
|
|
3163
|
+
y2=(y(j+1)-y(n-j+1))
|
|
3164
|
+
y(j+1)=y1-wi*y2
|
|
3165
|
+
y(n-j+1)=y1+wi*y2
|
|
3166
|
+
sum=sum+wr*y2
|
|
3167
|
+
11 continue
|
|
3168
|
+
call realft(y,n,+1)
|
|
3169
|
+
y(n+1)=y(2)
|
|
3170
|
+
y(2)=sum
|
|
3171
|
+
do 12 j=4,n,2
|
|
3172
|
+
sum=sum+y(j)
|
|
3173
|
+
y(j)=sum
|
|
3174
|
+
12 continue
|
|
3175
|
+
return
|
|
3176
|
+
END
|
|
3177
|
+
|
|
3178
|
+
|
|
3179
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
3180
|
+
C
|
|
3181
|
+
C Copies of routines already given above, but with slightly modified names,
|
|
3182
|
+
C to avoid recursive calling when evaluating double integrals.
|
|
3183
|
+
C
|
|
3184
|
+
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
3185
|
+
|
|
3186
|
+
SUBROUTINE qgauslegB(func,a,b,ss)
|
|
3187
|
+
C
|
|
3188
|
+
C Modified version of qgaus. Common block /gleg/ must have been
|
|
3189
|
+
C filled previously
|
|
3190
|
+
C
|
|
3191
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
3192
|
+
REAL*8 a,b,ss,func
|
|
3193
|
+
EXTERNAL func
|
|
3194
|
+
COMMON /gleg/ qx(300),qw(300),nGL
|
|
3195
|
+
ss = 0.0D0
|
|
3196
|
+
DO i=1,nGL
|
|
3197
|
+
ss = ss + (qw(i)*func(a+(qx(i)*(b-a))))
|
|
3198
|
+
END DO
|
|
3199
|
+
ss = ss*(b-a)
|
|
3200
|
+
END
|
|
3201
|
+
|
|
3202
|
+
|
|
3203
|
+
SUBROUTINE qromoB(func,a,b,ss,choose)
|
|
3204
|
+
C
|
|
3205
|
+
C Modified to be double precision, and to receive eps from common block
|
|
3206
|
+
C
|
|
3207
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
3208
|
+
INTEGER JMAX,JMAXP,K,KM
|
|
3209
|
+
REAL*8 a,b,func,ss,EPS
|
|
3210
|
+
COMMON /romoeps/ eps
|
|
3211
|
+
EXTERNAL func,choose
|
|
3212
|
+
PARAMETER (JMAX=14, JMAXP=JMAX+1, K=5, KM=K-1)
|
|
3213
|
+
CU USES polintB
|
|
3214
|
+
INTEGER j
|
|
3215
|
+
REAL*8 dss,h(JMAXP),s(JMAXP)
|
|
3216
|
+
h(1)=1.0D0
|
|
3217
|
+
do 11 j=1,JMAX
|
|
3218
|
+
call choose(func,a,b,s(j),j)
|
|
3219
|
+
if (j.ge.K) then
|
|
3220
|
+
call polintB(h(j-KM),s(j-KM),K,0.0D0,ss,dss)
|
|
3221
|
+
if (abs(dss).le.EPS*abs(ss)) return
|
|
3222
|
+
endif
|
|
3223
|
+
s(j+1)=s(j)
|
|
3224
|
+
h(j+1)=h(j)/9.0D0
|
|
3225
|
+
11 continue
|
|
3226
|
+
STOP 'too many steps in qromo'
|
|
3227
|
+
END
|
|
3228
|
+
|
|
3229
|
+
|
|
3230
|
+
SUBROUTINE polintB(xa,ya,n,x,y,dy)
|
|
3231
|
+
C
|
|
3232
|
+
C Modified to be double precision
|
|
3233
|
+
C
|
|
3234
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
3235
|
+
INTEGER n,NMAX
|
|
3236
|
+
REAL*8 dy,x,y,xa(n),ya(n)
|
|
3237
|
+
PARAMETER (NMAX=10)
|
|
3238
|
+
INTEGER i,m,ns
|
|
3239
|
+
REAL*8 den,dif,dift,ho,hp,w,c(NMAX),d(NMAX)
|
|
3240
|
+
ns=1
|
|
3241
|
+
dif=abs(x-xa(1))
|
|
3242
|
+
do 11 i=1,n
|
|
3243
|
+
dift=abs(x-xa(i))
|
|
3244
|
+
if (dift.lt.dif) then
|
|
3245
|
+
ns=i
|
|
3246
|
+
dif=dift
|
|
3247
|
+
endif
|
|
3248
|
+
c(i)=ya(i)
|
|
3249
|
+
d(i)=ya(i)
|
|
3250
|
+
11 continue
|
|
3251
|
+
y=ya(ns)
|
|
3252
|
+
ns=ns-1
|
|
3253
|
+
do 13 m=1,n-1
|
|
3254
|
+
do 12 i=1,n-m
|
|
3255
|
+
ho=xa(i)-x
|
|
3256
|
+
hp=xa(i+m)-x
|
|
3257
|
+
w=c(i+1)-d(i)
|
|
3258
|
+
den=ho-hp
|
|
3259
|
+
if(den.eq.0.0D0)STOP 'failure in polintB'
|
|
3260
|
+
den=w/den
|
|
3261
|
+
d(i)=hp*den
|
|
3262
|
+
c(i)=ho*den
|
|
3263
|
+
12 continue
|
|
3264
|
+
if (2*ns.lt.n-m)then
|
|
3265
|
+
dy=c(ns+1)
|
|
3266
|
+
else
|
|
3267
|
+
dy=d(ns)
|
|
3268
|
+
ns=ns-1
|
|
3269
|
+
endif
|
|
3270
|
+
y=y+dy
|
|
3271
|
+
13 continue
|
|
3272
|
+
return
|
|
3273
|
+
END
|
|
3274
|
+
|
|
3275
|
+
|
|
3276
|
+
SUBROUTINE midpntB(func,a,b,s,n)
|
|
3277
|
+
C
|
|
3278
|
+
C Modified to be double precision
|
|
3279
|
+
C
|
|
3280
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
3281
|
+
INTEGER n
|
|
3282
|
+
REAL*8 a,b,s,func
|
|
3283
|
+
EXTERNAL func
|
|
3284
|
+
INTEGER it,j
|
|
3285
|
+
REAL*8 ddel,del,sum,tnm,x
|
|
3286
|
+
if (n.eq.1) then
|
|
3287
|
+
s=(b-a)*func(0.5D0*(a+b))
|
|
3288
|
+
else
|
|
3289
|
+
it=3**(n-2)
|
|
3290
|
+
tnm=it
|
|
3291
|
+
del=(b-a)/(3.0D0*tnm)
|
|
3292
|
+
ddel=del+del
|
|
3293
|
+
x=a+0.5D0*del
|
|
3294
|
+
sum=0.0D0
|
|
3295
|
+
do 11 j=1,it
|
|
3296
|
+
sum=sum+func(x)
|
|
3297
|
+
x=x+ddel
|
|
3298
|
+
sum=sum+func(x)
|
|
3299
|
+
x=x+del
|
|
3300
|
+
11 continue
|
|
3301
|
+
s=(s+(b-a)*sum/tnm)/3.0D0
|
|
3302
|
+
endif
|
|
3303
|
+
return
|
|
3304
|
+
END
|
|
3305
|
+
|
|
3306
|
+
INTEGER FUNCTION LENSTR(str)
|
|
3307
|
+
C
|
|
3308
|
+
C Return effective length of a character string (trailing blanks removed).
|
|
3309
|
+
C Returns 0 for an all-blank string.
|
|
3310
|
+
C
|
|
3311
|
+
IMPLICIT REAL*8 (a-h,o-z)
|
|
3312
|
+
CHARACTER*(*) str
|
|
3313
|
+
INTEGER i
|
|
3314
|
+
LENSTR = LEN(str)
|
|
3315
|
+
DO i=LEN(str),1,-1
|
|
3316
|
+
IF (str(i:i).NE.' ') THEN
|
|
3317
|
+
LENSTR = i
|
|
3318
|
+
RETURN
|
|
3319
|
+
END IF
|
|
3320
|
+
END DO
|
|
3321
|
+
LENSTR = 0
|
|
3322
|
+
RETURN
|
|
3323
|
+
END
|