PLUME-MoM  1.0
Integralvolcanicplumemodel
 All Classes Files Functions Variables Pages
moments.f90
Go to the documentation of this file.
1 !********************************************************************************
3 !
9 !********************************************************************************
10 
12 
13  IMPLICIT NONE
14 
16  INTEGER :: n_nodes
17 
19  INTEGER, PARAMETER :: max_nmom = 20
20 
22  INTEGER :: n_mom
23 
24 CONTAINS
25 
26  !******************************************************************************
28  !
39  !******************************************************************************
40 
41  SUBROUTINE wheeler_algorithm(m,xi,w)
42 
43  IMPLICIT NONE
44 
45  REAL*8, DIMENSION(n_mom), INTENT(IN) :: m
46  REAL*8, DIMENSION(n_nodes), INTENT(OUT) :: xi
47  REAL*8, DIMENSION(n_nodes), INTENT(OUT) :: w
48 
49 
50  REAL*8, DIMENSION(n_nodes,n_nodes) :: jacobi
51  REAL*8, DIMENSION(n_nodes) :: d
52  REAL*8, DIMENSION(n_nodes-1) :: e
53 
54  REAL*8, DIMENSION(n_nodes) :: a , b
55  REAL*8, DIMENSION(n_nodes+1, 2*n_nodes) :: sigma
56 
57  REAL*8, DIMENSION(n_nodes,n_nodes) :: evec
58 
59  INTEGER :: i , l , k
60 
61  REAL*8, DIMENSION(2*n_nodes-2) :: work
62  INTEGER :: info
63  CHARACTER*1 :: jobz
64  INTEGER :: ldz
65 
66 
67  DO l=1,2*n_nodes-2
68 
69  sigma(1,l+1) = 0.0
70 
71  END DO
72 
73  DO l=0,2*n_nodes-1
74 
75  sigma(2,l+1) = m(l+1)
76 
77  END DO
78 
79  !
80  ! compute coefficients for Jacobi matrix
81  !
82 
83 
84  a(1) = m(2) / m(1)
85  b(1) = 0.d0
86 
87 
88  DO k=1,n_nodes-1
89 
90  DO l=k,2*n_nodes-k-1
91 
92  sigma(k+2,l+1) = sigma(k+1,l+2) - a(k) * sigma(k+1,l+1) - b(k) * &
93  sigma(k,l+1)
94 
95  a(k+1) = -sigma(k+1,k+1) / sigma(k+1,k) + sigma(k+2,k+2) / &
96  sigma(k+2,k+1)
97 
98  b(k+1) = sigma(k+2,k+1) / sigma(k+1,k)
99 
100  END DO
101 
102  END DO
103 
104  !
105  ! compute Jacobi matrix
106  !
107 
108  DO i=1,n_nodes
109 
110  jacobi(i,i) = a(i)
111 
112  d(i) = jacobi(i,i)
113 
114  END DO
115 
116  DO i=1,n_nodes-1
117 
118  jacobi(i,i+1) = -(abs(b(i+1)))**0.5
119  jacobi(i+1,i) = -(abs(b(i+1)))**0.5
120 
121  e(i) = jacobi(i,i+1)
122 
123  END DO
124 
125  !
126  ! compute eigenvalues and eigenvectors
127  !
128 
129  jobz = 'V' ! compute the eigenvectors
130 
131  ldz = n_nodes
132 
133  CALL dstev(jobz, n_nodes, d, e, evec, ldz, work, info)
134 
135  !
136  ! return weights
137  !
138 
139  DO i=1,n_nodes
140 
141  w(i) = evec(1,i)**2 * m(1)
142 
143  END DO
144 
145  !
146  ! return abscissas
147  !
148 
149  DO i=1,n_nodes
150 
151  xi(i) = d(i)
152 
153  END DO
154 
155  END SUBROUTINE wheeler_algorithm
156 
157  !******************************************************************************
159  !
169  !******************************************************************************
170 
171  SUBROUTINE moments_correction(m,iter)
172 
173  IMPLICIT NONE
174 
175  REAL*8, DIMENSION(:), INTENT(INOUT) :: m
176  INTEGER, INTENT(OUT) :: iter
177 
178  INTEGER :: iter_max
179 
180  REAL*8, DIMENSION(n_mom,n_mom) :: bk , bkk
181 
182  REAL*8, DIMENSION(n_mom,n_mom) :: d
183 
184  INTEGER :: i , j , k
185 
186  LOGICAL :: check_corr
187 
188  INTEGER :: k_star
189 
190  REAL*8, DIMENSION(n_mom) :: cos_quad_alfa
191 
192  REAL*8 :: lnck
193 
194  iter_max = 100
195 
196  !
197  ! define the unitary correction matrix
198  !
199  DO i = 1,n_mom
200 
201  DO j = 1,n_mom
202 
203  bkk(i,j) = 0.0
204 
205  END DO
206 
207  END DO
208 
209  DO k = 1,n_mom
210 
211  DO i = 1,n_mom
212 
213  IF ( i.EQ.k ) THEN
214 
215  bkk(i,1) = 1.d0
216 
217  ELSE
218 
219  bkk(i,1) = 0.0
220 
221  END IF
222 
223  END DO
224 
225  DO j=2,4
226 
227  DO i=1,n_mom-j+1
228 
229  bkk(i,j) = bkk(i+1,j-1) - bkk(i,j-1)
230 
231  END DO
232 
233  END DO
234 
235  DO i=1,n_mom
236 
237  bk(k,i) = bkk(i,4)
238 
239  END DO
240 
241  END DO
242 
243  check_corr = .true.
244  iter = 0
245 
246  ! start the correction loop
247 
248  DO WHILE ( ( check_corr ) .AND. ( iter .LT. iter_max ) )
249 
250  check_corr = .false.
251 
252  DO i = 1,n_mom
253 
254  d(i,1) = log(m(i))
255 
256  END DO
257 
258  DO j = 2,n_mom+1
259 
260  DO i = 1,n_mom-j+1
261 
262  d(i,j) = d(i+1,j-1) - d(i,j-1)
263 
264  IF ( ( j .EQ. 3 ) .AND. ( d(i,j) .LT. 0.d0 ) ) THEN
265 
266  check_corr = .true.
267 
268  END IF
269 
270  END DO
271  END DO
272 
273  IF ( check_corr ) THEN
274 
275  iter = iter + 1
276  k_star = 1
277 
278  DO k = 1,n_mom
279 
280  cos_quad_alfa(k) = ( ( dot_product( bk(k,:) , d(:,4) ) ) / &
281  ( sqrt( dot_product( bk(k,:) , bk(k,:) ) ) * &
282  sqrt( dot_product( d(:,4) , d(:,4) ) ) ) ) **2.d0
283 
284  IF ( cos_quad_alfa(k) .GE. cos_quad_alfa(k_star) ) THEN
285 
286  k_star = k
287 
288  END IF
289 
290  END DO
291 
292  lnck = -( dot_product( bk(k_star,:) , d(:,4) ) ) / &
293  dot_product( bk(k_star,:) , bk(k_star,:) )
294 
295  m(k_star) = dexp(lnck) * m(k_star)
296 
297  END IF
298 
299  END DO
300 
301  END SUBROUTINE moments_correction
302 
303  !******************************************************************************
305  !
314  !******************************************************************************
315 
316  REAL*8 FUNCTION beta_function(z,w)
317 
318  IMPLICIT NONE
319 
320  REAL*8, INTENT(IN):: w,z
321 
322  REAL*8:: gamln_z , gamln_w , gamln_zw
323 
324  gamln_z = gammln(z)
325  gamln_w = gammln(w)
326  gamln_zw = gammln(z+w)
327 
328  beta_function = dexp( gamln_z + gamln_w - gamln_zw )
329 
330  RETURN
331 
332  END FUNCTION beta_function
333 
334  !******************************************************************************
336  !
344  !******************************************************************************
345 
346  FUNCTION gammln(xx)
347 
348  IMPLICIT NONE
349 
350  REAL*8 :: gammln,xx
351 
352  INTEGER :: j
353 
354  REAL*8 :: ser , tmp , x , y , cof(14)
355 
356  cof(1) = 57.1562356658629235
357  cof(2) = -59.5979603554754912
358  cof(3) = 14.1360979747417471
359  cof(4) = -0.491913816097620199
360  cof(5) = 0.339946499848118887d-4
361  cof(6) = 0.465236289270485756d-4
362  cof(7) = -0.983744753048795646d-4
363  cof(8) = 0.158088703224912494d-3
364  cof(9) = -0.210264441724104883d-3
365  cof(10) = 0.217439618115212643d-3
366  cof(11) = -0.164318106536763890d-3
367  cof(12) = 0.844182239838527433d-4
368  cof(13) = -0.261908384015814087d-4
369  cof(14) = .368991826595316234d-5
370 
371  IF (xx .LE. 0) THEN
372 
373  WRITE(*,*) "bad arg in gammln"
374  RETURN
375 
376  END IF
377 
378  x = xx
379  y = x
380 
381  tmp = x + 5.2421875d0
382  tmp = ( x + 0.5d0 ) * log(tmp) - tmp
383 
384  ser = 0.999999999999997092
385 
386  DO j=1,14
387 
388  y = y+1.d0
389  ser = ser + cof(j)/y
390 
391  END DO
392 
393  gammln = tmp + log(2.5066282746310005*ser/x)
394 
395  RETURN
396 
397  END FUNCTION gammln
398 
399  !******************************************************************************
401  !
411  !******************************************************************************
412 
413 
414  SUBROUTINE coefficient(nmax,c)
415  IMPLICIT NONE
416 
417  ! This example evaluates the binomial coefficients c(n,m) and
418  ! stores the values in the matrix (array) c(n,m)
419  ! declarations
420  INTEGER :: n,m
421  INTEGER, INTENT(IN) :: nmax
422  ! specify the dimensions of the two dimensional array
423  ! (matrix) c(n,m).
424  INTEGER, DIMENSION(0:nmax,0:nmax), INTENT(OUT) :: c
425 
426  ! initialize array. Note how all elements are set to zero
427  ! by this one statement. Fortran90 has the facility to treat
428  ! arrays as single objects.
429  c = 0
430 
431  ! use recurrence relation c(n,m)=c(n-1,m-1) + c(n-1,m)
432  ! where m<n to generate elements
433 
434  c(0,0) = 1
435  c(1,0) = 1
436  c(1,1) = 1
437 
438  DO n = 2,nmax
439 
440  c(n,0) = 1
441  c(n,n) = 1
442 
443  DO m = 1,n-1
444 
445  c(n,m) = c(n-1,m-1) + c(n-1,m)
446 
447  END DO
448 
449  END DO
450 
451  RETURN
452 
453  END SUBROUTINE coefficient
454 
455 END MODULE moments_module
real *8 function gammln(xx)
Gamma function logarithm.
Definition: moments.f90:346
subroutine coefficient(nmax, c)
Binomial Coefficient.
Definition: moments.f90:414
subroutine moments_correction(m, iter)
Moments correction.
Definition: moments.f90:171
Method of Moments module.
Definition: moments.f90:11
real *8 function beta_function(z, w)
Beta function.
Definition: moments.f90:316
subroutine wheeler_algorithm(m, xi, w)
Wheeler algorithm.
Definition: moments.f90:41