grid_tools 1.14.0
Loading...
Searching...
No Matches
pmat.f90
Go to the documentation of this file.
1
5
6!! Utility routines for various linear inversions and Cholesky.
7!!
8!! Originally, these routines were copies of the purely "inversion" members
9!! of pmat1.f90 (a most extensive collection of matrix routines -- not just
10!! inversions). As well as having both single and double precision versions
11!! of each routine, these versions also make provision for a more graceful
12!! termination in cases where the system matrix is detected to be
13!! essentially singular (and therefore noninvertible). This provision takes
14!! the form of an optional "failure flag", FF, which is normally returned
15!! as .FALSE., but is returned as .TRUE. when inversion fails.
16!! In Sep 2012, these routines were collected together into pmat.f90 so
17!! that all the main matrix routines could be in the same library, pmat.a.
18!!
19!! @author R. J. Purser
20module pmat
21use pkind, only: spi,sp,dp,spc,dpc
22use pietc, only: t,f
23implicit none
24private
26interface swpvv; module procedure sswpvv,dswpvv,cswpvv; end interface
27interface ldum
28 module procedure sldum,dldum,cldum,sldumf,dldumf,cldumf; end interface
29interface udlmm
30 module procedure sudlmm,dudlmm,cudlmm,sudlmv,dudlmv,cudlmv; end interface
31interface inv
32 module procedure &
33sinvmt, dinvmt, cinvmt, slinmmt, dlinmmt, clinmmt, slinmvt, dlinmvt, clinmvt, &
34sinvmtf,dinvmtf,cinvmtf,slinmmtf,dlinmmtf,clinmmtf,slinmvtf,dlinmvtf,clinmvtf,&
35iinvf
36 end interface
37interface l1lm; module procedure sl1lm,dl1lm,sl1lmf,dl1lmf; end interface
38interface ldlm; module procedure sldlm,dldlm,sldlmf,dldlmf; end interface
39interface invl; module procedure sinvl,dinvl,slinlv,dlinlv; end interface
40interface invu; module procedure sinvu,dinvu,slinuv,dlinuv; end interface
41
42contains
43
49subroutine sswpvv(d,e)! [swpvv]
50real(sp), intent(inout) :: d(:), e(:)
51real(sp) :: tv(size(d))
52tv = d; d = e; e = tv
53end subroutine sswpvv
54
60subroutine dswpvv(d,e)! [swpvv]
61real(dp), intent(inout) :: d(:), e(:)
62real(dp) :: tv(size(d))
63tv = d; d = e; e = tv
64end subroutine dswpvv
65
71subroutine cswpvv(d,e)! [swpvv]
72complex(dpc),intent(inout) :: d(:), e(:)
73complex(dpc) :: tv(size(d))
74tv = d; d = e; e = tv
75end subroutine cswpvv
76
81subroutine sinvmt(a)! [inv]
82real(sp),dimension(:,:),intent(INOUT):: a
83logical :: ff
84call sinvmtf(a,ff)
85if(ff)stop 'In sinvmt; Unable to invert matrix'
86end subroutine sinvmt
87
92subroutine dinvmt(a)! [inv]
93real(dp),dimension(:,:),intent(inout):: a
94logical :: ff
95call dinvmtf(a,ff)
96if(ff)stop 'In dinvmt; Unable to invert matrix'
97end subroutine dinvmt
98
103subroutine cinvmt(a)! [inv]
104complex(dpc),dimension(:,:),intent(inout):: a
105logical :: ff
106call cinvmtf(a,ff)
107if(ff)stop 'In cinvmt; Unable to invert matrix'
108end subroutine cinvmt
109
115subroutine sinvmtf(a,ff)! [inv]
116use pietc_s, only: u1
117real(sp),dimension(:,:),intent(inout):: a
118logical, intent( out):: ff
119integer(spi) :: m,i,j,jp,l
120real(sp) :: d
121integer(spi),dimension(size(a,1)):: ipiv
122m=size(a,1)
123if(m /= size(a,2))stop 'In sinvmtf; matrix passed to sinvmtf is not square'
124! Perform a pivoted L-D-U decomposition on matrix a:
125call sldumf(a,ipiv,d,ff)
126if(ff)then
127 print '(" In sinvmtf; failed call to sldumf")'
128 return
129endif
130! Invert upper triangular portion U in place:
131do i=1,m; a(i,i)=u1/a(i,i); enddo
132do i=1,m-1
133 do j=i+1,m; a(i,j)=-a(j,j)*dot_product(a(i:j-1,j),a(i,i:j-1)); enddo
134enddo
135! Invert lower triangular portion L in place:
136do j=1,m-1; jp=j+1
137 do i=jp,m; a(i,j)=-a(i,j)-dot_product(a(jp:i-1,j),a(i,jp:i-1)); enddo
138enddo
139! Form the product of U**-1 and L**-1 in place
140do j=1,m-1; jp=j+1
141 do i=1,j; a(i,j)=a(i,j)+dot_product(a(jp:m,j),a(i,jp:m)); enddo
142 do i=jp,m; a(i,j)=dot_product(a(i:m,j),a(i,i:m)); enddo
143enddo
144! Permute columns according to ipiv
145do j=m-1,1,-1; l=ipiv(j); call sswpvv(a(:,j),a(:,l)); enddo
146end subroutine sinvmtf
147
153subroutine dinvmtf(a,ff)! [inv]
154real(dp),dimension(:,:),intent(inout):: a
155logical, intent( out):: ff
156integer(spi) :: m,i,j,jp,l
157real(dp) :: d
158integer(spi), dimension(size(a,1)) :: ipiv
159m=size(a,1)
160if(m /= size(a,2))stop 'In inv; matrix passed to dinvmtf is not square'
161! Perform a pivoted L-D-U decomposition on matrix a:
162call dldumf(a,ipiv,d,ff)
163if(ff)then
164 print '(" In dinvmtf; failed call to dldumf")'
165 return
166endif
167! Invert upper triangular portion U in place:
168do i=1,m; a(i,i)=1_dp/a(i,i); enddo
169do i=1,m-1
170 do j=i+1,m; a(i,j)=-a(j,j)*dot_product(a(i:j-1,j),a(i,i:j-1)); enddo
171enddo
172! Invert lower triangular portion L in place:
173do j=1,m-1; jp=j+1
174 do i=jp,m; a(i,j)=-a(i,j)-dot_product(a(jp:i-1,j),a(i,jp:i-1)); enddo
175enddo
176! Form the product of U**-1 and L**-1 in place
177do j=1,m-1; jp=j+1
178 do i=1,j; a(i,j)=a(i,j)+dot_product(a(jp:m,j),a(i,jp:m)); enddo
179 do i=jp,m; a(i,j)=dot_product(a(i:m,j),a(i,i:m)); enddo
180enddo
181! Permute columns according to ipiv
182do j=m-1,1,-1; l=ipiv(j); call dswpvv(a(:,j),a(:,l)); enddo
183end subroutine dinvmtf
184
190subroutine cinvmtf(a,ff)! [inv]
191use pietc, only: c1
192complex(dpc),dimension(:,:),intent(INOUT):: a
193logical, intent( OUT):: ff
194integer(spi) :: m,i,j,jp,l
195complex(dpc) :: d
196integer(spi),dimension(size(a,1)):: ipiv
197m=size(a,1)
198if(m /= size(a,2))stop 'In inv; matrix passed to cinvmtf is not square'
199! Perform a pivoted L-D-U decomposition on matrix a:
200call cldumf(a,ipiv,d,ff)
201if(ff)then
202 print '(" In cinvmtf; failed call to cldumf")'
203 return
204endif
205! Invert upper triangular portion U in place:
206do i=1,m; a(i,i)=c1/a(i,i); enddo
207do i=1,m-1
208 do j=i+1,m; a(i,j)=-a(j,j)*sum(a(i:j-1,j)*a(i,i:j-1)); enddo
209enddo
210! Invert lower triangular portion L in place:
211do j=1,m-1; jp=j+1
212 do i=jp,m; a(i,j)=-a(i,j)-sum(a(jp:i-1,j)*a(i,jp:i-1)); enddo
213enddo
214! Form the product of U**-1 and L**-1 in place
215do j=1,m-1; jp=j+1
216 do i=1,j; a(i,j)=a(i,j)+sum(a(jp:m,j)*a(i,jp:m)); enddo
217 do i=jp,m; a(i,j)=sum(a(i:m,j)*a(i,i:m)); enddo
218enddo
219! Permute columns according to ipiv
220do j=m-1,1,-1; l=ipiv(j); call cswpvv(a(:,j),a(:,l)); enddo
221end subroutine cinvmtf
222
229subroutine slinmmt(a,b)! [inv]
230real(sp),dimension(:,:),intent(inout):: a,b
231logical :: ff
232call slinmmtf(a,b,ff)
233if(ff)stop 'In slinmmt; unable to invert linear system'
234end subroutine slinmmt
235
242subroutine dlinmmt(a,b)! [inv]
243real(dp),dimension(:,:),intent(inout):: a,b
244logical :: ff
245call dlinmmtf(a,b,ff)
246if(ff)stop 'In dlinmmt; unable to invert linear system'
247end subroutine dlinmmt
248
255subroutine clinmmt(a,b)! [inv]
256complex(dpc),dimension(:,:),intent(inout):: a,b
257logical :: ff
258call clinmmtf(a,b,ff)
259if(ff)stop 'In clinmmt; unable to invert linear system'
260end subroutine clinmmt
261
269subroutine slinmmtf(a,b,ff)! [inv]
270real(sp), dimension(:,:),intent(inout):: a,b
271logical, intent( out):: ff
272integer(spi),dimension(size(a,1)) :: ipiv
273integer(spi) :: m
274real(sp) :: d
275m=size(a,1)
276if(m /= size(a,2))stop 'In inv; matrix passed to slinmmtf is not square'
277if(m /= size(b,1))&
278 stop 'In inv; matrix and vectors in slinmmtf have unmatched sizes'
279call sldumf(a,ipiv,d,ff)
280if(ff)then
281 print '("In slinmmtf; failed call to sldumf")'
282 return
283endif
284call sudlmm(a,b,ipiv)
285end subroutine slinmmtf
286
294subroutine dlinmmtf(a,b,ff)! [inv]
295real(dp),dimension(:,:), intent(inout):: a,b
296logical, intent( out):: ff
297integer(spi),dimension(size(a,1)):: ipiv
298integer(spi):: m
299real(dp) :: d
300m=size(a,1)
301if(m /= size(a,2))stop 'In inv; matrix passed to dlinmmtf is not square'
302if(m /= size(b,1))&
303 stop 'In inv; matrix and vectors in dlinmmtf have unmatched sizes'
304call dldumf(a,ipiv,d,ff)
305if(ff)then
306 print '("In dlinmmtf; failed call to dldumf")'
307 return
308endif
309call dudlmm(a,b,ipiv)
310end subroutine dlinmmtf
311
319subroutine clinmmtf(a,b,ff)! [inv]
320complex(dpc),dimension(:,:),intent(INOUT):: a,b
321logical, intent( OUT):: ff
322integer(spi),dimension(size(a,1)):: ipiv
323integer(spi) :: m
324complex(dpc) :: d
325m=size(a,1)
326if(m /= size(a,2))stop 'In inv; matrix passed to dlinmmtf is not square'
327if(m /= size(b,1))&
328 stop 'In inv; matrix and vectors in dlinmmtf have unmatched sizes'
329call cldumf(a,ipiv,d,ff)
330if(ff)then
331 print '("In clinmmtf; failed call to cldumf")'
332 return
333endif
334call cudlmm(a,b,ipiv)
335end subroutine clinmmtf
336
343subroutine slinmvt(a,b)! [inv]
344real(sp),dimension(:,:),intent(inout):: a
345real(sp),dimension(:), intent(inout):: b
346logical:: ff
347call slinmvtf(a,b,ff)
348if(ff)stop 'In slinmvt; matrix singular, unable to continue'
349end subroutine slinmvt
350
357subroutine dlinmvt(a,b)! [inv]
358real(dp),dimension(:,:),intent(inout):: a
359real(dp),dimension(:), intent(inout):: b
360logical :: ff
361call dlinmvtf(a,b,ff)
362if(ff)stop 'In dlinmvt; matrix singular, unable to continue'
363end subroutine dlinmvt
364
371subroutine clinmvt(a,b)! [inv]
372complex(dpc), dimension(:,:),intent(inout):: a
373complex(dpc), dimension(:), intent(inout):: b
374logical :: ff
375call clinmvtf(a,b,ff)
376if(ff)stop 'In clinmvt; matrix singular, unable to continue'
377end subroutine clinmvt
378
385subroutine slinmvtf(a,b,ff)! [inv]
386real(sp),dimension(:,:),intent(inout):: a
387real(sp),dimension(:), intent(inout):: b
388logical, intent( out):: ff
389integer(spi),dimension(size(a,1)) :: ipiv
390real(sp) :: d
391if(size(a,1) /= size(a,2).or. size(a,1) /= size(b))&
392 stop 'In inv; In slinmvtf; incompatible array dimensions'
393call sldumf(a,ipiv,d,ff)
394if(ff)then
395 print '("In slinmvtf; failed call to sldumf")'
396 return
397endif
398call sudlmv(a,b,ipiv)
399end subroutine slinmvtf
400
407subroutine dlinmvtf(a,b,ff)! [inv]
408real(dp),dimension(:,:),intent(inout):: a
409real(dp),dimension(:), intent(inout):: b
410logical, intent( out):: ff
411integer(spi), dimension(size(a,1)) :: ipiv
412real(dp) :: d
413if(size(a,1) /= size(a,2).or. size(a,1) /= size(b))&
414 stop 'In inv; incompatible array dimensions passed to dlinmvtf'
415call dldumf(a,ipiv,d,ff)
416if(ff)then
417 print '("In dlinmvtf; failed call to dldumf")'
418 return
419endif
420call dudlmv(a,b,ipiv)
421end subroutine dlinmvtf
422
429subroutine clinmvtf(a,b,ff)! [inv]
430complex(dpc),dimension(:,:),intent(inout):: a
431complex(dpc),dimension(:), intent(inout):: b
432logical, intent( out):: ff
433integer, dimension(size(a,1)) :: ipiv
434complex(dpc) :: d
435if(size(a,1) /= size(a,2).or. size(a,1) /= size(b))&
436 stop 'In inv; incompatible array dimensions passed to clinmvtf'
437call cldumf(a,ipiv,d,ff)
438if(ff)then
439 print '("In clinmvtf; failed call to cldumf")'
440 return
441endif
442call cudlmv(a,b,ipiv)
443end subroutine clinmvtf
444
451subroutine iinvf(imat,ff)! [inv]
452integer(spi),dimension(:,:),intent(INOUT):: imat
453logical, intent( OUT):: ff
454real(dp),parameter :: eps=1.e-6_dp
455real(dp),dimension(size(imat,1),size(imat,1)):: dmat
456integer(spi) :: m,i,j
457m=size(imat,1)
458if(m /= size(imat,2))stop 'In inv; matrix passed to iinvf is not square'
459dmat=imat; call inv(dmat,ff)
460if(.not.ff)then
461 do j=1,m
462 do i=1,m
463 imat(i,j)=nint(dmat(i,j)); if(abs(dmat(i,j)-imat(i,j))>eps)ff=t
464 enddo
465 enddo
466endif
467end subroutine iinvf
468
476subroutine sldum(a,ipiv,d)! [ldum]
477real(sp), intent(inout) :: a(:,:)
478real(sp), intent( out) :: d
479integer(spi),intent( out) :: ipiv(:)
480logical:: ff
481call sldumf(a,ipiv,d,ff)
482if(ff)stop 'In sldum; matrix singular, unable to continue'
483end subroutine sldum
484
492subroutine dldum(a,ipiv,d)! [ldum]
493real(dp), intent(inout) :: a(:,:)
494real(dp), intent( out) :: d
495integer(spi),intent( out) :: ipiv(:)
496logical:: ff
497call dldumf(a,ipiv,d,ff)
498if(ff)stop 'In dldum; matrix singular, unable to continue'
499end subroutine dldum
500
508subroutine cldum(a,ipiv,d)! [ldum]
509complex(dpc),intent(inout) :: a(:,:)
510complex(dpc),intent(out ) :: d
511integer(spi),intent(out ) :: ipiv(:)
512logical:: ff
513call cldumf(a,ipiv,d,ff)
514if(ff)stop 'In cldum; matrix singular, unable to continue'
515end subroutine cldum
516
525subroutine sldumf(a,ipiv,d,ff)! [ldum]
526use pietc_s,only: u0,u1
527real(sp), intent(inout) :: a(:,:)
528real(sp), intent( out) :: d
529integer(spi),intent( out) :: ipiv(:)
530logical, intent( out) :: ff
531integer(spi):: m,i, j, jp, ibig, jm
532real(sp) :: s(size(a,1)), aam, aa, abig, ajj, ajji, aij
533ff=f
534m=size(a,1)
535do i=1,m
536 aam=u0
537 do j=1,m
538 aa=abs(a(i,j))
539 if(aa > aam)aam=aa
540 enddo
541 if(aam == u0)then
542 print '("In sldumf; row ",i6," of matrix vanishes")',i
543 ff=t
544 return
545 endif
546 s(i)=u1/aam
547enddo
548d=1_sp
549ipiv(m)=m
550do j=1,m-1
551 jp=j+1
552 abig=s(j)*abs(a(j,j))
553 ibig=j
554 do i=jp,m
555 aa=s(i)*abs(a(i,j))
556 if(aa > abig)then
557 ibig=i
558 abig=aa
559 endif
560 enddo
561! swap rows, recording changed sign of determinant
562 ipiv(j)=ibig
563 if(ibig /= j)then
564 d=-d
565 call sswpvv(a(j,:),a(ibig,:))
566 s(ibig)=s(j)
567 endif
568 ajj=a(j,j)
569 if(ajj == u0)then
570 jm=j-1
571 print '(" failure in sldumf:"/" matrix singular, rank=",i3)',jm
572 ff=t
573 return
574 endif
575 ajji=u1/ajj
576 do i=jp,m
577 aij=ajji*a(i,j)
578 a(i,j)=aij
579 a(i,jp:m) = a(i,jp:m) - aij*a(j,jp:m)
580 enddo
581enddo
582end subroutine sldumf
583
592subroutine dldumf(a,ipiv,d,ff)! [ldum]
593use pietc, only: u0,u1
594real(dp), intent(inout) :: a(:,:)
595real(dp), intent( out) :: d
596integer, intent( out) :: ipiv(:)
597logical(spi),intent( out) :: ff
598integer(spi) :: m,i, j, jp, ibig, jm
599real(dp) :: s(size(a,1)), aam, aa, abig, ajj, ajji, aij
600ff=f
601m=size(a,1)
602do i=1,m
603 aam=u0
604 do j=1,m
605 aa=abs(a(i,j))
606 if(aa > aam)aam=aa
607 enddo
608 if(aam == u0)then
609 print '("In dldumf; row ",i6," of matrix vanishes")',i
610 ff=t
611 return
612 endif
613 s(i)=u1/aam
614enddo
615d=u1
616ipiv(m)=m
617do j=1,m-1
618 jp=j+1
619 abig=s(j)*abs(a(j,j))
620 ibig=j
621 do i=jp,m
622 aa=s(i)*abs(a(i,j))
623 if(aa > abig)then
624 ibig=i
625 abig=aa
626 endif
627 enddo
628 ! swap rows, recording changed sign of determinant
629 ipiv(j)=ibig
630 if(ibig /= j)then
631 d=-d
632 call dswpvv(a(j,:),a(ibig,:))
633 s(ibig)=s(j)
634 endif
635 ajj=a(j,j)
636 if(ajj == u0)then
637 jm=j-1
638 print '(" Failure in dldumf:"/" matrix singular, rank=",i3)',jm
639 ff=t
640 return
641 endif
642 ajji=u1/ajj
643 do i=jp,m
644 aij=ajji*a(i,j)
645 a(i,j)=aij
646 a(i,jp:m) = a(i,jp:m) - aij*a(j,jp:m)
647 enddo
648enddo
649end subroutine dldumf
650
659subroutine cldumf(a,ipiv,d,ff)! [ldum]
660use pietc, only: u0,u1,c0,c1
661complex(dpc), intent(inout) :: a(:,:)
662complex(dpc), intent( out) :: d
663integer(spi), intent( out) :: ipiv(:)
664logical, intent( out) :: ff
665integer(spi) :: m,i, j, jp, ibig, jm
666complex(dpc) :: ajj, ajji, aij
667real(dp) :: aam,aa,abig
668real(dp),dimension(size(a,1)):: s
669ff=f
670m=size(a,1)
671do i=1,m
672 aam=u0
673 do j=1,m
674 aa=abs(a(i,j))
675 if(aa > aam)aam=aa
676 enddo
677 if(aam == u0)then
678 print '("In cldumf; row ",i6," of matrix vanishes")',i
679 ff=t
680 return
681 endif
682 s(i)=u1/aam
683enddo
684d=c1
685ipiv(m)=m
686do j=1,m-1
687 jp=j+1
688 abig=s(j)*abs(a(j,j))
689 ibig=j
690 do i=jp,m
691 aa=s(i)*abs(a(i,j))
692 if(aa > abig)then
693 ibig=i
694 abig=aa
695 endif
696 enddo
697 ! swap rows, recording changed sign of determinant
698 ipiv(j)=ibig
699 if(ibig /= j)then
700 d=-d
701 call cswpvv(a(j,:),a(ibig,:))
702 s(ibig)=s(j)
703 endif
704 ajj=a(j,j)
705 if(ajj == c0)then
706 jm=j-1
707 print '(" Failure in cldumf:"/" matrix singular, rank=",i3)',jm
708 ff=t
709 return
710 endif
711 ajji=c1/ajj
712 do i=jp,m
713 aij=ajji*a(i,j)
714 a(i,j)=aij
715 a(i,jp:m) = a(i,jp:m) - aij*a(j,jp:m)
716 enddo
717enddo
718end subroutine cldumf
719
729subroutine sudlmm(a,b,ipiv)! [udlmm]
730use pietc_s, only: u1
731integer(spi),dimension(:), intent(in) :: ipiv
732real(sp), dimension(:,:),intent(in) :: a
733real(sp), dimension(:,:),intent(inout) :: b
734integer(spi):: m,i, k, l
735real(sp) :: s,aiii
736m=size(a,1)
737do k=1,size(b,2) !loop over columns of b
738 do i=1,m
739 l=ipiv(i)
740 s=b(l,k)
741 b(l,k)=b(i,k)
742 s = s - sum(b(1:i-1,k)*a(i,1:i-1))
743 b(i,k)=s
744 enddo
745 b(m,k)=b(m,k)/a(m,m)
746 do i=m-1,1,-1
747 aiii=u1/a(i,i)
748 b(i,k) = b(i,k) - sum(b(i+1:m,k)*a(i,i+1:m))
749 b(i,k)=b(i,k)*aiii
750 enddo
751enddo
752end subroutine sudlmm
753
763subroutine dudlmm(a,b,ipiv)! [udlmm]
764use pietc, only: u1
765integer(spi),dimension(:), intent(in ) :: ipiv
766real(dp), dimension(:,:),intent(in ) :: a
767real(dp), dimension(:,:),intent(inout) :: b
768integer(spi):: m,i, k, l
769real(dp) :: s,aiii
770m=size(a,1)
771do k=1, size(b,2)!loop over columns of b
772 do i=1,m
773 l=ipiv(i)
774 s=b(l,k)
775 b(l,k)=b(i,k)
776 s = s - sum(b(1:i-1,k)*a(i,1:i-1))
777 b(i,k)=s
778 enddo
779 b(m,k)=b(m,k)/a(m,m)
780 do i=m-1,1,-1
781 aiii=u1/a(i,i)
782 b(i,k) = b(i,k) - sum(b(i+1:m,k)*a(i,i+1:m))
783 b(i,k)=b(i,k)*aiii
784 enddo
785enddo
786end subroutine dudlmm
787
797subroutine cudlmm(a,b,ipiv)! [udlmm]
798use pietc, only: c1
799integer(spi),dimension(:), intent(in ) :: ipiv
800complex(dpc),dimension(:,:),intent(in ) :: a
801complex(dpc),dimension(:,:),intent(inout) :: b
802integer(spi):: m,i, k, l
803complex(dpc):: s,aiii
804m=size(a,1)
805do k=1, size(b,2)!loop over columns of b
806 do i=1,m
807 l=ipiv(i)
808 s=b(l,k)
809 b(l,k)=b(i,k)
810 s = s - sum(b(1:i-1,k)*a(i,1:i-1))
811 b(i,k)=s
812 enddo
813 b(m,k)=b(m,k)/a(m,m)
814 do i=m-1,1,-1
815 aiii=c1/a(i,i)
816 b(i,k) = b(i,k) - sum(b(i+1:m,k)*a(i,i+1:m))
817 b(i,k)=b(i,k)*aiii
818 enddo
819enddo
820end subroutine cudlmm
821
830subroutine sudlmv(a,b,ipiv)! [udlmv]
831use pietc_s, only: u1
832integer(spi),dimension(:), intent(in ):: ipiv
833real(sp), dimension(:,:),intent(in ):: a
834real(sp), dimension(:), intent(inout):: b
835integer(spi):: m,i, l
836real(sp) :: s,aiii
837m=size(a,1)
838do i=1,m
839 l=ipiv(i)
840 s=b(l)
841 b(l)=b(i)
842 s = s - sum(b(1:i-1)*a(i,1:i-1))
843 b(i)=s
844enddo
845b(m)=b(m)/a(m,m)
846do i=m-1,1,-1
847 aiii=u1/a(i,i)
848 b(i) = b(i) - sum(b(i+1:m)*a(i,i+1:m))
849 b(i)=b(i)*aiii
850enddo
851end subroutine sudlmv
852
861subroutine dudlmv(a,b,ipiv)! [udlmv]
862use pietc, only: u1
863integer(spi),dimension(:), intent(in ) :: ipiv(:)
864real(dp), dimension(:,:),intent(in ) :: a(:,:)
865real(dp), dimension(:), intent(inout) :: b(:)
866integer(spi):: m,i, l
867real(dp) :: s,aiii
868m=size(a,1)
869do i=1,m
870 l=ipiv(i)
871 s=b(l)
872 b(l)=b(i)
873 s = s - sum(b(1:i-1)*a(i,1:i-1))
874 b(i)=s
875enddo
876b(m)=b(m)/a(m,m)
877do i=m-1,1,-1
878 aiii=u1/a(i,i)
879 b(i) = b(i) - sum(b(i+1:m)*a(i,i+1:m))
880 b(i)=b(i)*aiii
881enddo
882end subroutine dudlmv
883
892subroutine cudlmv(a,b,ipiv)! [udlmv]
893use pietc, only: c1
894integer(spi),dimension(:), intent(in ) :: ipiv(:)
895complex(dpc),dimension(:,:),intent(in ) :: a(:,:)
896complex(dpc),dimension(:), intent(inout) :: b(:)
897integer(spi):: m,i, l
898complex(dpc):: s,aiii
899m=size(a,1)
900do i=1,m
901 l=ipiv(i)
902 s=b(l)
903 b(l)=b(i)
904 s = s - sum(b(1:i-1)*a(i,1:i-1))
905 b(i)=s
906enddo
907b(m)=b(m)/a(m,m)
908do i=m-1,1,-1
909 aiii=c1/a(i,i)
910 b(i)= b(i) - sum(b(i+1:m)*a(i,i+1:m))
911 b(i)=b(i)*aiii
912enddo
913end subroutine cudlmv
914
920subroutine sl1lm(a,b) ! [l1lm]
921real(sp),intent(in ):: a(:,:)
922real(sp),intent(inout):: b(:,:)
923logical:: ff
924call sl1lmf(a,b,ff)
925if(ff)stop 'In sl1lm; matrix singular, unable to continue'
926end subroutine sl1lm
927
933subroutine dl1lm(a,b) ! [l1lm]
934real(dp),intent(in ):: a(:,:)
935real(dp),intent(inout):: b(:,:)
936logical:: ff
937call dl1lmf(a,b,ff)
938if(ff)stop 'In dl1lm; matrix singular, unable to continue'
939end subroutine dl1lm
940
947subroutine sl1lmf(a,b,ff)! [L1Lm]
948use pietc_s, only: u0
949real(sp),intent(in ):: a(:,:)
950real(sp),intent(inout):: b(:,:)
951logical, intent( out):: ff
952integer(spi):: m,j, jm, jp, i
953real(sp) :: s, bjji
954m=size(a,1)
955ff=f
956do j=1,m
957 jm=j-1
958 jp=j+1
959 s = a(j,j) - sum(b(j,1:jm)*b(j,1:jm))
960 ff=(s <= u0)
961 if(ff)then
962 print '("sL1Lmf detects nonpositive a, rank=",i6)',jm
963 return
964 endif
965 b(j,j)=sqrt(s)
966 bjji=1_sp/b(j,j)
967 do i=jp,m
968 s = a(i,j) - sum(b(i,1:jm)*b(j,1:jm))
969 b(i,j)=s*bjji
970 enddo
971 b(1:jm,j) = u0
972enddo
973end subroutine sl1lmf
974
981subroutine dl1lmf(a,b,ff) ! [L1Lm]
982use pietc, only: u0,u1
983real(dp),intent(in ) :: a(:,:)
984real(dp),intent(inout) :: b(:,:)
985logical, intent( out) :: ff
986integer(spi):: m,j, jm, jp, i
987real(dp) :: s, bjji
988m=size(a,1)
989ff=f
990do j=1,m
991 jm=j-1
992 jp=j+1
993 s = a(j,j) - sum(b(j,1:jm)*b(j,1:jm))
994 ff=(s <= u0)
995 if(ff)then
996 print '("dL1LMF detects nonpositive A, rank=",i6)',jm
997 return
998 endif
999 b(j,j)=sqrt(s)
1000 bjji=u1/b(j,j)
1001 do i=jp,m
1002 s = a(i,j) - sum(b(i,1:jm)*b(j,1:jm))
1003 b(i,j)=s*bjji
1004 enddo
1005 b(1:jm,j) = u0
1006enddo
1007end subroutine dl1lmf
1008
1015subroutine sldlm(a,b,d)! [LdLm]
1016real(sp),intent(in ):: a(:,:)
1017real(sp),intent(inout):: b(:,:)
1018real(sp),intent( out):: d(:)
1019logical:: ff
1020call sldlmf(a,b,d,ff)
1021if(ff)stop 'In sldlm; matrix singular, unable to continue'
1022end subroutine sldlm
1023
1030subroutine dldlm(a,b,d)! [LdLm]
1031real(dp),intent(in ):: a(:,:)
1032real(dp),intent(inout):: b(:,:)
1033real(dp),intent( out):: d(:)
1034logical:: ff
1035call dldlmf(a,b,d,ff)
1036if(ff)stop 'In dldlm; matrix singular, unable to continue'
1037end subroutine dldlm
1038
1046subroutine sldlmf(a,b,d,ff) ! [LDLM]
1047use pietc_s, only: u0,u1
1048real(sp), intent(in ):: a(:,:)
1049real(sp), intent(inout):: b(:,:)
1050real(sp), intent( out):: d(:)
1051logical, intent( out):: ff
1052integer(spi):: m,j, jm, jp, i
1053real(sp) :: bjji
1054m=size(a,1)
1055ff=f
1056do j=1,m
1057 jm=j-1
1058 jp=j+1
1059 d(j)=a(j,j) - sum(b(1:jm,j)*b(j,1:jm))
1060 b(j,j) = u1
1061 ff=(d(j) == u0)
1062 if(ff)then
1063 print '("In sldlmf; singularity of matrix detected")'
1064 print '("Rank of matrix: ",i6)',jm
1065 return
1066 endif
1067 bjji=u1/d(j)
1068 do i=jp,m
1069 b(j,i)=a(i,j) - dot_product(b(1:jm,j),b(i,1:jm))
1070 b(i,j)=b(j,i)*bjji
1071 enddo
1072 b(1:jm,j)=u0
1073enddo
1074end subroutine sldlmf
1075
1083subroutine dldlmf(a,b,d,ff) ! [LDLM]
1084use pietc, only: u0,u1
1085real(dp), intent(IN ) :: a(:,:)
1086real(dp), intent(INOUT) :: b(:,:)
1087real(dp), intent( OUT) :: d(:)
1088logical, intent( OUT) :: ff
1089integer(spi):: m,j, jm, jp, i
1090real(dp) :: bjji
1091m=size(a,1)
1092ff=f
1093do j=1,m; jm=j-1; jp=j+1
1094 d(j)=a(j,j) - sum(b(1:jm,j)*b(j,1:jm))
1095 b(j,j) = 1
1096 ff=(d(j) == u0)
1097 if(ff)then
1098 print '("In dldlmf; singularity of matrix detected")'
1099 print '("Rank of matrix: ",i6)',jm
1100 return
1101 endif
1102 bjji=u1/d(j)
1103 do i=jp,m
1104 b(j,i)=a(i,j) - dot_product(b(1:jm,j),b(i,1:jm))
1105 b(i,j)=b(j,i)*bjji
1106 enddo
1107 b(1:jm,j)=u0
1108enddo
1109end subroutine dldlmf
1110
1116subroutine sinvu(a)! [invu]
1117real(sp),dimension(:,:),intent(inout):: a
1118a=transpose(a); call sinvl(a); a=transpose(a)
1119end subroutine sinvu
1120
1126subroutine dinvu(a)! [invu]
1127real(dp),dimension(:,:),intent(inout):: a
1128a=transpose(a); call dinvl(a); a=transpose(a)
1129end subroutine dinvu
1130
1135subroutine sinvl(a)! [invl]
1136use pietc_s, only: u0,u1
1137real(sp), intent(inout) :: a(:,:)
1138integer(spi):: m,j, i
1139m=size(a,1)
1140do j=m,1,-1
1141 a(1:j-1,j) = u0
1142 a(j,j)=u1/a(j,j)
1143 do i=j+1,m
1144 a(i,j)=-a(i,i)*sum(a(j:i-1,j)*a(i,j:i-1))
1145 enddo
1146enddo
1147end subroutine sinvl
1148
1153subroutine dinvl(a)! [invl]
1154use pietc, only: u0,u1
1155real(dp), intent(inout) :: a(:,:)
1156integer(spi):: m,j, i
1157m=size(a,1)
1158do j=m,1,-1
1159 a(1:j-1,j) = u0
1160 a(j,j)=u1/a(j,j)
1161 do i=j+1,m
1162 a(i,j)=-a(i,i)*sum(a(j:i-1,j)*a(i,j:i-1))
1163 enddo
1164enddo
1165end subroutine dinvl
1166
1173subroutine slinlv(a,u)! [invl]
1174real(sp),intent(in ) :: a(:,:)
1175real(sp),intent(inout) :: u(:)
1176integer(spi):: i
1177if(size(a,1) /= size(a,2) .or. size(a,1) /= size(u))&
1178 stop 'In slinlv; incompatible array dimensions'
1179do i=1,size(u); u(i)=(u(i) - sum(u(:i-1)*a(i,:i-1)))/a(i,i); enddo
1180end subroutine slinlv
1181
1188subroutine dlinlv(a,u)! [invl]
1189real(dp),intent(in ) :: a(:,:)
1190real(dp),intent(inout) :: u(:)
1191integer(spi):: i
1192if(size(a,1) /= size(a,2) .or. size(a,1) /= size(u))&
1193 stop 'In dlinlv; incompatible array dimensions'
1194do i=1,size(u); u(i)=(u(i) - sum(u(:i-1)*a(i,:i-1)))/a(i,i); enddo
1195end subroutine dlinlv
1196
1203subroutine slinuv(a,u)! [invu]
1204real(sp),intent(in ) :: a(:,:)
1205real(sp),intent(inout) :: u(:)
1206integer(spi):: i
1207if(size(a,1) /= size(a,2) .or. size(a,1) /= size(u))&
1208 stop 'In linuv; incompatible array dimensions'
1209do i=size(u),1,-1; u(i)=(u(i) - sum(a(i+1:,i)*u(i+1:)))/a(i,i); enddo
1210end subroutine slinuv
1211
1218subroutine dlinuv(a,u)! [invu]
1219real(dp), intent(in ) :: a(:,:)
1220real(dp), intent(inout) :: u(:)
1221integer(spi) :: i
1222if(size(a,1) /= size(a,2) .or. size(a,1) /= size(u))&
1223 stop 'In dlinuv; incompatible array dimensions'
1224do i=size(u),1,-1; u(i)=(u(i) - sum(a(i+1:,i)*u(i+1:)))/a(i,i); enddo
1225end subroutine dlinuv
1226
1227end module pmat
1228
Some of the commonly used constants (pi etc) mainly for double-precision subroutines.
Definition pietc.f90:14
logical, parameter f
for pain-relief in logical ops
Definition pietc.f90:18
real(dp), parameter u1
one
Definition pietc.f90:20
complex(dpc), parameter c0
complex zero
Definition pietc.f90:112
complex(dpc), parameter c1
complex one
Definition pietc.f90:113
logical, parameter t
for pain-relief in logical ops
Definition pietc.f90:17
real(dp), parameter u0
zero
Definition pietc.f90:19
Standard integer, real, and complex single and double precision kinds.
Definition pkind.f90:7
integer, parameter dp
Double precision real kind.
Definition pkind.f90:11
integer, parameter dpc
Double precision real kind.
Definition pkind.f90:13
integer, parameter spc
Single precision real kind.
Definition pkind.f90:12
integer, parameter sp
Single precision real kind.
Definition pkind.f90:10
integer, parameter spi
Single precision integer kind.
Definition pkind.f90:8