Commit d1b0528b40d1b22a5e7f65da95939e13adc95a51

Authored by daniau
1 parent 7c27b9e1d2

git-svn-id: https://lxsd.femto-st.fr/svn/fvn@6 b657c933-2333-4658-acf2-d3c7c2708721

Showing 2 changed files with 3558 additions and 0 deletions Inline Diff

File was created 1
2 module fvn
3 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4 !
5 ! fvn : a f95 module replacement for some imsl routines
6 ! it uses lapack for linear algebra
7 ! it uses modified quadpack for integration
8 !
9 ! William Daniau 2007
10 ! william.daniau@femto-st.fr
11 !
12 ! Routines naming scheme :
13 !
14 ! fvn_x_name
15 ! where x can be s : real
16 ! d : real double precision
17 ! c : complex
18 ! z : double complex
19 !
20 !
21 ! This piece of code is totally free! Do whatever you want with it. However
22 ! if you find it usefull it would be kind to give credits ;-) Nevertheless, you
23 ! may give credits to quadpack authors.
24 !
25 ! Version 1.1
26 !
27 ! TO DO LIST :
28 ! + Order eigenvalues and vectors in decreasing eigenvalue's modulus order -> atm
29 ! eigenvalues are given with no particular order.
30 ! + Generic interface for fvn_x_name family -> fvn_name
31 ! + Make some parameters optional, status for example
32 ! + use f95 kinds "double complex" -> complex(kind=8)
33 ! + unify quadpack routines
34 ! + ...
35 !
36 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
37
38 implicit none
39 ! All quadpack routines are private to the module
40 private :: d1mach,dqag,dqag_2d_inner,dqag_2d_outer,dqage,dqage_2d_inner, &
41 dqage_2d_outer,dqk15,dqk15_2d_inner,dqk15_2d_outer,dqk21,dqk21_2d_inner,dqk21_2d_outer, &
42 dqk31,dqk31_2d_inner,dqk31_2d_outer,dqk41,dqk41_2d_inner,dqk41_2d_outer, &
43 dqk51,dqk51_2d_inner,dqk51_2d_outer,dqk61,dqk61_2d_inner,dqk61_2d_outer,dqpsrt
44
45
46 contains
47
48 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
49 !
50 ! Matrix inversion subroutines
51 !
52 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
53 subroutine fvn_s_matinv(d,a,inva,status)
54 !
55 ! Matrix inversion of a real matrix using BLAS and LAPACK
56 !
57 ! d (in) : matrix rank
58 ! a (in) : input matrix
59 ! inva (out) : inversed matrix
60 ! status (ou) : =0 if something failed
61 !
62 integer, intent(in) :: d
63 real, intent(in) :: a(d,d)
64 real, intent(out) :: inva(d,d)
65 integer, intent(out) :: status
66
67 integer, allocatable :: ipiv(:)
68 real, allocatable :: work(:)
69 real twork(1)
70 integer :: info
71 integer :: lwork
72
73 status=1
74
75 allocate(ipiv(d))
76 ! copy a into inva using BLAS
77 !call scopy(d*d,a,1,inva,1)
78 inva(:,:)=a(:,:)
79 ! LU factorization using LAPACK
80 call sgetrf(d,d,inva,d,ipiv,info)
81 ! if info is not equal to 0, something went wrong we exit setting status to 0
82 if (info /= 0) then
83 status=0
84 deallocate(ipiv)
85 return
86 end if
87 ! we use the query fonction of xxxtri to obtain the optimal workspace size
88 call sgetri(d,inva,d,ipiv,twork,-1,info)
89 lwork=int(twork(1))
90 allocate(work(lwork))
91 ! Matrix inversion using LAPACK
92 call sgetri(d,inva,d,ipiv,work,lwork,info)
93 ! again if info is not equal to 0, we exit setting status to 0
94 if (info /= 0) then
95 status=0
96 end if
97 deallocate(work)
98 deallocate(ipiv)
99 end subroutine
100
101 subroutine fvn_d_matinv(d,a,inva,status)
102 !
103 ! Matrix inversion of a double precision matrix using BLAS and LAPACK
104 !
105 ! d (in) : matrix rank
106 ! a (in) : input matrix
107 ! inva (out) : inversed matrix
108 ! status (ou) : =0 if something failed
109 !
110 integer, intent(in) :: d
111 double precision, intent(in) :: a(d,d)
112 double precision, intent(out) :: inva(d,d)
113 integer, intent(out) :: status
114
115 integer, allocatable :: ipiv(:)
116 double precision, allocatable :: work(:)
117 double precision :: twork(1)
118 integer :: info
119 integer :: lwork
120
121 status=1
122
123 allocate(ipiv(d))
124 ! copy a into inva using BLAS
125 !call dcopy(d*d,a,1,inva,1)
126 inva(:,:)=a(:,:)
127 ! LU factorization using LAPACK
128 call dgetrf(d,d,inva,d,ipiv,info)
129 ! if info is not equal to 0, something went wrong we exit setting status to 0
130 if (info /= 0) then
131 status=0
132 deallocate(ipiv)
133 return
134 end if
135 ! we use the query fonction of xxxtri to obtain the optimal workspace size
136 call dgetri(d,inva,d,ipiv,twork,-1,info)
137 lwork=int(twork(1))
138 allocate(work(lwork))
139 ! Matrix inversion using LAPACK
140 call dgetri(d,inva,d,ipiv,work,lwork,info)
141 ! again if info is not equal to 0, we exit setting status to 0
142 if (info /= 0) then
143 status=0
144 end if
145 deallocate(work)
146 deallocate(ipiv)
147 end subroutine
148
149 subroutine fvn_c_matinv(d,a,inva,status)
150 !
151 ! Matrix inversion of a complex matrix using BLAS and LAPACK
152 !
153 ! d (in) : matrix rank
154 ! a (in) : input matrix
155 ! inva (out) : inversed matrix
156 ! status (ou) : =0 if something failed
157 !
158 integer, intent(in) :: d
159 complex, intent(in) :: a(d,d)
160 complex, intent(out) :: inva(d,d)
161 integer, intent(out) :: status
162
163 integer, allocatable :: ipiv(:)
164 complex, allocatable :: work(:)
165 complex :: twork(1)
166 integer :: info
167 integer :: lwork
168
169 status=1
170
171 allocate(ipiv(d))
172 ! copy a into inva using BLAS
173 !call ccopy(d*d,a,1,inva,1)
174 inva(:,:)=a(:,:)
175
176 ! LU factorization using LAPACK
177 call cgetrf(d,d,inva,d,ipiv,info)
178 ! if info is not equal to 0, something went wrong we exit setting status to 0
179 if (info /= 0) then
180 status=0
181 deallocate(ipiv)
182 return
183 end if
184 ! we use the query fonction of xxxtri to obtain the optimal workspace size
185 call cgetri(d,inva,d,ipiv,twork,-1,info)
186 lwork=int(twork(1))
187 allocate(work(lwork))
188 ! Matrix inversion using LAPACK
189 call cgetri(d,inva,d,ipiv,work,lwork,info)
190 ! again if info is not equal to 0, we exit setting status to 0
191 if (info /= 0) then
192 status=0
193 end if
194 deallocate(work)
195 deallocate(ipiv)
196 end subroutine
197
198 subroutine fvn_z_matinv(d,a,inva,status)
199 !
200 ! Matrix inversion of a double complex matrix using BLAS and LAPACK
201 !
202 ! d (in) : matrix rank
203 ! a (in) : input matrix
204 ! inva (out) : inversed matrix
205 ! status (ou) : =0 if something failed
206 !
207 integer, intent(in) :: d
208 double complex, intent(in) :: a(d,d)
209 double complex, intent(out) :: inva(d,d)
210 integer, intent(out) :: status
211
212 integer, allocatable :: ipiv(:)
213 double complex, allocatable :: work(:)
214 double complex :: twork(1)
215 integer :: info
216 integer :: lwork
217
218 status=1
219
220 allocate(ipiv(d))
221 ! copy a into inva using BLAS
222 !call zcopy(d*d,a,1,inva,1)
223 inva(:,:)=a(:,:)
224
225 ! LU factorization using LAPACK
226 call zgetrf(d,d,inva,d,ipiv,info)
227 ! if info is not equal to 0, something went wrong we exit setting status to 0
228 if (info /= 0) then
229 status=0
230 deallocate(ipiv)
231 return
232 end if
233 ! we use the query fonction of xxxtri to obtain the optimal workspace size
234 call zgetri(d,inva,d,ipiv,twork,-1,info)
235 lwork=int(twork(1))
236 allocate(work(lwork))
237 ! Matrix inversion using LAPACK
238 call zgetri(d,inva,d,ipiv,work,lwork,info)
239 ! again if info is not equal to 0, we exit setting status to 0
240 if (info /= 0) then
241 status=0
242 end if
243 deallocate(work)
244 deallocate(ipiv)
245 end subroutine
246
247
248 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
249 !
250 ! Determinants
251 !
252 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
253 function fvn_s_det(d,a,status)
254 !
255 ! Evaluate the determinant of a square matrix using lapack LU factorization
256 !
257 ! d (in) : matrix rank
258 ! a (in) : The Matrix
259 ! status (out) : =0 if LU factorization failed
260 !
261 integer, intent(in) :: d
262 real, intent(in) :: a(d,d)
263 integer, intent(out) :: status
264 real :: fvn_s_det
265
266 real, allocatable :: wc_a(:,:)
267 integer, allocatable :: ipiv(:)
268 integer :: info,i
269
270 status=1
271 allocate(wc_a(d,d))
272 allocate(ipiv(d))
273 wc_a(:,:)=a(:,:)
274 call sgetrf(d,d,wc_a,d,ipiv,info)
275 if (info/= 0) then
276 status=0
277 fvn_s_det=0.e0
278 deallocate(ipiv)
279 deallocate(wc_a)
280 return
281 end if
282 fvn_s_det=1.e0
283 do i=1,d
284 if (ipiv(i)==i) then
285 fvn_s_det=fvn_s_det*wc_a(i,i)
286 else
287 fvn_s_det=-fvn_s_det*wc_a(i,i)
288 end if
289 end do
290 deallocate(ipiv)
291 deallocate(wc_a)
292
293 end function
294
295 function fvn_d_det(d,a,status)
296 !
297 ! Evaluate the determinant of a square matrix using lapack LU factorization
298 !
299 ! d (in) : matrix rank
300 ! a (in) : The Matrix
301 ! status (out) : =0 if LU factorization failed
302 !
303 integer, intent(in) :: d
304 double precision, intent(in) :: a(d,d)
305 integer, intent(out) :: status
306 double precision :: fvn_d_det
307
308 double precision, allocatable :: wc_a(:,:)
309 integer, allocatable :: ipiv(:)
310 integer :: info,i
311
312 status=1
313 allocate(wc_a(d,d))
314 allocate(ipiv(d))
315 wc_a(:,:)=a(:,:)
316 call dgetrf(d,d,wc_a,d,ipiv,info)
317 if (info/= 0) then
318 status=0
319 fvn_d_det=0.d0
320 deallocate(ipiv)
321 deallocate(wc_a)
322 return
323 end if
324 fvn_d_det=1.d0
325 do i=1,d
326 if (ipiv(i)==i) then
327 fvn_d_det=fvn_d_det*wc_a(i,i)
328 else
329 fvn_d_det=-fvn_d_det*wc_a(i,i)
330 end if
331 end do
332 deallocate(ipiv)
333 deallocate(wc_a)
334
335 end function
336
337 function fvn_c_det(d,a,status) !
338 ! Evaluate the determinant of a square matrix using lapack LU factorization
339 !
340 ! d (in) : matrix rank
341 ! a (in) : The Matrix
342 ! status (out) : =0 if LU factorization failed
343 !
344 integer, intent(in) :: d
345 complex, intent(in) :: a(d,d)
346 integer, intent(out) :: status
347 complex :: fvn_c_det
348
349 complex, allocatable :: wc_a(:,:)
350 integer, allocatable :: ipiv(:)
351 integer :: info,i
352
353 status=1
354 allocate(wc_a(d,d))
355 allocate(ipiv(d))
356 wc_a(:,:)=a(:,:)
357 call cgetrf(d,d,wc_a,d,ipiv,info)
358 if (info/= 0) then
359 status=0
360 fvn_c_det=(0.e0,0.e0)
361 deallocate(ipiv)
362 deallocate(wc_a)
363 return
364 end if
365 fvn_c_det=(1.e0,0.e0)
366 do i=1,d
367 if (ipiv(i)==i) then
368 fvn_c_det=fvn_c_det*wc_a(i,i)
369 else
370 fvn_c_det=-fvn_c_det*wc_a(i,i)
371 end if
372 end do
373 deallocate(ipiv)
374 deallocate(wc_a)
375
376 end function
377
378 function fvn_z_det(d,a,status)
379 !
380 ! Evaluate the determinant of a square matrix using lapack LU factorization
381 !
382 ! d (in) : matrix rank
383 ! a (in) : The Matrix
384 ! det (out) : determinant
385 ! status (out) : =0 if LU factorization failed
386 !
387 integer, intent(in) :: d
388 double complex, intent(in) :: a(d,d)
389 integer, intent(out) :: status
390 double complex :: fvn_z_det
391
392 double complex, allocatable :: wc_a(:,:)
393 integer, allocatable :: ipiv(:)
394 integer :: info,i
395
396 status=1
397 allocate(wc_a(d,d))
398 allocate(ipiv(d))
399 wc_a(:,:)=a(:,:)
400 call zgetrf(d,d,wc_a,d,ipiv,info)
401 if (info/= 0) then
402 status=0
403 fvn_z_det=(0.d0,0.d0)
404 deallocate(ipiv)
405 deallocate(wc_a)
406 return
407 end if
408 fvn_z_det=(1.d0,0.d0)
409 do i=1,d
410 if (ipiv(i)==i) then
411 fvn_z_det=fvn_z_det*wc_a(i,i)
412 else
413 fvn_z_det=-fvn_z_det*wc_a(i,i)
414 end if
415 end do
416 deallocate(ipiv)
417 deallocate(wc_a)
418
419 end function
420
421 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
422 !
423 ! Condition test
424 !
425 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
426 ! 1-norm
427 ! fonction lapack slange,dlange,clange,zlange pour obtenir la 1-norm
428 ! fonction lapack sgecon,dgecon,cgecon,zgecon pour calculer la rcond
429 !
430 subroutine fvn_s_matcon(d,a,rcond,status)
431 ! Matrix condition (reciprocal of condition number)
432 !
433 ! d (in) : matrix rank
434 ! a (in) : The Matrix
435 ! rcond (out) : guess what
436 ! status (out) : =0 if something went wrong
437 !
438 integer, intent(in) :: d
439 real, intent(in) :: a(d,d)
440 real, intent(out) :: rcond
441 integer, intent(out) :: status
442
443 real, allocatable :: work(:)
444 integer, allocatable :: iwork(:)
445 real :: anorm
446 real, allocatable :: wc_a(:,:) ! working copy of a
447 integer :: info
448 integer, allocatable :: ipiv(:)
449
450 real, external :: slange
451
452
453 status=1
454
455 anorm=slange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm
456
457 allocate(wc_a(d,d))
458 !call scopy(d*d,a,1,wc_a,1)
459 wc_a(:,:)=a(:,:)
460
461 allocate(ipiv(d))
462 call sgetrf(d,d,wc_a,d,ipiv,info)
463 if (info /= 0) then
464 status=0
465 deallocate(ipiv)
466 deallocate(wc_a)
467 return
468 end if
469 allocate(work(4*d))
470 allocate(iwork(d))
471 call sgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info)
472 if (info /= 0) then
473 status=0
474 end if
475 deallocate(iwork)
476 deallocate(work)
477 deallocate(ipiv)
478 deallocate(wc_a)
479
480 end subroutine
481
482 subroutine fvn_d_matcon(d,a,rcond,status)
483 ! Matrix condition (reciprocal of condition number)
484 !
485 ! d (in) : matrix rank
486 ! a (in) : The Matrix
487 ! rcond (out) : guess what
488 ! status (out) : =0 if something went wrong
489 !
490 integer, intent(in) :: d
491 double precision, intent(in) :: a(d,d)
492 double precision, intent(out) :: rcond
493 integer, intent(out) :: status
494
495 double precision, allocatable :: work(:)
496 integer, allocatable :: iwork(:)
497 double precision :: anorm
498 double precision, allocatable :: wc_a(:,:) ! working copy of a
499 integer :: info
500 integer, allocatable :: ipiv(:)
501
502 double precision, external :: dlange
503
504
505 status=1
506
507 anorm=dlange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm
508
509 allocate(wc_a(d,d))
510 !call dcopy(d*d,a,1,wc_a,1)
511 wc_a(:,:)=a(:,:)
512
513 allocate(ipiv(d))
514 call dgetrf(d,d,wc_a,d,ipiv,info)
515 if (info /= 0) then
516 status=0
517 deallocate(ipiv)
518 deallocate(wc_a)
519 return
520 end if
521
522 allocate(work(4*d))
523 allocate(iwork(d))
524 call dgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info)
525 if (info /= 0) then
526 status=0
527 end if
528 deallocate(iwork)
529 deallocate(work)
530 deallocate(ipiv)
531 deallocate(wc_a)
532
533 end subroutine
534
535 subroutine fvn_c_matcon(d,a,rcond,status)
536 ! Matrix condition (reciprocal of condition number)
537 !
538 ! d (in) : matrix rank
539 ! a (in) : The Matrix
540 ! rcond (out) : guess what
541 ! status (out) : =0 if something went wrong
542 !
543 integer, intent(in) :: d
544 complex, intent(in) :: a(d,d)
545 real, intent(out) :: rcond
546 integer, intent(out) :: status
547
548 real, allocatable :: rwork(:)
549 complex, allocatable :: work(:)
550 integer, allocatable :: iwork(:)
551 real :: anorm
552 complex, allocatable :: wc_a(:,:) ! working copy of a
553 integer :: info
554 integer, allocatable :: ipiv(:)
555
556 real, external :: clange
557
558
559 status=1
560
561 anorm=clange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm
562
563 allocate(wc_a(d,d))
564 !call ccopy(d*d,a,1,wc_a,1)
565 wc_a(:,:)=a(:,:)
566
567 allocate(ipiv(d))
568 call cgetrf(d,d,wc_a,d,ipiv,info)
569 if (info /= 0) then
570 status=0
571 deallocate(ipiv)
572 deallocate(wc_a)
573 return
574 end if
575 allocate(work(2*d))
576 allocate(rwork(2*d))
577 call cgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info)
578 if (info /= 0) then
579 status=0
580 end if
581 deallocate(rwork)
582 deallocate(work)
583 deallocate(ipiv)
584 deallocate(wc_a)
585 end subroutine
586
587 subroutine fvn_z_matcon(d,a,rcond,status)
588 ! Matrix condition (reciprocal of condition number)
589 !
590 ! d (in) : matrix rank
591 ! a (in) : The Matrix
592 ! rcond (out) : guess what
593 ! status (out) : =0 if something went wrong
594 !
595 integer, intent(in) :: d
596 double complex, intent(in) :: a(d,d)
597 double precision, intent(out) :: rcond
598 integer, intent(out) :: status
599
600 double complex, allocatable :: work(:)
601 double precision, allocatable :: rwork(:)
602 double precision :: anorm
603 double complex, allocatable :: wc_a(:,:) ! working copy of a
604 integer :: info
605 integer, allocatable :: ipiv(:)
606
607 double precision, external :: zlange
608
609
610 status=1
611
612 anorm=zlange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm
613
614 allocate(wc_a(d,d))
615 !call zcopy(d*d,a,1,wc_a,1)
616 wc_a(:,:)=a(:,:)
617
618 allocate(ipiv(d))
619 call zgetrf(d,d,wc_a,d,ipiv,info)
620 if (info /= 0) then
621 status=0
622 deallocate(ipiv)
623 deallocate(wc_a)
624 return
625 end if
626
627 allocate(work(2*d))
628 allocate(rwork(2*d))
629 call zgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info)
630 if (info /= 0) then
631 status=0
632 end if
633 deallocate(rwork)
634 deallocate(work)
635 deallocate(ipiv)
636 deallocate(wc_a)
637 end subroutine
638
639 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
640 !
641 ! Valeurs propres/ Vecteurs propre
642 !
643 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
644
645 subroutine fvn_s_matev(d,a,evala,eveca,status)
646 !
647 ! integer d (in) : matrice rank
648 ! real a(d,d) (in) : The Matrix
649 ! complex evala(d) (out) : eigenvalues
650 ! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
651 ! integer (out) : status =0 if something went wrong
652 !
653 ! interfacing Lapack routine SGEEV
654
655 integer, intent(in) :: d
656 real, intent(in) :: a(d,d)
657 complex, intent(out) :: evala(d)
658 complex, intent(out) :: eveca(d,d)
659 integer, intent(out) :: status
660
661 real, allocatable :: wc_a(:,:) ! a working copy of a
662 integer :: info
663 integer :: lwork
664 real, allocatable :: wr(:),wi(:)
665 real :: vl ! unused but necessary for the call
666 real, allocatable :: vr(:,:)
667 real, allocatable :: work(:)
668 real :: twork(1)
669 integer i
670 integer j
671
672 ! making a working copy of a
673 allocate(wc_a(d,d))
674 !call scopy(d*d,a,1,wc_a,1)
675 wc_a(:,:)=a(:,:)
676
677 allocate(wr(d))
678 allocate(wi(d))
679 allocate(vr(d,d))
680 ! query optimal work size
681 call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info)
682 lwork=int(twork(1))
683 allocate(work(lwork))
684 call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info)
685
686 if (info /= 0) then
687 status=0
688 deallocate(work)
689 deallocate(vr)
690 deallocate(wi)
691 deallocate(wr)
692 deallocate(wc_a)
693 return
694 end if
695
696 ! now fill in the results
697 i=1
698 do while(i<=d)
699 evala(i)=cmplx(wr(i),wi(i))
700 if (wi(i) == 0.) then ! eigenvalue is real
701 eveca(:,i)=cmplx(vr(:,i),0.)
702 else ! eigenvalue is complex
703 evala(i+1)=cmplx(wr(i+1),wi(i+1))
704 eveca(:,i)=cmplx(vr(:,i),vr(:,i+1))
705 eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1))
706 i=i+1
707 end if
708 i=i+1
709 enddo
710 deallocate(work)
711 deallocate(vr)
712 deallocate(wi)
713 deallocate(wr)
714 deallocate(wc_a)
715
716 end subroutine
717
718 subroutine fvn_d_matev(d,a,evala,eveca,status)
719 !
720 ! integer d (in) : matrice rank
721 ! double precision a(d,d) (in) : The Matrix
722 ! double complex evala(d) (out) : eigenvalues
723 ! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
724 ! integer (out) : status =0 if something went wrong
725 !
726 ! interfacing Lapack routine DGEEV
727 integer, intent(in) :: d
728 double precision, intent(in) :: a(d,d)
729 double complex, intent(out) :: evala(d)
730 double complex, intent(out) :: eveca(d,d)
731 integer, intent(out) :: status
732
733 double precision, allocatable :: wc_a(:,:) ! a working copy of a
734 integer :: info
735 integer :: lwork
736 double precision, allocatable :: wr(:),wi(:)
737 double precision :: vl ! unused but necessary for the call
738 double precision, allocatable :: vr(:,:)
739 double precision, allocatable :: work(:)
740 double precision :: twork(1)
741 integer i
742 integer j
743
744 ! making a working copy of a
745 allocate(wc_a(d,d))
746 !call dcopy(d*d,a,1,wc_a,1)
747 wc_a(:,:)=a(:,:)
748
749 allocate(wr(d))
750 allocate(wi(d))
751 allocate(vr(d,d))
752 ! query optimal work size
753 call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info)
754 lwork=int(twork(1))
755 allocate(work(lwork))
756 call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info)
757
758 if (info /= 0) then
759 status=0
760 deallocate(work)
761 deallocate(vr)
762 deallocate(wi)
763 deallocate(wr)
764 deallocate(wc_a)
765 return
766 end if
767
768 ! now fill in the results
769 i=1
770 do while(i<=d)
771 evala(i)=dcmplx(wr(i),wi(i))
772 if (wi(i) == 0.) then ! eigenvalue is real
773 eveca(:,i)=dcmplx(vr(:,i),0.)
774 else ! eigenvalue is complex
775 evala(i+1)=dcmplx(wr(i+1),wi(i+1))
776 eveca(:,i)=dcmplx(vr(:,i),vr(:,i+1))
777 eveca(:,i+1)=dcmplx(vr(:,i),-vr(:,i+1))
778 i=i+1
779 end if
780 i=i+1
781 enddo
782
783 deallocate(work)
784 deallocate(vr)
785 deallocate(wi)
786 deallocate(wr)
787 deallocate(wc_a)
788
789 end subroutine
790
791 subroutine fvn_c_matev(d,a,evala,eveca,status)
792 !
793 ! integer d (in) : matrice rank
794 ! complex a(d,d) (in) : The Matrix
795 ! complex evala(d) (out) : eigenvalues
796 ! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
797 ! integer (out) : status =0 if something went wrong
798 !
799 ! interfacing Lapack routine CGEEV
800
801 integer, intent(in) :: d
802 complex, intent(in) :: a(d,d)
803 complex, intent(out) :: evala(d)
804 complex, intent(out) :: eveca(d,d)
805 integer, intent(out) :: status
806
807 complex, allocatable :: wc_a(:,:) ! a working copy of a
808 integer :: info
809 integer :: lwork
810 complex, allocatable :: work(:)
811 complex :: twork(1)
812 real, allocatable :: rwork(:)
813 complex :: vl ! unused but necessary for the call
814
815 status=1
816
817 ! making a working copy of a
818 allocate(wc_a(d,d))
819 !call ccopy(d*d,a,1,wc_a,1)
820 wc_a(:,:)=a(:,:)
821
822
823 ! query optimal work size
824 call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info)
825 lwork=int(twork(1))
826 allocate(work(lwork))
827 allocate(rwork(2*d))
828 call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info)
829
830 if (info /= 0) then
831 status=0
832 end if
833 deallocate(rwork)
834 deallocate(work)
835 deallocate(wc_a)
836
837 end subroutine
838
839 subroutine fvn_z_matev(d,a,evala,eveca,status)
840 !
841 ! integer d (in) : matrice rank
842 ! double complex a(d,d) (in) : The Matrix
843 ! double complex evala(d) (out) : eigenvalues
844 ! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
845 ! integer (out) : status =0 if something went wrong
846 !
847 ! interfacing Lapack routine ZGEEV
848
849 integer, intent(in) :: d
850 double complex, intent(in) :: a(d,d)
851 double complex, intent(out) :: evala(d)
852 double complex, intent(out) :: eveca(d,d)
853 integer, intent(out) :: status
854
855 double complex, allocatable :: wc_a(:,:) ! a working copy of a
856 integer :: info
857 integer :: lwork
858 double complex, allocatable :: work(:)
859 double complex :: twork(1)
860 double precision, allocatable :: rwork(:)
861 double complex :: vl ! unused but necessary for the call
862
863 status=1
864
865 ! making a working copy of a
866 allocate(wc_a(d,d))
867 !call zcopy(d*d,a,1,wc_a,1)
868 wc_a(:,:)=a(:,:)
869
870 ! query optimal work size
871 call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info)
872 lwork=int(twork(1))
873 allocate(work(lwork))
874 allocate(rwork(2*d))
875 call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info)
876
877 if (info /= 0) then
878 status=0
879 end if
880 deallocate(rwork)
881 deallocate(work)
882 deallocate(wc_a)
883
884 end subroutine
885
886 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
887 !
888 ! Akima spline interpolation and spline evaluation
889 !
890 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
891
892 ! Single precision
893 subroutine fvn_s_akima(n,x,y,br,co)
894 implicit none
895 integer, intent(in) :: n
896 real, intent(in) :: x(n)
897 real, intent(in) :: y(n)
898 real, intent(out) :: br(n)
899 real, intent(out) :: co(4,n)
900
901 real, allocatable :: var(:),z(:)
902 real :: wi_1,wi
903 integer :: i
904 real :: dx,a,b
905
906 ! br is just a copy of x
907 br(:)=x(:)
908
909 allocate(var(n))
910 allocate(z(n))
911 ! evaluate the variations
912 do i=1, n-1
913 var(i+2)=(y(i+1)-y(i))/(x(i+1)-x(i))
914 end do
915 var(n+2)=2.e0*var(n+1)-var(n)
916 var(n+3)=2.e0*var(n+2)-var(n+1)
917 var(2)=2.e0*var(3)-var(4)
918 var(1)=2.e0*var(2)-var(3)
919
920 do i = 1, n
921 wi_1=abs(var(i+3)-var(i+2))
922 wi=abs(var(i+1)-var(i))
923 if ((wi_1+wi).eq.0.e0) then
924 z(i)=(var(i+2)+var(i+1))/2.e0
925 else
926 z(i)=(wi_1*var(i+1)+wi*var(i+2))/(wi_1+wi)
927 end if
928 end do
929
930 do i=1, n-1
931 dx=x(i+1)-x(i)
932 a=(z(i+1)-z(i))*dx ! coeff intermediaires pour calcul wd
933 b=y(i+1)-y(i)-z(i)*dx ! coeff intermediaires pour calcul wd
934 co(1,i)=y(i)
935 co(2,i)=z(i)
936 !co(3,i)=-(a-3.*b)/dx**2 ! mรฉthode wd
937 !co(4,i)=(a-2.*b)/dx**3 ! mรฉthode wd
938 co(3,i)=(3.e0*var(i+2)-2.e0*z(i)-z(i+1))/dx ! mรฉthode JP Moreau
939 co(4,i)=(z(i)+z(i+1)-2.e0*var(i+2))/dx**2 !
940 ! les coefficients donnรฉs par imsl sont co(3,i)*2 et co(4,i)*6
941 ! etrangement la fonction csval corrige et donne la bonne valeur ...
942 end do
943 co(1,n)=y(n)
944 co(2,n)=z(n)
945 co(3,n)=0.e0
946 co(4,n)=0.e0
947
948 deallocate(z)
949 deallocate(var)
950
951 end subroutine
952
953 ! Double precision
954 subroutine fvn_d_akima(n,x,y,br,co)
955
956 implicit none
957 integer, intent(in) :: n
958 double precision, intent(in) :: x(n)
959 double precision, intent(in) :: y(n)
960 double precision, intent(out) :: br(n)
961 double precision, intent(out) :: co(4,n)
962
963 double precision, allocatable :: var(:),z(:)
964 double precision :: wi_1,wi
965 integer :: i
966 double precision :: dx,a,b
967
968 ! br is just a copy of x
969 br(:)=x(:)
970
971 allocate(var(n))
972 allocate(z(n))
973 ! evaluate the variations
974 do i=1, n-1
975 var(i+2)=(y(i+1)-y(i))/(x(i+1)-x(i))
976 end do
977 var(n+2)=2.d0*var(n+1)-var(n)
978 var(n+3)=2.d0*var(n+2)-var(n+1)
979 var(2)=2.d0*var(3)-var(4)
980 var(1)=2.d0*var(2)-var(3)
981
982 do i = 1, n
983 wi_1=dabs(var(i+3)-var(i+2))
984 wi=dabs(var(i+1)-var(i))
985 if ((wi_1+wi).eq.0.d0) then
986 z(i)=(var(i+2)+var(i+1))/2.d0
987 else
988 z(i)=(wi_1*var(i+1)+wi*var(i+2))/(wi_1+wi)
989 end if
990 end do
991
992 do i=1, n-1
993 dx=x(i+1)-x(i)
994 a=(z(i+1)-z(i))*dx ! coeff intermediaires pour calcul wd
995 b=y(i+1)-y(i)-z(i)*dx ! coeff intermediaires pour calcul wd
996 co(1,i)=y(i)
997 co(2,i)=z(i)
998 !co(3,i)=-(a-3.*b)/dx**2 ! mรฉthode wd
999 !co(4,i)=(a-2.*b)/dx**3 ! mรฉthode wd
1000 co(3,i)=(3.d0*var(i+2)-2.d0*z(i)-z(i+1))/dx ! mรฉthode JP Moreau
1001 co(4,i)=(z(i)+z(i+1)-2.d0*var(i+2))/dx**2 !
1002 ! les coefficients donnรฉs par imsl sont co(3,i)*2 et co(4,i)*6
1003 ! etrangement la fonction csval corrige et donne la bonne valeur ...
1004 end do
1005 co(1,n)=y(n)
1006 co(2,n)=z(n)
1007 co(3,n)=0.d0
1008 co(4,n)=0.d0
1009
1010 deallocate(z)
1011 deallocate(var)
1012
1013 end subroutine
1014
1015 !
1016 ! Single precision spline evaluation
1017 !
1018 function fvn_s_spline_eval(x,n,br,co)
1019 implicit none
1020 real, intent(in) :: x ! x must be br(1)<= x <= br(n+1) otherwise value is extrapolated
1021 integer, intent(in) :: n ! number of intervals
1022 real, intent(in) :: br(n+1) ! breakpoints
1023 real, intent(in) :: co(4,n+1) ! spline coeeficients
1024 real :: fvn_s_spline_eval
1025
1026 integer :: i
1027 real :: dx
1028
1029 if (x<=br(1)) then
1030 i=1
1031 else if (x>=br(n+1)) then
1032 i=n
1033 else
1034 i=1
1035 do while(x>=br(i))
1036 i=i+1
1037 end do
1038 i=i-1
1039 end if
1040 dx=x-br(i)
1041 fvn_s_spline_eval=co(1,i)+co(2,i)*dx+co(3,i)*dx**2+co(4,i)*dx**3
1042
1043 end function
1044
1045 ! Double precision spline evaluation
1046 function fvn_d_spline_eval(x,n,br,co)
1047 implicit none
1048 double precision, intent(in) :: x ! x must be br(1)<= x <= br(n+1) otherwise value is extrapolated
1049 integer, intent(in) :: n ! number of intervals
1050 double precision, intent(in) :: br(n+1) ! breakpoints
1051 double precision, intent(in) :: co(4,n+1) ! spline coeeficients
1052 double precision :: fvn_d_spline_eval
1053
1054 integer :: i
1055 double precision :: dx
1056
1057
1058 if (x<=br(1)) then
1059 i=1
1060 else if (x>=br(n+1)) then
1061 i=n
1062 else
1063 i=1
1064 do while(x>=br(i))
1065 i=i+1
1066 end do
1067 i=i-1
1068 end if
1069
1070 dx=x-br(i)
1071 fvn_d_spline_eval=co(1,i)+co(2,i)*dx+co(3,i)*dx**2+co(4,i)*dx**3
1072
1073 end function
1074
1075
1076 !
1077 ! Muller
1078 !
1079 !
1080 !
1081 ! William Daniau 2007
1082 !
1083 ! This routine is a fortran 90 port of Hans D. Mittelmann's routine muller.f
1084 ! http://plato.asu.edu/ftp/other_software/muller.f
1085 !
1086 ! it can be used as a replacement for imsl routine dzanly with minor changes
1087 !
1088 !-----------------------------------------------------------------------
1089 !
1090 ! purpose - zeros of an analytic complex function
1091 ! using the muller method with deflation
1092 !
1093 ! usage - call fvn_z_muller (f,eps,eps1,kn,n,nguess,x,itmax,
1094 ! infer,ier)
1095 !
1096 ! arguments f - a complex function subprogram, f(z), written
1097 ! by the user specifying the equation whose
1098 ! roots are to be found. f must appear in
1099 ! an external statement in the calling pro-
1100 ! gram.
1101 ! eps - 1st stopping criterion. let fp(z)=f(z)/p
1102 ! where p = (z-z(1))*(z-z(2))*,,,*(z-z(k-1))
1103 ! and z(1),...,z(k-1) are previously found
1104 ! roots. if ((cdabs(f(z)).le.eps) .and.
1105 ! (cdabs(fp(z)).le.eps)), then z is accepted
1106 ! as a root. (input)
1107 ! eps1 - 2nd stopping criterion. a root is accepted
1108 ! if two successive approximations to a given
1109 ! root agree within eps1. (input)
1110 ! note. if either or both of the stopping
1111 ! criteria are fulfilled, the root is
1112 ! accepted.
1113 ! kn - the number of known roots which must be stored
1114 ! in x(1),...,x(kn), prior to entry to muller
1115 ! nguess - the number of initial guesses provided. these
1116 ! guesses must be stored in x(kn+1),...,
1117 ! x(kn+nguess). nguess must be set equal
1118 ! to zero if no guesses are provided. (input)
1119 ! n - the number of new roots to be found by
1120 ! muller (input)
1121 ! x - a complex vector of length kn+n. x(1),...,
1122 ! x(kn) on input must contain any known
1123 ! roots. x(kn+1),..., x(kn+n) on input may,
1124 ! on user option, contain initial guesses for
1125 ! the n new roots which are to be computed.
1126 ! if the user does not provide an initial
1127 ! guess, zero is used.
1128 ! on output, x(kn+1),...,x(kn+n) contain the
1129 ! approximate roots found by muller.
1130 ! itmax - the maximum allowable number of iterations
1131 ! per root (input)
1132 ! infer - an integer vector of length kn+n. on
1133 ! output infer(j) contains the number of
1134 ! iterations used in finding the j-th root
1135 ! when convergence was achieved. if
1136 ! convergence was not obtained in itmax
1137 ! iterations, infer(j) will be greater than
1138 ! itmax (output).
1139 ! ier - error parameter (output)
1140 ! warning error
1141 ! ier = 33 indicates failure to converge with-
1142 ! in itmax iterations for at least one of
1143 ! the (n) new roots.
1144 !
1145 !
1146 ! remarks muller always returns the last approximation for root j
1147 ! in x(j). if the convergence criterion is satisfied,
1148 ! then infer(j) is less than or equal to itmax. if the
1149 ! convergence criterion is not satisified, then infer(j)
1150 ! is set to either itmax+1 or itmax+k, with k greater
1151 ! than 1. infer(j) = itmax+1 indicates that muller did
1152 ! not obtain convergence in the allowed number of iter-
1153 ! ations. in this case, the user may wish to set itmax
1154 ! to a larger value. infer(j) = itmax+k means that con-
1155 ! vergence was obtained (on iteration k) for the defla-
1156 ! ted function
1157 ! fp(z) = f(z)/((z-z(1)...(z-z(j-1)))
1158 !
1159 ! but failed for f(z). in this case, better initial
1160 ! guesses might help or, it might be necessary to relax
1161 ! the convergence criterion.
1162 !
1163 !-----------------------------------------------------------------------
1164 !
1165 subroutine fvn_z_muller (f,eps,eps1,kn,nguess,n,x,itmax,infer,ier)
1166 implicit none
1167 double precision :: rzero,rten,rhun,rp01,ax,eps1,qz,eps,tpq
1168 double complex :: d,dd,den,fprt,frt,h,rt,t1,t2,t3, &
1169 tem,z0,z1,z2,bi,xx,xl,y0,y1,y2,x0, &
1170 zero,p1,one,four,p5
1171
1172 double complex, external :: f
1173 integer :: ickmax,kn,nguess,n,itmax,ier,knp1,knpn,i,l,ic, &
1174 knpng,jk,ick,nn,lm1,errcode
1175 double complex :: x(kn+n)
1176 integer :: infer(kn+n)
1177
1178
1179 data zero/(0.0,0.0)/,p1/(0.1,0.0)/, &
1180 one/(1.0,0.0)/,four/(4.0,0.0)/, &
1181 p5/(0.5,0.0)/, &
1182 rzero/0.0/,rten/10.0/,rhun/100.0/, &
1183 ax/0.1/,ickmax/3/,rp01/0.01/
1184
1185 ier = 0
1186 if (n .lt. 1) then ! What the hell are doing here then ...
1187 return
1188 end if
1189 !eps1 = rten **(-nsig)
1190 eps1 = min(eps1,rp01)
1191
1192 knp1 = kn+1
1193 knpn = kn+n
1194 knpng = kn+nguess
1195 do i=1,knpn
1196 infer(i) = 0
1197 if (i .gt. knpng) x(i) = zero
1198 end do
1199 l= knp1
1200
1201 ic=0
1202 rloop: do while (l<=knpn) ! Main loop over new roots
1203 jk = 0
1204 ick = 0
1205 xl = x(l)
1206 icloop: do
1207 ic = 0
1208 h = ax
1209 h = p1*h
1210 if (cdabs(xl) .gt. ax) h = p1*xl
1211 ! first three points are
1212 ! xl+h, xl-h, xl
1213 rt = xl+h
1214 call deflated_work(errcode)
1215 if (errcode == 1) then
1216 exit icloop
1217 end if
1218
1219 z0 = fprt
1220 y0 = frt
1221 x0 = rt
1222 rt = xl-h
1223 call deflated_work(errcode)
1224 if (errcode == 1) then
1225 exit icloop
1226 end if
1227
1228 z1 = fprt
1229 y1 = frt
1230 h = xl-rt
1231 d = h/(rt-x0)
1232 rt = xl
1233
1234 call deflated_work(errcode)
1235 if (errcode == 1) then
1236 exit icloop
1237 end if
1238
1239
1240 z2 = fprt
1241 y2 = frt
1242 ! begin main algorithm
1243 iloop: do
1244 dd = one + d
1245 t1 = z0*d*d
1246 t2 = z1*dd*dd
1247 xx = z2*dd
1248 t3 = z2*d
1249 bi = t1-t2+xx+t3
1250 den = bi*bi-four*(xx*t1-t3*(t2-xx))
1251 ! use denominator of maximum amplitude
1252 t1 = cdsqrt(den)
1253 qz = rhun*max(cdabs(bi),cdabs(t1))
1254 t2 = bi + t1
1255 tpq = cdabs(t2)+qz
1256 if (tpq .eq. qz) t2 = zero
1257 t3 = bi - t1
1258 tpq = cdabs(t3) + qz
1259 if (tpq .eq. qz) t3 = zero
1260 den = t2
1261 qz = cdabs(t3)-cdabs(t2)
1262 if (qz .gt. rzero) den = t3
1263 ! test for zero denominator
1264 if (cdabs(den) .eq. rzero) then
1265 call trans_rt()
1266 call deflated_work(errcode)
1267 if (errcode == 1) then
1268 exit icloop
1269 end if
1270 z2 = fprt
1271 y2 = frt
1272 cycle iloop
1273 end if
1274
1275
1276 d = -xx/den
1277 d = d+d
1278 h = d*h
1279 rt = rt + h
1280 ! check convergence of the first kind
1281 if (cdabs(h) .le. eps1*max(cdabs(rt),ax)) then
1282 if (ic .ne. 0) then
1283 exit icloop
1284 end if
1285 ic = 1
1286 z0 = y1
1287 z1 = y2
1288 z2 = f(rt)
1289 xl = rt
1290 ick = ick+1
1291 if (ick .le. ickmax) then
1292 cycle iloop
1293 end if
1294 ! warning error, itmax = maximum
1295 jk = itmax + jk
1296 ier = 33
1297 end if
1298 if (ic .ne. 0) then
1299 cycle icloop
1300 end if
1301 call deflated_work(errcode)
1302 if (errcode == 1) then
1303 exit icloop
1304 end if
1305
1306 do while ( (cdabs(fprt)-cdabs(z2)*rten) .ge. rzero)
1307 ! take remedial action to induce
1308 ! convergence
1309 d = d*p5
1310 h = h*p5
1311 rt = rt-h
1312 call deflated_work(errcode)
1313 if (errcode == 1) then
1314 exit icloop
1315 end if
1316 end do
1317 z0 = z1
1318 z1 = z2
1319 z2 = fprt
1320 y0 = y1
1321 y1 = y2
1322 y2 = frt
1323 end do iloop
1324 end do icloop
1325 x(l) = rt
1326 infer(l) = jk
1327 l = l+1
1328 end do rloop
1329
1330 contains
1331 subroutine trans_rt()
1332 tem = rten*eps1
1333 if (cdabs(rt) .gt. ax) tem = tem*rt
1334 rt = rt+tem
1335 d = (h+tem)*d/h
1336 h = h+tem
1337 end subroutine trans_rt
1338
1339 subroutine deflated_work(errcode)
1340 ! errcode=0 => no errors
1341 ! errcode=1 => jk>itmax or convergence of second kind achieved
1342 integer :: errcode,flag
1343
1344 flag=1
1345 loop1: do while(flag==1)
1346 errcode=0
1347 jk = jk+1
1348 if (jk .gt. itmax) then
1349 ier=33
1350 errcode=1
1351 return
1352 end if
1353 frt = f(rt)
1354 fprt = frt
1355 if (l /= 1) then
1356 lm1 = l-1
1357 do i=1,lm1
1358 tem = rt - x(i)
1359 if (cdabs(tem) .eq. rzero) then
1360 !if (ic .ne. 0) go to 15 !! ?? possible?
1361 call trans_rt()
1362 cycle loop1
1363 end if
1364 fprt = fprt/tem
1365 end do
1366 end if
1367 flag=0
1368 end do loop1
1369
1370 if (cdabs(fprt) .le. eps .and. cdabs(frt) .le. eps) then
1371 errcode=1
1372 return
1373 end if
1374
1375 end subroutine deflated_work
1376
1377 end subroutine
1378
1379
1380 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1381 !
1382 ! Integration
1383 !
1384 ! Only double precision coded atm
1385 !
1386 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1387
1388
1389 subroutine fvn_d_gauss_legendre(n,qx,qw)
1390 !
1391 ! This routine compute the n Gauss Legendre abscissas and weights
1392 ! Adapted from Numerical Recipes routine gauleg
1393 !
1394 ! n (in) : number of points
1395 ! qx(out) : abscissas
1396 ! qw(out) : weights
1397 !
1398 implicit none
1399 double precision,parameter :: pi=3.141592653589793d0
1400 integer, intent(in) :: n
1401 double precision, intent(out) :: qx(n),qw(n)
1402
1403 integer :: m,i,j
1404 double precision :: z,z1,p1,p2,p3,pp
1405 m=(n+1)/2
1406 do i=1,m
1407 z=cos(pi*(dble(i)-0.25d0)/(dble(n)+0.5d0))
1408 iloop: do
1409 p1=1.d0
1410 p2=0.d0
1411 do j=1,n
1412 p3=p2
1413 p2=p1
1414 p1=((2.d0*dble(j)-1.d0)*z*p2-(dble(j)-1.d0)*p3)/dble(j)
1415 end do
1416 pp=dble(n)*(z*p1-p2)/(z*z-1.d0)
1417 z1=z
1418 z=z1-p1/pp
1419 if (dabs(z-z1)<=epsilon(z)) then
1420 exit iloop
1421 end if
1422 end do iloop
1423 qx(i)=-z
1424 qx(n+1-i)=z
1425 qw(i)=2.d0/((1.d0-z*z)*pp*pp)
1426 qw(n+1-i)=qw(i)
1427 end do
1428 end subroutine
1429
1430
1431
1432 subroutine fvn_d_gl_integ(f,a,b,n,res)
1433 !
1434 ! This is a simple non adaptative integration routine
1435 ! using n gauss legendre abscissas and weights
1436 !
1437 ! f(in) : the function to integrate
1438 ! a(in) : lower bound
1439 ! b(in) : higher bound
1440 ! n(in) : number of gauss legendre pairs
1441 ! res(out): the evaluation of the integral
1442 !
1443 double precision,external :: f
1444 double precision, intent(in) :: a,b
1445 integer, intent(in):: n
1446 double precision, intent(out) :: res
1447
1448 double precision, allocatable :: qx(:),qw(:)
1449 double precision :: xm,xr
1450 integer :: i
1451
1452 ! First compute n gauss legendre abs and weight
1453 allocate(qx(n))
1454 allocate(qw(n))
1455 call fvn_d_gauss_legendre(n,qx,qw)
1456
1457 xm=0.5d0*(b+a)
1458 xr=0.5d0*(b-a)
1459
1460 res=0.d0
1461
1462 do i=1,n
1463 res=res+qw(i)*f(xm+xr*qx(i))
1464 end do
1465
1466 res=xr*res
1467
1468 deallocate(qw)
1469 deallocate(qx)
1470
1471 end subroutine
1472
1473 !!!!!!!!!!!!!!!!!!!!!!!!
1474 !
1475 ! Simple and double adaptative Gauss Kronrod integration based on
1476 ! a modified version of quadpack ( http://www.netlib.org/quadpack
1477 !
1478 ! Common parameters :
1479 !
1480 ! key (in)
1481 ! epsabs
1482 ! epsrel
1483 !
1484 !
1485 !!!!!!!!!!!!!!!!!!!!!!!!
1486
1487 subroutine fvn_d_integ_1_gk(f,a,b,epsabs,epsrel,key,res,abserr,ier,limit)
1488 !
1489 ! Evaluate the integral of function f(x) between a and b
1490 !
1491 ! f(in) : the function
1492 ! a(in) : lower bound
1493 ! b(in) : higher bound
1494 ! epsabs(in) : desired absolute error
1495 ! epsrel(in) : desired relative error
1496 ! key(in) : gauss kronrod rule
1497 ! 1: 7 - 15 points
1498 ! 2: 10 - 21 points
1499 ! 3: 15 - 31 points
1500 ! 4: 20 - 41 points
1501 ! 5: 25 - 51 points
1502 ! 6: 30 - 61 points
1503 !
1504 ! limit(in) : maximum number of subintervals in the partition of the
1505 ! given integration interval (a,b). A value of 500 will give the same
1506 ! behaviour as the imsl routine dqdag
1507 !
1508 ! res(out) : estimated integral value
1509 ! abserr(out) : estimated absolute error
1510 ! ier(out) : error flag from quadpack routines
1511 ! 0 : no error
1512 ! 1 : maximum number of subdivisions allowed
1513 ! has been achieved. one can allow more
1514 ! subdivisions by increasing the value of
1515 ! limit (and taking the according dimension
1516 ! adjustments into account). however, if
1517 ! this yield no improvement it is advised
1518 ! to analyze the integrand in order to
1519 ! determine the integration difficulaties.
1520 ! if the position of a local difficulty can
1521 ! be determined (i.e.singularity,
1522 ! discontinuity within the interval) one
1523 ! will probably gain from splitting up the
1524 ! interval at this point and calling the
1525 ! integrator on the subranges. if possible,
1526 ! an appropriate special-purpose integrator
1527 ! should be used which is designed for
1528 ! handling the type of difficulty involved.
1529 ! 2 : the occurrence of roundoff error is
1530 ! detected, which prevents the requested
1531 ! tolerance from being achieved.
1532 ! 3 : extremely bad integrand behaviour occurs
1533 ! at some points of the integration
1534 ! interval.
1535 ! 6 : the input is invalid, because
1536 ! (epsabs.le.0 and
1537 ! epsrel.lt.max(50*rel.mach.acc.,0.5d-28))
1538 ! or limit.lt.1 or lenw.lt.limit*4.
1539 ! result, abserr, neval, last are set
1540 ! to zero.
1541 ! except when lenw is invalid, iwork(1),
1542 ! work(limit*2+1) and work(limit*3+1) are
1543 ! set to zero, work(1) is set to a and
1544 ! work(limit+1) to b.
1545
1546 implicit none
1547 double precision, external :: f
1548 double precision, intent(in) :: a,b,epsabs,epsrel
1549 integer, intent(in) :: key
1550 integer, intent(in) :: limit
1551 double precision, intent(out) :: res,abserr
1552 integer, intent(out) :: ier
1553
1554 double precision, allocatable :: work(:)
1555 integer, allocatable :: iwork(:)
1556 integer :: lenw,neval,last
1557
1558 ! imsl value for limit is 500
1559 lenw=limit*4
1560
1561 allocate(iwork(limit))
1562 allocate(work(lenw))
1563
1564 call dqag(f,a,b,epsabs,epsrel,key,res,abserr,neval,ier,limit,lenw,last,iwork,work)
1565
1566 deallocate(work)
1567 deallocate(iwork)
1568
1569 end subroutine
1570
1571
File was created 1
2 module fvn
3 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4 !
5 ! fvn : a f95 module replacement for some imsl routines
6 ! it uses lapack for linear algebra
7 ! it uses modified quadpack for integration
8 !
9 ! William Daniau 2007
10 ! william.daniau@femto-st.fr
11 !
12 ! Routines naming scheme :
13 !
14 ! fvn_x_name
15 ! where x can be s : real
16 ! d : real double precision
17 ! c : complex
18 ! z : double complex
19 !
20 !
21 ! This piece of code is totally free! Do whatever you want with it. However
22 ! if you find it usefull it would be kind to give credits ;-) Nevertheless, you
23 ! may give credits to quadpack authors.
24 !
25 ! Version 1.1
26 !
27 ! TO DO LIST :
28 ! + Order eigenvalues and vectors in decreasing eigenvalue's modulus order -> atm
29 ! eigenvalues are given with no particular order.
30 ! + Generic interface for fvn_x_name family -> fvn_name
31 ! + Make some parameters optional, status for example
32 ! + use f95 kinds "double complex" -> complex(kind=8)
33 ! + unify quadpack routines
34 ! + ...
35 !
36 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
37
38 implicit none
39 ! All quadpack routines are private to the module
40 private :: d1mach,dqag,dqag_2d_inner,dqag_2d_outer,dqage,dqage_2d_inner, &
41 dqage_2d_outer,dqk15,dqk15_2d_inner,dqk15_2d_outer,dqk21,dqk21_2d_inner,dqk21_2d_outer, &
42 dqk31,dqk31_2d_inner,dqk31_2d_outer,dqk41,dqk41_2d_inner,dqk41_2d_outer, &
43 dqk51,dqk51_2d_inner,dqk51_2d_outer,dqk61,dqk61_2d_inner,dqk61_2d_outer,dqpsrt
44
45
46 contains
47
48 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
49 !
50 ! Matrix inversion subroutines
51 !
52 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
53 subroutine fvn_s_matinv(d,a,inva,status)
54 !
55 ! Matrix inversion of a real matrix using BLAS and LAPACK
56 !
57 ! d (in) : matrix rank
58 ! a (in) : input matrix
59 ! inva (out) : inversed matrix
60 ! status (ou) : =0 if something failed
61 !
62 integer, intent(in) :: d
63 real, intent(in) :: a(d,d)
64 real, intent(out) :: inva(d,d)
65 integer, intent(out) :: status
66
67 integer, allocatable :: ipiv(:)
68 real, allocatable :: work(:)
69 real twork(1)
70 integer :: info
71 integer :: lwork
72
73 status=1
74
75 allocate(ipiv(d))
76 ! copy a into inva using BLAS
77 !call scopy(d*d,a,1,inva,1)
78 inva(:,:)=a(:,:)
79 ! LU factorization using LAPACK
80 call sgetrf(d,d,inva,d,ipiv,info)
81 ! if info is not equal to 0, something went wrong we exit setting status to 0
82 if (info /= 0) then
83 status=0
84 deallocate(ipiv)
85 return
86 end if
87 ! we use the query fonction of xxxtri to obtain the optimal workspace size
88 call sgetri(d,inva,d,ipiv,twork,-1,info)
89 lwork=int(twork(1))
90 allocate(work(lwork))
91 ! Matrix inversion using LAPACK
92 call sgetri(d,inva,d,ipiv,work,lwork,info)
93 ! again if info is not equal to 0, we exit setting status to 0
94 if (info /= 0) then
95 status=0
96 end if
97 deallocate(work)
98 deallocate(ipiv)
99 end subroutine
100
101 subroutine fvn_d_matinv(d,a,inva,status)
102 !
103 ! Matrix inversion of a double precision matrix using BLAS and LAPACK
104 !
105 ! d (in) : matrix rank
106 ! a (in) : input matrix
107 ! inva (out) : inversed matrix
108 ! status (ou) : =0 if something failed
109 !
110 integer, intent(in) :: d
111 double precision, intent(in) :: a(d,d)
112 double precision, intent(out) :: inva(d,d)
113 integer, intent(out) :: status
114
115 integer, allocatable :: ipiv(:)
116 double precision, allocatable :: work(:)
117 double precision :: twork(1)
118 integer :: info
119 integer :: lwork
120
121 status=1
122
123 allocate(ipiv(d))
124 ! copy a into inva using BLAS
125 !call dcopy(d*d,a,1,inva,1)
126 inva(:,:)=a(:,:)
127 ! LU factorization using LAPACK
128 call dgetrf(d,d,inva,d,ipiv,info)
129 ! if info is not equal to 0, something went wrong we exit setting status to 0
130 if (info /= 0) then
131 status=0
132 deallocate(ipiv)
133 return
134 end if
135 ! we use the query fonction of xxxtri to obtain the optimal workspace size
136 call dgetri(d,inva,d,ipiv,twork,-1,info)
137 lwork=int(twork(1))
138 allocate(work(lwork))
139 ! Matrix inversion using LAPACK
140 call dgetri(d,inva,d,ipiv,work,lwork,info)
141 ! again if info is not equal to 0, we exit setting status to 0
142 if (info /= 0) then
143 status=0
144 end if
145 deallocate(work)
146 deallocate(ipiv)
147 end subroutine
148
149 subroutine fvn_c_matinv(d,a,inva,status)
150 !
151 ! Matrix inversion of a complex matrix using BLAS and LAPACK
152 !
153 ! d (in) : matrix rank
154 ! a (in) : input matrix
155 ! inva (out) : inversed matrix
156 ! status (ou) : =0 if something failed
157 !
158 integer, intent(in) :: d
159 complex, intent(in) :: a(d,d)
160 complex, intent(out) :: inva(d,d)
161 integer, intent(out) :: status
162
163 integer, allocatable :: ipiv(:)
164 complex, allocatable :: work(:)
165 complex :: twork(1)
166 integer :: info
167 integer :: lwork
168
169 status=1
170
171 allocate(ipiv(d))
172 ! copy a into inva using BLAS
173 !call ccopy(d*d,a,1,inva,1)
174 inva(:,:)=a(:,:)
175
176 ! LU factorization using LAPACK
177 call cgetrf(d,d,inva,d,ipiv,info)
178 ! if info is not equal to 0, something went wrong we exit setting status to 0
179 if (info /= 0) then
180 status=0
181 deallocate(ipiv)
182 return
183 end if
184 ! we use the query fonction of xxxtri to obtain the optimal workspace size
185 call cgetri(d,inva,d,ipiv,twork,-1,info)
186 lwork=int(twork(1))
187 allocate(work(lwork))
188 ! Matrix inversion using LAPACK
189 call cgetri(d,inva,d,ipiv,work,lwork,info)
190 ! again if info is not equal to 0, we exit setting status to 0
191 if (info /= 0) then
192 status=0
193 end if
194 deallocate(work)
195 deallocate(ipiv)
196 end subroutine
197
198 subroutine fvn_z_matinv(d,a,inva,status)
199 !
200 ! Matrix inversion of a double complex matrix using BLAS and LAPACK
201 !
202 ! d (in) : matrix rank
203 ! a (in) : input matrix
204 ! inva (out) : inversed matrix
205 ! status (ou) : =0 if something failed
206 !
207 integer, intent(in) :: d
208 double complex, intent(in) :: a(d,d)
209 double complex, intent(out) :: inva(d,d)
210 integer, intent(out) :: status
211
212 integer, allocatable :: ipiv(:)
213 double complex, allocatable :: work(:)
214 double complex :: twork(1)
215 integer :: info
216 integer :: lwork
217
218 status=1
219
220 allocate(ipiv(d))
221 ! copy a into inva using BLAS
222 !call zcopy(d*d,a,1,inva,1)
223 inva(:,:)=a(:,:)
224
225 ! LU factorization using LAPACK
226 call zgetrf(d,d,inva,d,ipiv,info)
227 ! if info is not equal to 0, something went wrong we exit setting status to 0
228 if (info /= 0) then
229 status=0
230 deallocate(ipiv)
231 return
232 end if
233 ! we use the query fonction of xxxtri to obtain the optimal workspace size
234 call zgetri(d,inva,d,ipiv,twork,-1,info)
235 lwork=int(twork(1))
236 allocate(work(lwork))
237 ! Matrix inversion using LAPACK
238 call zgetri(d,inva,d,ipiv,work,lwork,info)
239 ! again if info is not equal to 0, we exit setting status to 0
240 if (info /= 0) then
241 status=0
242 end if
243 deallocate(work)
244 deallocate(ipiv)
245 end subroutine
246
247
248 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
249 !
250 ! Determinants
251 !
252 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
253 function fvn_s_det(d,a,status)
254 !
255 ! Evaluate the determinant of a square matrix using lapack LU factorization
256 !
257 ! d (in) : matrix rank
258 ! a (in) : The Matrix
259 ! status (out) : =0 if LU factorization failed
260 !
261 integer, intent(in) :: d
262 real, intent(in) :: a(d,d)
263 integer, intent(out) :: status
264 real :: fvn_s_det
265
266 real, allocatable :: wc_a(:,:)
267 integer, allocatable :: ipiv(:)
268 integer :: info,i
269
270 status=1
271 allocate(wc_a(d,d))
272 allocate(ipiv(d))
273 wc_a(:,:)=a(:,:)
274 call sgetrf(d,d,wc_a,d,ipiv,info)
275 if (info/= 0) then
276 status=0
277 fvn_s_det=0.e0
278 deallocate(ipiv)
279 deallocate(wc_a)
280 return
281 end if
282 fvn_s_det=1.e0
283 do i=1,d
284 if (ipiv(i)==i) then
285 fvn_s_det=fvn_s_det*wc_a(i,i)
286 else
287 fvn_s_det=-fvn_s_det*wc_a(i,i)
288 end if
289 end do
290 deallocate(ipiv)
291 deallocate(wc_a)
292
293 end function
294
295 function fvn_d_det(d,a,status)
296 !
297 ! Evaluate the determinant of a square matrix using lapack LU factorization
298 !
299 ! d (in) : matrix rank
300 ! a (in) : The Matrix
301 ! status (out) : =0 if LU factorization failed
302 !
303 integer, intent(in) :: d
304 double precision, intent(in) :: a(d,d)
305 integer, intent(out) :: status
306 double precision :: fvn_d_det
307
308 double precision, allocatable :: wc_a(:,:)
309 integer, allocatable :: ipiv(:)
310 integer :: info,i
311
312 status=1
313 allocate(wc_a(d,d))
314 allocate(ipiv(d))
315 wc_a(:,:)=a(:,:)
316 call dgetrf(d,d,wc_a,d,ipiv,info)
317 if (info/= 0) then
318 status=0
319 fvn_d_det=0.d0
320 deallocate(ipiv)
321 deallocate(wc_a)
322 return
323 end if
324 fvn_d_det=1.d0
325 do i=1,d
326 if (ipiv(i)==i) then
327 fvn_d_det=fvn_d_det*wc_a(i,i)
328 else
329 fvn_d_det=-fvn_d_det*wc_a(i,i)
330 end if
331 end do
332 deallocate(ipiv)
333 deallocate(wc_a)
334
335 end function
336
337 function fvn_c_det(d,a,status) !
338 ! Evaluate the determinant of a square matrix using lapack LU factorization
339 !
340 ! d (in) : matrix rank
341 ! a (in) : The Matrix
342 ! status (out) : =0 if LU factorization failed
343 !
344 integer, intent(in) :: d
345 complex, intent(in) :: a(d,d)
346 integer, intent(out) :: status
347 complex :: fvn_c_det
348
349 complex, allocatable :: wc_a(:,:)
350 integer, allocatable :: ipiv(:)
351 integer :: info,i
352
353 status=1
354 allocate(wc_a(d,d))
355 allocate(ipiv(d))
356 wc_a(:,:)=a(:,:)
357 call cgetrf(d,d,wc_a,d,ipiv,info)
358 if (info/= 0) then
359 status=0
360 fvn_c_det=(0.e0,0.e0)
361 deallocate(ipiv)
362 deallocate(wc_a)
363 return
364 end if
365 fvn_c_det=(1.e0,0.e0)
366 do i=1,d
367 if (ipiv(i)==i) then
368 fvn_c_det=fvn_c_det*wc_a(i,i)
369 else
370 fvn_c_det=-fvn_c_det*wc_a(i,i)
371 end if
372 end do
373 deallocate(ipiv)
374 deallocate(wc_a)
375
376 end function
377
378 function fvn_z_det(d,a,status)
379 !
380 ! Evaluate the determinant of a square matrix using lapack LU factorization
381 !
382 ! d (in) : matrix rank
383 ! a (in) : The Matrix
384 ! det (out) : determinant
385 ! status (out) : =0 if LU factorization failed
386 !
387 integer, intent(in) :: d
388 double complex, intent(in) :: a(d,d)
389 integer, intent(out) :: status
390 double complex :: fvn_z_det
391
392 double complex, allocatable :: wc_a(:,:)
393 integer, allocatable :: ipiv(:)
394 integer :: info,i
395
396 status=1
397 allocate(wc_a(d,d))
398 allocate(ipiv(d))
399 wc_a(:,:)=a(:,:)
400 call zgetrf(d,d,wc_a,d,ipiv,info)
401 if (info/= 0) then
402 status=0
403 fvn_z_det=(0.d0,0.d0)
404 deallocate(ipiv)
405 deallocate(wc_a)
406 return
407 end if
408 fvn_z_det=(1.d0,0.d0)
409 do i=1,d
410 if (ipiv(i)==i) then
411 fvn_z_det=fvn_z_det*wc_a(i,i)
412 else
413 fvn_z_det=-fvn_z_det*wc_a(i,i)
414 end if
415 end do
416 deallocate(ipiv)
417 deallocate(wc_a)
418
419 end function
420
421 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
422 !
423 ! Condition test
424 !
425 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
426 ! 1-norm
427 ! fonction lapack slange,dlange,clange,zlange pour obtenir la 1-norm
428 ! fonction lapack sgecon,dgecon,cgecon,zgecon pour calculer la rcond
429 !
430 subroutine fvn_s_matcon(d,a,rcond,status)
431 ! Matrix condition (reciprocal of condition number)
432 !
433 ! d (in) : matrix rank
434 ! a (in) : The Matrix
435 ! rcond (out) : guess what
436 ! status (out) : =0 if something went wrong
437 !
438 integer, intent(in) :: d
439 real, intent(in) :: a(d,d)
440 real, intent(out) :: rcond
441 integer, intent(out) :: status
442
443 real, allocatable :: work(:)
444 integer, allocatable :: iwork(:)
445 real :: anorm
446 real, allocatable :: wc_a(:,:) ! working copy of a
447 integer :: info
448 integer, allocatable :: ipiv(:)
449
450 real, external :: slange
451
452
453 status=1
454
455 anorm=slange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm
456
457 allocate(wc_a(d,d))
458 !call scopy(d*d,a,1,wc_a,1)
459 wc_a(:,:)=a(:,:)
460
461 allocate(ipiv(d))
462 call sgetrf(d,d,wc_a,d,ipiv,info)
463 if (info /= 0) then
464 status=0
465 deallocate(ipiv)
466 deallocate(wc_a)
467 return
468 end if
469 allocate(work(4*d))
470 allocate(iwork(d))
471 call sgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info)
472 if (info /= 0) then
473 status=0
474 end if
475 deallocate(iwork)
476 deallocate(work)
477 deallocate(ipiv)
478 deallocate(wc_a)
479
480 end subroutine
481
482 subroutine fvn_d_matcon(d,a,rcond,status)
483 ! Matrix condition (reciprocal of condition number)
484 !
485 ! d (in) : matrix rank
486 ! a (in) : The Matrix
487 ! rcond (out) : guess what
488 ! status (out) : =0 if something went wrong
489 !
490 integer, intent(in) :: d
491 double precision, intent(in) :: a(d,d)
492 double precision, intent(out) :: rcond
493 integer, intent(out) :: status
494
495 double precision, allocatable :: work(:)
496 integer, allocatable :: iwork(:)
497 double precision :: anorm
498 double precision, allocatable :: wc_a(:,:) ! working copy of a
499 integer :: info
500 integer, allocatable :: ipiv(:)
501
502 double precision, external :: dlange
503
504
505 status=1
506
507 anorm=dlange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm
508
509 allocate(wc_a(d,d))
510 !call dcopy(d*d,a,1,wc_a,1)
511 wc_a(:,:)=a(:,:)
512
513 allocate(ipiv(d))
514 call dgetrf(d,d,wc_a,d,ipiv,info)
515 if (info /= 0) then
516 status=0
517 deallocate(ipiv)
518 deallocate(wc_a)
519 return
520 end if
521
522 allocate(work(4*d))
523 allocate(iwork(d))
524 call dgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info)
525 if (info /= 0) then
526 status=0
527 end if
528 deallocate(iwork)
529 deallocate(work)
530 deallocate(ipiv)
531 deallocate(wc_a)
532
533 end subroutine
534
535 subroutine fvn_c_matcon(d,a,rcond,status)
536 ! Matrix condition (reciprocal of condition number)
537 !
538 ! d (in) : matrix rank
539 ! a (in) : The Matrix
540 ! rcond (out) : guess what
541 ! status (out) : =0 if something went wrong
542 !
543 integer, intent(in) :: d
544 complex, intent(in) :: a(d,d)
545 real, intent(out) :: rcond
546 integer, intent(out) :: status
547
548 real, allocatable :: rwork(:)
549 complex, allocatable :: work(:)
550 integer, allocatable :: iwork(:)
551 real :: anorm
552 complex, allocatable :: wc_a(:,:) ! working copy of a
553 integer :: info
554 integer, allocatable :: ipiv(:)
555
556 real, external :: clange
557
558
559 status=1
560
561 anorm=clange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm
562
563 allocate(wc_a(d,d))
564 !call ccopy(d*d,a,1,wc_a,1)
565 wc_a(:,:)=a(:,:)
566
567 allocate(ipiv(d))
568 call cgetrf(d,d,wc_a,d,ipiv,info)
569 if (info /= 0) then
570 status=0
571 deallocate(ipiv)
572 deallocate(wc_a)
573 return
574 end if
575 allocate(work(2*d))
576 allocate(rwork(2*d))
577 call cgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info)
578 if (info /= 0) then
579 status=0
580 end if
581 deallocate(rwork)
582 deallocate(work)
583 deallocate(ipiv)
584 deallocate(wc_a)
585 end subroutine
586
587 subroutine fvn_z_matcon(d,a,rcond,status)
588 ! Matrix condition (reciprocal of condition number)
589 !
590 ! d (in) : matrix rank
591 ! a (in) : The Matrix
592 ! rcond (out) : guess what
593 ! status (out) : =0 if something went wrong
594 !
595 integer, intent(in) :: d
596 double complex, intent(in) :: a(d,d)
597 double precision, intent(out) :: rcond
598 integer, intent(out) :: status
599
600 double complex, allocatable :: work(:)
601 double precision, allocatable :: rwork(:)
602 double precision :: anorm
603 double complex, allocatable :: wc_a(:,:) ! working copy of a
604 integer :: info
605 integer, allocatable :: ipiv(:)
606
607 double precision, external :: zlange
608
609
610 status=1
611
612 anorm=zlange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm
613
614 allocate(wc_a(d,d))
615 !call zcopy(d*d,a,1,wc_a,1)
616 wc_a(:,:)=a(:,:)
617
618 allocate(ipiv(d))
619 call zgetrf(d,d,wc_a,d,ipiv,info)
620 if (info /= 0) then
621 status=0
622 deallocate(ipiv)
623 deallocate(wc_a)
624 return
625 end if
626
627 allocate(work(2*d))
628 allocate(rwork(2*d))
629 call zgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info)
630 if (info /= 0) then
631 status=0
632 end if
633 deallocate(rwork)
634 deallocate(work)
635 deallocate(ipiv)
636 deallocate(wc_a)
637 end subroutine
638
639 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
640 !
641 ! Valeurs propres/ Vecteurs propre
642 !
643 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
644
645 subroutine fvn_s_matev(d,a,evala,eveca,status)
646 !
647 ! integer d (in) : matrice rank
648 ! real a(d,d) (in) : The Matrix
649 ! complex evala(d) (out) : eigenvalues
650 ! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
651 ! integer (out) : status =0 if something went wrong
652 !
653 ! interfacing Lapack routine SGEEV
654
655 integer, intent(in) :: d
656 real, intent(in) :: a(d,d)
657 complex, intent(out) :: evala(d)
658 complex, intent(out) :: eveca(d,d)
659 integer, intent(out) :: status
660
661 real, allocatable :: wc_a(:,:) ! a working copy of a
662 integer :: info
663 integer :: lwork
664 real, allocatable :: wr(:),wi(:)
665 real :: vl ! unused but necessary for the call
666 real, allocatable :: vr(:,:)
667 real, allocatable :: work(:)
668 real :: twork(1)
669 integer i
670 integer j
671
672 ! making a working copy of a
673 allocate(wc_a(d,d))
674 !call scopy(d*d,a,1,wc_a,1)
675 wc_a(:,:)=a(:,:)
676
677 allocate(wr(d))
678 allocate(wi(d))
679 allocate(vr(d,d))
680 ! query optimal work size
681 call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info)
682 lwork=int(twork(1))
683 allocate(work(lwork))
684 call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info)
685
686 if (info /= 0) then
687 status=0
688 deallocate(work)
689 deallocate(vr)
690 deallocate(wi)
691 deallocate(wr)
692 deallocate(wc_a)
693 return
694 end if
695
696 ! now fill in the results
697 i=1
698 do while(i<=d)
699 evala(i)=cmplx(wr(i),wi(i))
700 if (wi(i) == 0.) then ! eigenvalue is real
701 eveca(:,i)=cmplx(vr(:,i),0.)
702 else ! eigenvalue is complex
703 evala(i+1)=cmplx(wr(i+1),wi(i+1))
704 eveca(:,i)=cmplx(vr(:,i),vr(:,i+1))
705 eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1))
706 i=i+1
707 end if
708 i=i+1
709 enddo
710 deallocate(work)
711 deallocate(vr)
712 deallocate(wi)
713 deallocate(wr)
714 deallocate(wc_a)
715
716 end subroutine
717
718 subroutine fvn_d_matev(d,a,evala,eveca,status)
719 !
720 ! integer d (in) : matrice rank
721 ! double precision a(d,d) (in) : The Matrix
722 ! double complex evala(d) (out) : eigenvalues
723 ! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
724 ! integer (out) : status =0 if something went wrong
725 !
726 ! interfacing Lapack routine DGEEV
727 integer, intent(in) :: d
728 double precision, intent(in) :: a(d,d)
729 double complex, intent(out) :: evala(d)
730 double complex, intent(out) :: eveca(d,d)
731 integer, intent(out) :: status
732
733 double precision, allocatable :: wc_a(:,:) ! a working copy of a
734 integer :: info
735 integer :: lwork
736 double precision, allocatable :: wr(:),wi(:)
737 double precision :: vl ! unused but necessary for the call
738 double precision, allocatable :: vr(:,:)
739 double precision, allocatable :: work(:)
740 double precision :: twork(1)
741 integer i
742 integer j
743
744 ! making a working copy of a
745 allocate(wc_a(d,d))
746 !call dcopy(d*d,a,1,wc_a,1)
747 wc_a(:,:)=a(:,:)
748
749 allocate(wr(d))
750 allocate(wi(d))
751 allocate(vr(d,d))
752 ! query optimal work size
753 call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info)
754 lwork=int(twork(1))
755 allocate(work(lwork))
756 call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info)
757
758 if (info /= 0) then
759 status=0
760 deallocate(work)
761 deallocate(vr)
762 deallocate(wi)
763 deallocate(wr)
764 deallocate(wc_a)
765 return
766 end if
767
768 ! now fill in the results
769 i=1
770 do while(i<=d)
771 evala(i)=dcmplx(wr(i),wi(i))
772 if (wi(i) == 0.) then ! eigenvalue is real
773 eveca(:,i)=dcmplx(vr(:,i),0.)
774 else ! eigenvalue is complex
775 evala(i+1)=dcmplx(wr(i+1),wi(i+1))
776 eveca(:,i)=dcmplx(vr(:,i),vr(:,i+1))
777 eveca(:,i+1)=dcmplx(vr(:,i),-vr(:,i+1))
778 i=i+1
779 end if
780 i=i+1
781 enddo
782
783 deallocate(work)
784 deallocate(vr)
785 deallocate(wi)
786 deallocate(wr)
787 deallocate(wc_a)
788
789 end subroutine
790
791 subroutine fvn_c_matev(d,a,evala,eveca,status)
792 !
793 ! integer d (in) : matrice rank
794 ! complex a(d,d) (in) : The Matrix
795 ! complex evala(d) (out) : eigenvalues
796 ! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
797 ! integer (out) : status =0 if something went wrong
798 !
799 ! interfacing Lapack routine CGEEV
800
801 integer, intent(in) :: d
802 complex, intent(in) :: a(d,d)
803 complex, intent(out) :: evala(d)
804 complex, intent(out) :: eveca(d,d)
805 integer, intent(out) :: status
806
807 complex, allocatable :: wc_a(:,:) ! a working copy of a
808 integer :: info
809 integer :: lwork
810 complex, allocatable :: work(:)
811 complex :: twork(1)
812 real, allocatable :: rwork(:)
813 complex :: vl ! unused but necessary for the call
814
815 status=1
816
817 ! making a working copy of a
818 allocate(wc_a(d,d))
819 !call ccopy(d*d,a,1,wc_a,1)
820 wc_a(:,:)=a(:,:)
821
822
823 ! query optimal work size
824 call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info)
825 lwork=int(twork(1))
826 allocate(work(lwork))
827 allocate(rwork(2*d))
828 call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info)
829
830 if (info /= 0) then
831 status=0
832 end if
833 deallocate(rwork)
834 deallocate(work)
835 deallocate(wc_a)
836
837 end subroutine
838
839 subroutine fvn_z_matev(d,a,evala,eveca,status)
840 !
841 ! integer d (in) : matrice rank
842 ! double complex a(d,d) (in) : The Matrix
843 ! double complex evala(d) (out) : eigenvalues
844 ! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
845 ! integer (out) : status =0 if something went wrong
846 !
847 ! interfacing Lapack routine ZGEEV
848
849 integer, intent(in) :: d
850 double complex, intent(in) :: a(d,d)
851 double complex, intent(out) :: evala(d)
852 double complex, intent(out) :: eveca(d,d)
853 integer, intent(out) :: status
854
855 double complex, allocatable :: wc_a(:,:) ! a working copy of a
856 integer :: info
857 integer :: lwork
858 double complex, allocatable :: work(:)
859 double complex :: twork(1)
860 double precision, allocatable :: rwork(:)
861 double complex :: vl ! unused but necessary for the call
862
863 status=1
864
865 ! making a working copy of a
866 allocate(wc_a(d,d))
867 !call zcopy(d*d,a,1,wc_a,1)
868 wc_a(:,:)=a(:,:)
869
870 ! query optimal work size
871 call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info)
872 lwork=int(twork(1))
873 allocate(work(lwork))
874 allocate(rwork(2*d))
875 call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info)
876
877 if (info /= 0) then
878 status=0
879 end if
880 deallocate(rwork)
881 deallocate(work)
882 deallocate(wc_a)
883
884 end subroutine
885
886 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
887 !
888 ! Akima spline interpolation and spline evaluation
889 !
890 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
891
892 ! Single precision
893 subroutine fvn_s_akima(n,x,y,br,co)
894 implicit none
895 integer, intent(in) :: n
896 real, intent(in) :: x(n)
897 real, intent(in) :: y(n)
898 real, intent(out) :: br(n)
899 real, intent(out) :: co(4,n)
900
901 real, allocatable :: var(:),z(:)
902 real :: wi_1,wi
903 integer :: i
904 real :: dx,a,b
905
906 ! br is just a copy of x
907 br(:)=x(:)
908
909 allocate(var(n))
910 allocate(z(n))
911 ! evaluate the variations
912 do i=1, n-1
913 var(i+2)=(y(i+1)-y(i))/(x(i+1)-x(i))
914 end do
915 var(n+2)=2.e0*var(n+1)-var(n)
916 var(n+3)=2.e0*var(n+2)-var(n+1)
917 var(2)=2.e0*var(3)-var(4)
918 var(1)=2.e0*var(2)-var(3)
919
920 do i = 1, n
921 wi_1=abs(var(i+3)-var(i+2))
922 wi=abs(var(i+1)-var(i))
923 if ((wi_1+wi).eq.0.e0) then
924 z(i)=(var(i+2)+var(i+1))/2.e0
925 else
926 z(i)=(wi_1*var(i+1)+wi*var(i+2))/(wi_1+wi)
927 end if
928 end do
929
930 do i=1, n-1
931 dx=x(i+1)-x(i)
932 a=(z(i+1)-z(i))*dx ! coeff intermediaires pour calcul wd
933 b=y(i+1)-y(i)-z(i)*dx ! coeff intermediaires pour calcul wd
934 co(1,i)=y(i)
935 co(2,i)=z(i)
936 !co(3,i)=-(a-3.*b)/dx**2 ! mรฉthode wd
937 !co(4,i)=(a-2.*b)/dx**3 ! mรฉthode wd
938 co(3,i)=(3.e0*var(i+2)-2.e0*z(i)-z(i+1))/dx ! mรฉthode JP Moreau
939 co(4,i)=(z(i)+z(i+1)-2.e0*var(i+2))/dx**2 !
940 ! les coefficients donnรฉs par imsl sont co(3,i)*2 et co(4,i)*6
941 ! etrangement la fonction csval corrige et donne la bonne valeur ...
942 end do
943 co(1,n)=y(n)
944 co(2,n)=z(n)
945 co(3,n)=0.e0
946 co(4,n)=0.e0
947
948 deallocate(z)
949 deallocate(var)
950
951 end subroutine
952
953 ! Double precision
954 subroutine fvn_d_akima(n,x,y,br,co)
955
956 implicit none
957 integer, intent(in) :: n
958 double precision, intent(in) :: x(n)
959 double precision, intent(in) :: y(n)
960 double precision, intent(out) :: br(n)
961 double precision, intent(out) :: co(4,n)
962
963 double precision, allocatable :: var(:),z(:)
964 double precision :: wi_1,wi
965 integer :: i
966 double precision :: dx,a,b
967
968 ! br is just a copy of x
969 br(:)=x(:)
970
971 allocate(var(n))
972 allocate(z(n))
973 ! evaluate the variations
974 do i=1, n-1
975 var(i+2)=(y(i+1)-y(i))/(x(i+1)-x(i))
976 end do
977 var(n+2)=2.d0*var(n+1)-var(n)
978 var(n+3)=2.d0*var(n+2)-var(n+1)
979 var(2)=2.d0*var(3)-var(4)
980 var(1)=2.d0*var(2)-var(3)
981
982 do i = 1, n
983 wi_1=dabs(var(i+3)-var(i+2))
984 wi=dabs(var(i+1)-var(i))
985 if ((wi_1+wi).eq.0.d0) then
986 z(i)=(var(i+2)+var(i+1))/2.d0
987 else
988 z(i)=(wi_1*var(i+1)+wi*var(i+2))/(wi_1+wi)
989 end if
990 end do
991
992 do i=1, n-1
993 dx=x(i+1)-x(i)
994 a=(z(i+1)-z(i))*dx ! coeff intermediaires pour calcul wd
995 b=y(i+1)-y(i)-z(i)*dx ! coeff intermediaires pour calcul wd
996 co(1,i)=y(i)
997 co(2,i)=z(i)
998 !co(3,i)=-(a-3.*b)/dx**2 ! mรฉthode wd
999 !co(4,i)=(a-2.*b)/dx**3 ! mรฉthode wd
1000 co(3,i)=(3.d0*var(i+2)-2.d0*z(i)-z(i+1))/dx ! mรฉthode JP Moreau
1001 co(4,i)=(z(i)+z(i+1)-2.d0*var(i+2))/dx**2 !
1002 ! les coefficients donnรฉs par imsl sont co(3,i)*2 et co(4,i)*6
1003 ! etrangement la fonction csval corrige et donne la bonne valeur ...
1004 end do
1005 co(1,n)=y(n)
1006 co(2,n)=z(n)
1007 co(3,n)=0.d0
1008 co(4,n)=0.d0
1009
1010 deallocate(z)
1011 deallocate(var)
1012
1013 end subroutine
1014
1015 !
1016 ! Single precision spline evaluation
1017 !
1018 function fvn_s_spline_eval(x,n,br,co)
1019 implicit none
1020 real, intent(in) :: x ! x must be br(1)<= x <= br(n+1) otherwise value is extrapolated
1021 integer, intent(in) :: n ! number of intervals
1022 real, intent(in) :: br(n+1) ! breakpoints
1023 real, intent(in) :: co(4,n+1) ! spline coeeficients
1024 real :: fvn_s_spline_eval
1025
1026 integer :: i
1027 real :: dx
1028
1029 if (x<=br(1)) then
1030 i=1
1031 else if (x>=br(n+1)) then
1032 i=n
1033 else
1034 i=1
1035 do while(x>=br(i))
1036 i=i+1
1037 end do
1038 i=i-1
1039 end if
1040 dx=x-br(i)
1041 fvn_s_spline_eval=co(1,i)+co(2,i)*dx+co(3,i)*dx**2+co(4,i)*dx**3
1042
1043 end function
1044
1045 ! Double precision spline evaluation
1046 function fvn_d_spline_eval(x,n,br,co)
1047 implicit none
1048 double precision, intent(in) :: x ! x must be br(1)<= x <= br(n+1) otherwise value is extrapolated
1049 integer, intent(in) :: n ! number of intervals
1050 double precision, intent(in) :: br(n+1) ! breakpoints
1051 double precision, intent(in) :: co(4,n+1) ! spline coeeficients
1052 double precision :: fvn_d_spline_eval
1053
1054 integer :: i
1055 double precision :: dx
1056
1057
1058 if (x<=br(1)) then
1059 i=1
1060 else if (x>=br(n+1)) then
1061 i=n
1062 else
1063 i=1
1064 do while(x>=br(i))
1065 i=i+1
1066 end do
1067 i=i-1
1068 end if
1069
1070 dx=x-br(i)
1071 fvn_d_spline_eval=co(1,i)+co(2,i)*dx+co(3,i)*dx**2+co(4,i)*dx**3
1072
1073 end function
1074
1075
1076 !
1077 ! Muller
1078 !
1079 !
1080 !
1081 ! William Daniau 2007
1082 !
1083 ! This routine is a fortran 90 port of Hans D. Mittelmann's routine muller.f
1084 ! http://plato.asu.edu/ftp/other_software/muller.f
1085 !
1086 ! it can be used as a replacement for imsl routine dzanly with minor changes
1087 !
1088 !-----------------------------------------------------------------------
1089 !
1090 ! purpose - zeros of an analytic complex function
1091 ! using the muller method with deflation
1092 !
1093 ! usage - call fvn_z_muller (f,eps,eps1,kn,n,nguess,x,itmax,
1094 ! infer,ier)
1095 !
1096 ! arguments f - a complex function subprogram, f(z), written
1097 ! by the user specifying the equation whose
1098 ! roots are to be found. f must appear in
1099 ! an external statement in the calling pro-
1100 ! gram.
1101 ! eps - 1st stopping criterion. let fp(z)=f(z)/p
1102 ! where p = (z-z(1))*(z-z(2))*,,,*(z-z(k-1))
1103 ! and z(1),...,z(k-1) are previously found
1104 ! roots. if ((cdabs(f(z)).le.eps) .and.
1105 ! (cdabs(fp(z)).le.eps)), then z is accepted
1106 ! as a root. (input)
1107 ! eps1 - 2nd stopping criterion. a root is accepted
1108 ! if two successive approximations to a given
1109 ! root agree within eps1. (input)
1110 ! note. if either or both of the stopping
1111 ! criteria are fulfilled, the root is
1112 ! accepted.
1113 ! kn - the number of known roots which must be stored
1114 ! in x(1),...,x(kn), prior to entry to muller
1115 ! nguess - the number of initial guesses provided. these
1116 ! guesses must be stored in x(kn+1),...,
1117 ! x(kn+nguess). nguess must be set equal
1118 ! to zero if no guesses are provided. (input)
1119 ! n - the number of new roots to be found by
1120 ! muller (input)
1121 ! x - a complex vector of length kn+n. x(1),...,
1122 ! x(kn) on input must contain any known
1123 ! roots. x(kn+1),..., x(kn+n) on input may,
1124 ! on user option, contain initial guesses for
1125 ! the n new roots which are to be computed.
1126 ! if the user does not provide an initial
1127 ! guess, zero is used.
1128 ! on output, x(kn+1),...,x(kn+n) contain the
1129 ! approximate roots found by muller.
1130 ! itmax - the maximum allowable number of iterations
1131 ! per root (input)
1132 ! infer - an integer vector of length kn+n. on
1133 ! output infer(j) contains the number of
1134 ! iterations used in finding the j-th root
1135 ! when convergence was achieved. if
1136 ! convergence was not obtained in itmax
1137 ! iterations, infer(j) will be greater than
1138 ! itmax (output).
1139 ! ier - error parameter (output)
1140 ! warning error
1141 ! ier = 33 indicates failure to converge with-
1142 ! in itmax iterations for at least one of
1143 ! the (n) new roots.
1144 !
1145 !
1146 ! remarks muller always returns the last approximation for root j
1147 ! in x(j). if the convergence criterion is satisfied,
1148 ! then infer(j) is less than or equal to itmax. if the
1149 ! convergence criterion is not satisified, then infer(j)
1150 ! is set to either itmax+1 or itmax+k, with k greater
1151 ! than 1. infer(j) = itmax+1 indicates that muller did
1152 ! not obtain convergence in the allowed number of iter-
1153 ! ations. in this case, the user may wish to set itmax
1154 ! to a larger value. infer(j) = itmax+k means that con-
1155 ! vergence was obtained (on iteration k) for the defla-
1156 ! ted function
1157 ! fp(z) = f(z)/((z-z(1)...(z-z(j-1)))
1158 !
1159 ! but failed for f(z). in this case, better initial
1160 ! guesses might help or, it might be necessary to relax
1161 ! the convergence criterion.
1162 !
1163 !-----------------------------------------------------------------------
1164 !
1165 subroutine fvn_z_muller (f,eps,eps1,kn,nguess,n,x,itmax,infer,ier)
1166 implicit none
1167 double precision :: rzero,rten,rhun,rp01,ax,eps1,qz,eps,tpq
1168 double complex :: d,dd,den,fprt,frt,h,rt,t1,t2,t3, &
1169 tem,z0,z1,z2,bi,xx,xl,y0,y1,y2,x0, &
1170 zero,p1,one,four,p5
1171
1172 double complex, external :: f
1173 integer :: ickmax,kn,nguess,n,itmax,ier,knp1,knpn,i,l,ic, &
1174 knpng,jk,ick,nn,lm1,errcode
1175 double complex :: x(kn+n)
1176 integer :: infer(kn+n)
1177
1178
1179 data zero/(0.0,0.0)/,p1/(0.1,0.0)/, &
1180 one/(1.0,0.0)/,four/(4.0,0.0)/, &
1181 p5/(0.5,0.0)/, &
1182 rzero/0.0/,rten/10.0/,rhun/100.0/, &
1183 ax/0.1/,ickmax/3/,rp01/0.01/
1184
1185 ier = 0
1186 if (n .lt. 1) then ! What the hell are doing here then ...
1187 return
1188 end if
1189 !eps1 = rten **(-nsig)
1190 eps1 = min(eps1,rp01)
1191
1192 knp1 = kn+1
1193 knpn = kn+n
1194 knpng = kn+nguess
1195 do i=1,knpn
1196 infer(i) = 0
1197 if (i .gt. knpng) x(i) = zero
1198 end do
1199 l= knp1
1200
1201 ic=0
1202 rloop: do while (l<=knpn) ! Main loop over new roots
1203 jk = 0
1204 ick = 0
1205 xl = x(l)
1206 icloop: do
1207 ic = 0
1208 h = ax
1209 h = p1*h
1210 if (cdabs(xl) .gt. ax) h = p1*xl
1211 ! first three points are
1212 ! xl+h, xl-h, xl
1213 rt = xl+h
1214 call deflated_work(errcode)
1215 if (errcode == 1) then
1216 exit icloop
1217 end if
1218
1219 z0 = fprt
1220 y0 = frt
1221 x0 = rt
1222 rt = xl-h
1223 call deflated_work(errcode)
1224 if (errcode == 1) then
1225 exit icloop
1226 end if
1227
1228 z1 = fprt
1229 y1 = frt
1230 h = xl-rt
1231 d = h/(rt-x0)
1232 rt = xl
1233
1234 call deflated_work(errcode)
1235 if (errcode == 1) then
1236 exit icloop
1237 end if
1238
1239
1240 z2 = fprt
1241 y2 = frt
1242 ! begin main algorithm
1243 iloop: do
1244 dd = one + d
1245 t1 = z0*d*d
1246 t2 = z1*dd*dd
1247 xx = z2*dd
1248 t3 = z2*d
1249 bi = t1-t2+xx+t3
1250 den = bi*bi-four*(xx*t1-t3*(t2-xx))
1251 ! use denominator of maximum amplitude
1252 t1 = cdsqrt(den)
1253 qz = rhun*max(cdabs(bi),cdabs(t1))
1254 t2 = bi + t1
1255 tpq = cdabs(t2)+qz
1256 if (tpq .eq. qz) t2 = zero
1257 t3 = bi - t1
1258 tpq = cdabs(t3) + qz
1259 if (tpq .eq. qz) t3 = zero
1260 den = t2
1261 qz = cdabs(t3)-cdabs(t2)
1262 if (qz .gt. rzero) den = t3
1263 ! test for zero denominator
1264 if (cdabs(den) .eq. rzero) then
1265 call trans_rt()
1266 call deflated_work(errcode)
1267 if (errcode == 1) then
1268 exit icloop
1269 end if
1270 z2 = fprt
1271 y2 = frt
1272 cycle iloop
1273 end if
1274
1275
1276 d = -xx/den
1277 d = d+d
1278 h = d*h
1279 rt = rt + h
1280 ! check convergence of the first kind
1281 if (cdabs(h) .le. eps1*max(cdabs(rt),ax)) then
1282 if (ic .ne. 0) then
1283 exit icloop
1284 end if
1285 ic = 1
1286 z0 = y1
1287 z1 = y2
1288 z2 = f(rt)
1289 xl = rt
1290 ick = ick+1
1291 if (ick .le. ickmax) then
1292 cycle iloop
1293 end if
1294 ! warning error, itmax = maximum
1295 jk = itmax + jk
1296 ier = 33
1297 end if
1298 if (ic .ne. 0) then
1299 cycle icloop
1300 end if
1301 call deflated_work(errcode)
1302 if (errcode == 1) then
1303 exit icloop
1304 end if
1305
1306 do while ( (cdabs(fprt)-cdabs(z2)*rten) .ge. rzero)
1307 ! take remedial action to induce
1308 ! convergence
1309 d = d*p5
1310 h = h*p5
1311 rt = rt-h
1312 call deflated_work(errcode)
1313 if (errcode == 1) then
1314 exit icloop
1315 end if
1316 end do
1317 z0 = z1
1318 z1 = z2
1319 z2 = fprt
1320 y0 = y1
1321 y1 = y2
1322 y2 = frt
1323 end do iloop
1324 end do icloop
1325 x(l) = rt
1326 infer(l) = jk
1327 l = l+1
1328 end do rloop
1329
1330 contains
1331 subroutine trans_rt()
1332 tem = rten*eps1
1333 if (cdabs(rt) .gt. ax) tem = tem*rt
1334 rt = rt+tem
1335 d = (h+tem)*d/h
1336 h = h+tem
1337 end subroutine trans_rt
1338
1339 subroutine deflated_work(errcode)
1340 ! errcode=0 => no errors
1341 ! errcode=1 => jk>itmax or convergence of second kind achieved
1342 integer :: errcode,flag
1343
1344 flag=1
1345 loop1: do while(flag==1)
1346 errcode=0
1347 jk = jk+1
1348 if (jk .gt. itmax) then
1349 ier=33
1350 errcode=1
1351 return
1352 end if
1353 frt = f(rt)
1354 fprt = frt
1355 if (l /= 1) then
1356 lm1 = l-1
1357 do i=1,lm1
1358 tem = rt - x(i)
1359 if (cdabs(tem) .eq. rzero) then
1360 !if (ic .ne. 0) go to 15 !! ?? possible?
1361 call trans_rt()
1362 cycle loop1
1363 end if
1364 fprt = fprt/tem
1365 end do
1366 end if
1367 flag=0
1368 end do loop1
1369
1370 if (cdabs(fprt) .le. eps .and. cdabs(frt) .le. eps) then
1371 errcode=1
1372 return
1373 end if
1374
1375 end subroutine deflated_work
1376
1377 end subroutine
1378
1379
1380 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1381 !
1382 ! Integration
1383 !
1384 ! Only double precision coded atm
1385 !
1386 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1387
1388
1389 subroutine fvn_d_gauss_legendre(n,qx,qw)
1390 !
1391 ! This routine compute the n Gauss Legendre abscissas and weights
1392 ! Adapted from Numerical Recipes routine gauleg
1393 !
1394 ! n (in) : number of points
1395 ! qx(out) : abscissas
1396 ! qw(out) : weights
1397 !
1398 implicit none
1399 double precision,parameter :: pi=3.141592653589793d0
1400 integer, intent(in) :: n
1401 double precision, intent(out) :: qx(n),qw(n)
1402
1403 integer :: m,i,j
1404 double precision :: z,z1,p1,p2,p3,pp
1405 m=(n+1)/2
1406 do i=1,m
1407 z=cos(pi*(dble(i)-0.25d0)/(dble(n)+0.5d0))
1408 iloop: do
1409 p1=1.d0
1410 p2=0.d0
1411 do j=1,n
1412 p3=p2
1413 p2=p1
1414 p1=((2.d0*dble(j)-1.d0)*z*p2-(dble(j)-1.d0)*p3)/dble(j)
1415 end do
1416 pp=dble(n)*(z*p1-p2)/(z*z-1.d0)
1417 z1=z
1418 z=z1-p1/pp
1419 if (dabs(z-z1)<=epsilon(z)) then
1420 exit iloop
1421 end if
1422 end do iloop
1423 qx(i)=-z
1424 qx(n+1-i)=z
1425 qw(i)=2.d0/((1.d0-z*z)*pp*pp)
1426 qw(n+1-i)=qw(i)
1427 end do
1428 end subroutine
1429
1430
1431
1432 subroutine fvn_d_gl_integ(f,a,b,n,res)
1433 !
1434 ! This is a simple non adaptative integration routine
1435 ! using n gauss legendre abscissas and weights
1436 !
1437 ! f(in) : the function to integrate
1438 ! a(in) : lower bound
1439 ! b(in) : higher bound
1440 ! n(in) : number of gauss legendre pairs
1441 ! res(out): the evaluation of the integral
1442 !
1443 double precision,external :: f
1444 double precision, intent(in) :: a,b
1445 integer, intent(in):: n
1446 double precision, intent(out) :: res
1447
1448 double precision, allocatable :: qx(:),qw(:)
1449 double precision :: xm,xr
1450 integer :: i
1451
1452 ! First compute n gauss legendre abs and weight
1453 allocate(qx(n))
1454 allocate(qw(n))
1455 call fvn_d_gauss_legendre(n,qx,qw)
1456
1457 xm=0.5d0*(b+a)
1458 xr=0.5d0*(b-a)
1459
1460 res=0.d0
1461
1462 do i=1,n
1463 res=res+qw(i)*f(xm+xr*qx(i))
1464 end do
1465
1466 res=xr*res
1467
1468 deallocate(qw)
1469 deallocate(qx)
1470
1471 end subroutine
1472
1473 !!!!!!!!!!!!!!!!!!!!!!!!
1474 !
1475 ! Simple and double adaptative Gauss Kronrod integration based on
1476 ! a modified version of quadpack ( http://www.netlib.org/quadpack
1477 !
1478 ! Common parameters :
1479 !
1480 ! key (in)
1481 ! epsabs
1482 ! epsrel
1483 !
1484 !
1485 !!!!!!!!!!!!!!!!!!!!!!!!
1486
1487 subroutine fvn_d_integ_1_gk(f,a,b,epsabs,epsrel,key,res,abserr,ier,limit)
1488 !
1489 ! Evaluate the integral of function f(x) between a and b
1490 !
1491 ! f(in) : the function
1492 ! a(in) : lower bound
1493 ! b(in) : higher bound
1494 ! epsabs(in) : desired absolute error
1495 ! epsrel(in) : desired relative error
1496 ! key(in) : gauss kronrod rule
1497 ! 1: 7 - 15 points
1498 ! 2: 10 - 21 points
1499 ! 3: 15 - 31 points
1500 ! 4: 20 - 41 points
1501 ! 5: 25 - 51 points
1502 ! 6: 30 - 61 points
1503 !
1504 ! limit(in) : maximum number of subintervals in the partition of the
1505 ! given integration interval (a,b). A value of 500 will give the same
1506 ! behaviour as the imsl routine dqdag
1507 !
1508 ! res(out) : estimated integral value
1509 ! abserr(out) : estimated absolute error
1510 ! ier(out) : error flag from quadpack routines
1511 ! 0 : no error
1512 ! 1 : maximum number of subdivisions allowed
1513 ! has been achieved. one can allow more
1514 ! subdivisions by increasing the value of
1515 ! limit (and taking the according dimension
1516 ! adjustments into account). however, if
1517 ! this yield no improvement it is advised
1518 ! to analyze the integrand in order to
1519 ! determine the integration difficulaties.
1520 ! if the position of a local difficulty can
1521 ! be determined (i.e.singularity,
1522 ! discontinuity within the interval) one
1523 ! will probably gain from splitting up the
1524 ! interval at this point and calling the
1525 ! integrator on the subranges. if possible,
1526 ! an appropriate special-purpose integrator
1527 ! should be used which is designed for
1528 ! handling the type of difficulty involved.
1529 ! 2 : the occurrence of roundoff error is
1530 ! detected, which prevents the requested
1531 ! tolerance from being achieved.
1532 ! 3 : extremely bad integrand behaviour occurs
1533 ! at some points of the integration
1534 ! interval.
1535 ! 6 : the input is invalid, because
1536 ! (epsabs.le.0 and
1537 ! epsrel.lt.max(50*rel.mach.acc.,0.5d-28))
1538 ! or limit.lt.1 or lenw.lt.limit*4.
1539 ! result, abserr, neval, last are set
1540 ! to zero.
1541 ! except when lenw is invalid, iwork(1),
1542 ! work(limit*2+1) and work(limit*3+1) are
1543 ! set to zero, work(1) is set to a and
1544 ! work(limit+1) to b.
1545
1546 implicit none
1547 double precision, external :: f
1548 double precision, intent(in) :: a,b,epsabs,epsrel
1549 integer, intent(in) :: key
1550 integer, intent(in) :: limit
1551 double precision, intent(out) :: res,abserr
1552 integer, intent(out) :: ier
1553
1554 double precision, allocatable :: work(:)
1555 integer, allocatable :: iwork(:)
1556 integer :: lenw,neval,last
1557
1558 ! imsl value for limit is 500
1559 lenw=limit*4
1560
1561 allocate(iwork(limit))
1562 allocate(work(lenw))
1563
1564 call dqag(f,a,b,epsabs,epsrel,key,res,abserr,neval,ier,limit,lenw,last,iwork,work)
1565
1566 deallocate(work)
1567 deallocate(iwork)
1568
1569 end subroutine
1570
1571