grid_tools  1.13.0
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
20 module pmat
21 use pkind, only: spi,sp,dp,spc,dpc
22 use pietc, only: t,f
23 implicit none
24 private
25 public:: ldum,udlmm,inv,l1lm,ldlm,invl,invu
26 interface swpvv; module procedure sswpvv,dswpvv,cswpvv; end interface
27 interface ldum
28  module procedure sldum,dldum,cldum,sldumf,dldumf,cldumf; end interface
29 interface udlmm
30  module procedure sudlmm,dudlmm,cudlmm,sudlmv,dudlmv,cudlmv; end interface
31 interface inv
32  module procedure &
33 sinvmt, dinvmt, cinvmt, slinmmt, dlinmmt, clinmmt, slinmvt, dlinmvt, clinmvt, &
34 sinvmtf,dinvmtf,cinvmtf,slinmmtf,dlinmmtf,clinmmtf,slinmvtf,dlinmvtf,clinmvtf,&
35 iinvf
36  end interface
37 interface l1lm; module procedure sl1lm,dl1lm,sl1lmf,dl1lmf; end interface
38 interface ldlm; module procedure sldlm,dldlm,sldlmf,dldlmf; end interface
39 interface invl; module procedure sinvl,dinvl,slinlv,dlinlv; end interface
40 interface invu; module procedure sinvu,dinvu,slinuv,dlinuv; end interface
41 
42 contains
43 
49 subroutine sswpvv(d,e)! [swpvv]
50 real(sp), intent(inout) :: d(:), e(:)
51 real(sp) :: tv(size(d))
52 tv = d; d = e; e = tv
53 end subroutine sswpvv
54 
60 subroutine dswpvv(d,e)! [swpvv]
61 real(dp), intent(inout) :: d(:), e(:)
62 real(dp) :: tv(size(d))
63 tv = d; d = e; e = tv
64 end subroutine dswpvv
65 
71 subroutine cswpvv(d,e)! [swpvv]
72 complex(dpc),intent(inout) :: d(:), e(:)
73 complex(dpc) :: tv(size(d))
74 tv = d; d = e; e = tv
75 end subroutine cswpvv
76 
81 subroutine sinvmt(a)! [inv]
82 real(sp),dimension(:,:),intent(INOUT):: a
83 logical :: ff
84 call sinvmtf(a,ff)
85 if(ff)stop 'In sinvmt; Unable to invert matrix'
86 end subroutine sinvmt
87 
92 subroutine dinvmt(a)! [inv]
93 real(dp),dimension(:,:),intent(inout):: a
94 logical :: ff
95 call dinvmtf(a,ff)
96 if(ff)stop 'In dinvmt; Unable to invert matrix'
97 end subroutine dinvmt
98 
103 subroutine cinvmt(a)! [inv]
104 complex(dpc),dimension(:,:),intent(inout):: a
105 logical :: ff
106 call cinvmtf(a,ff)
107 if(ff)stop 'In cinvmt; Unable to invert matrix'
108 end subroutine cinvmt
109 
115 subroutine sinvmtf(a,ff)! [inv]
116 use pietc_s, only: u1
117 real(sp),dimension(:,:),intent(inout):: a
118 logical, intent( out):: ff
119 integer(spi) :: m,i,j,jp,l
120 real(sp) :: d
121 integer(spi),dimension(size(a,1)):: ipiv
122 m=size(a,1)
123 if(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:
125 call sldumf(a,ipiv,d,ff)
126 if(ff)then
127  print '(" In sinvmtf; failed call to sldumf")'
128  return
129 endif
130 ! Invert upper triangular portion U in place:
131 do i=1,m; a(i,i)=u1/a(i,i); enddo
132 do 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
134 enddo
135 ! Invert lower triangular portion L in place:
136 do 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
138 enddo
139 ! Form the product of U**-1 and L**-1 in place
140 do 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
143 enddo
144 ! Permute columns according to ipiv
145 do j=m-1,1,-1; l=ipiv(j); call sswpvv(a(:,j),a(:,l)); enddo
146 end subroutine sinvmtf
147 
153 subroutine dinvmtf(a,ff)! [inv]
154 real(dp),dimension(:,:),intent(inout):: a
155 logical, intent( out):: ff
156 integer(spi) :: m,i,j,jp,l
157 real(dp) :: d
158 integer(spi), dimension(size(a,1)) :: ipiv
159 m=size(a,1)
160 if(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:
162 call dldumf(a,ipiv,d,ff)
163 if(ff)then
164  print '(" In dinvmtf; failed call to dldumf")'
165  return
166 endif
167 ! Invert upper triangular portion U in place:
168 do i=1,m; a(i,i)=1_dp/a(i,i); enddo
169 do 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
171 enddo
172 ! Invert lower triangular portion L in place:
173 do 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
175 enddo
176 ! Form the product of U**-1 and L**-1 in place
177 do 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
180 enddo
181 ! Permute columns according to ipiv
182 do j=m-1,1,-1; l=ipiv(j); call dswpvv(a(:,j),a(:,l)); enddo
183 end subroutine dinvmtf
184 
190 subroutine cinvmtf(a,ff)! [inv]
191 use pietc, only: c1
192 complex(dpc),dimension(:,:),intent(INOUT):: a
193 logical, intent( OUT):: ff
194 integer(spi) :: m,i,j,jp,l
195 complex(dpc) :: d
196 integer(spi),dimension(size(a,1)):: ipiv
197 m=size(a,1)
198 if(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:
200 call cldumf(a,ipiv,d,ff)
201 if(ff)then
202  print '(" In cinvmtf; failed call to cldumf")'
203  return
204 endif
205 ! Invert upper triangular portion U in place:
206 do i=1,m; a(i,i)=c1/a(i,i); enddo
207 do 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
209 enddo
210 ! Invert lower triangular portion L in place:
211 do 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
213 enddo
214 ! Form the product of U**-1 and L**-1 in place
215 do 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
218 enddo
219 ! Permute columns according to ipiv
220 do j=m-1,1,-1; l=ipiv(j); call cswpvv(a(:,j),a(:,l)); enddo
221 end subroutine cinvmtf
222 
229 subroutine slinmmt(a,b)! [inv]
230 real(sp),dimension(:,:),intent(inout):: a,b
231 logical :: ff
232 call slinmmtf(a,b,ff)
233 if(ff)stop 'In slinmmt; unable to invert linear system'
234 end subroutine slinmmt
235 
242 subroutine dlinmmt(a,b)! [inv]
243 real(dp),dimension(:,:),intent(inout):: a,b
244 logical :: ff
245 call dlinmmtf(a,b,ff)
246 if(ff)stop 'In dlinmmt; unable to invert linear system'
247 end subroutine dlinmmt
248 
255 subroutine clinmmt(a,b)! [inv]
256 complex(dpc),dimension(:,:),intent(inout):: a,b
257 logical :: ff
258 call clinmmtf(a,b,ff)
259 if(ff)stop 'In clinmmt; unable to invert linear system'
260 end subroutine clinmmt
261 
269 subroutine slinmmtf(a,b,ff)! [inv]
270 real(sp), dimension(:,:),intent(inout):: a,b
271 logical, intent( out):: ff
272 integer(spi),dimension(size(a,1)) :: ipiv
273 integer(spi) :: m
274 real(sp) :: d
275 m=size(a,1)
276 if(m /= size(a,2))stop 'In inv; matrix passed to slinmmtf is not square'
277 if(m /= size(b,1))&
278  stop 'In inv; matrix and vectors in slinmmtf have unmatched sizes'
279 call sldumf(a,ipiv,d,ff)
280 if(ff)then
281  print '("In slinmmtf; failed call to sldumf")'
282  return
283 endif
284 call sudlmm(a,b,ipiv)
285 end subroutine slinmmtf
286 
294 subroutine dlinmmtf(a,b,ff)! [inv]
295 real(dp),dimension(:,:), intent(inout):: a,b
296 logical, intent( out):: ff
297 integer(spi),dimension(size(a,1)):: ipiv
298 integer(spi):: m
299 real(dp) :: d
300 m=size(a,1)
301 if(m /= size(a,2))stop 'In inv; matrix passed to dlinmmtf is not square'
302 if(m /= size(b,1))&
303  stop 'In inv; matrix and vectors in dlinmmtf have unmatched sizes'
304 call dldumf(a,ipiv,d,ff)
305 if(ff)then
306  print '("In dlinmmtf; failed call to dldumf")'
307  return
308 endif
309 call dudlmm(a,b,ipiv)
310 end subroutine dlinmmtf
311 
319 subroutine clinmmtf(a,b,ff)! [inv]
320 complex(dpc),dimension(:,:),intent(INOUT):: a,b
321 logical, intent( OUT):: ff
322 integer(spi),dimension(size(a,1)):: ipiv
323 integer(spi) :: m
324 complex(dpc) :: d
325 m=size(a,1)
326 if(m /= size(a,2))stop 'In inv; matrix passed to dlinmmtf is not square'
327 if(m /= size(b,1))&
328  stop 'In inv; matrix and vectors in dlinmmtf have unmatched sizes'
329 call cldumf(a,ipiv,d,ff)
330 if(ff)then
331  print '("In clinmmtf; failed call to cldumf")'
332  return
333 endif
334 call cudlmm(a,b,ipiv)
335 end subroutine clinmmtf
336 
343 subroutine slinmvt(a,b)! [inv]
344 real(sp),dimension(:,:),intent(inout):: a
345 real(sp),dimension(:), intent(inout):: b
346 logical:: ff
347 call slinmvtf(a,b,ff)
348 if(ff)stop 'In slinmvt; matrix singular, unable to continue'
349 end subroutine slinmvt
350 
357 subroutine dlinmvt(a,b)! [inv]
358 real(dp),dimension(:,:),intent(inout):: a
359 real(dp),dimension(:), intent(inout):: b
360 logical :: ff
361 call dlinmvtf(a,b,ff)
362 if(ff)stop 'In dlinmvt; matrix singular, unable to continue'
363 end subroutine dlinmvt
364 
371 subroutine clinmvt(a,b)! [inv]
372 complex(dpc), dimension(:,:),intent(inout):: a
373 complex(dpc), dimension(:), intent(inout):: b
374 logical :: ff
375 call clinmvtf(a,b,ff)
376 if(ff)stop 'In clinmvt; matrix singular, unable to continue'
377 end subroutine clinmvt
378 
385 subroutine slinmvtf(a,b,ff)! [inv]
386 real(sp),dimension(:,:),intent(inout):: a
387 real(sp),dimension(:), intent(inout):: b
388 logical, intent( out):: ff
389 integer(spi),dimension(size(a,1)) :: ipiv
390 real(sp) :: d
391 if(size(a,1) /= size(a,2).or. size(a,1) /= size(b))&
392  stop 'In inv; In slinmvtf; incompatible array dimensions'
393 call sldumf(a,ipiv,d,ff)
394 if(ff)then
395  print '("In slinmvtf; failed call to sldumf")'
396  return
397 endif
398 call sudlmv(a,b,ipiv)
399 end subroutine slinmvtf
400 
407 subroutine dlinmvtf(a,b,ff)! [inv]
408 real(dp),dimension(:,:),intent(inout):: a
409 real(dp),dimension(:), intent(inout):: b
410 logical, intent( out):: ff
411 integer(spi), dimension(size(a,1)) :: ipiv
412 real(dp) :: d
413 if(size(a,1) /= size(a,2).or. size(a,1) /= size(b))&
414  stop 'In inv; incompatible array dimensions passed to dlinmvtf'
415 call dldumf(a,ipiv,d,ff)
416 if(ff)then
417  print '("In dlinmvtf; failed call to dldumf")'
418  return
419 endif
420 call dudlmv(a,b,ipiv)
421 end subroutine dlinmvtf
422 
429 subroutine clinmvtf(a,b,ff)! [inv]
430 complex(dpc),dimension(:,:),intent(inout):: a
431 complex(dpc),dimension(:), intent(inout):: b
432 logical, intent( out):: ff
433 integer, dimension(size(a,1)) :: ipiv
434 complex(dpc) :: d
435 if(size(a,1) /= size(a,2).or. size(a,1) /= size(b))&
436  stop 'In inv; incompatible array dimensions passed to clinmvtf'
437 call cldumf(a,ipiv,d,ff)
438 if(ff)then
439  print '("In clinmvtf; failed call to cldumf")'
440  return
441 endif
442 call cudlmv(a,b,ipiv)
443 end subroutine clinmvtf
444 
451 subroutine iinvf(imat,ff)! [inv]
452 integer(spi),dimension(:,:),intent(INOUT):: imat
453 logical, intent( OUT):: ff
454 real(dp),parameter :: eps=1.e-6_dp
455 real(dp),dimension(size(imat,1),size(imat,1)):: dmat
456 integer(spi) :: m,i,j
457 m=size(imat,1)
458 if(m /= size(imat,2))stop 'In inv; matrix passed to iinvf is not square'
459 dmat=imat; call inv(dmat,ff)
460 if(.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
466 endif
467 end subroutine iinvf
468 
476 subroutine sldum(a,ipiv,d)! [ldum]
477 real(sp), intent(inout) :: a(:,:)
478 real(sp), intent( out) :: d
479 integer(spi),intent( out) :: ipiv(:)
480 logical:: ff
481 call sldumf(a,ipiv,d,ff)
482 if(ff)stop 'In sldum; matrix singular, unable to continue'
483 end subroutine sldum
484 
492 subroutine dldum(a,ipiv,d)! [ldum]
493 real(dp), intent(inout) :: a(:,:)
494 real(dp), intent( out) :: d
495 integer(spi),intent( out) :: ipiv(:)
496 logical:: ff
497 call dldumf(a,ipiv,d,ff)
498 if(ff)stop 'In dldum; matrix singular, unable to continue'
499 end subroutine dldum
500 
508 subroutine cldum(a,ipiv,d)! [ldum]
509 complex(dpc),intent(inout) :: a(:,:)
510 complex(dpc),intent(out ) :: d
511 integer(spi),intent(out ) :: ipiv(:)
512 logical:: ff
513 call cldumf(a,ipiv,d,ff)
514 if(ff)stop 'In cldum; matrix singular, unable to continue'
515 end subroutine cldum
516 
525 subroutine sldumf(a,ipiv,d,ff)! [ldum]
526 use pietc_s,only: u0,u1
527 real(sp), intent(inout) :: a(:,:)
528 real(sp), intent( out) :: d
529 integer(spi),intent( out) :: ipiv(:)
530 logical, intent( out) :: ff
531 integer(spi):: m,i, j, jp, ibig, jm
532 real(sp) :: s(size(a,1)), aam, aa, abig, ajj, ajji, aij
533 ff=f
534 m=size(a,1)
535 do 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
547 enddo
548 d=1_sp
549 ipiv(m)=m
550 do 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
581 enddo
582 end subroutine sldumf
583 
592 subroutine dldumf(a,ipiv,d,ff)! [ldum]
593 use pietc, only: u0,u1
594 real(dp), intent(inout) :: a(:,:)
595 real(dp), intent( out) :: d
596 integer, intent( out) :: ipiv(:)
597 logical(spi),intent( out) :: ff
598 integer(spi) :: m,i, j, jp, ibig, jm
599 real(dp) :: s(size(a,1)), aam, aa, abig, ajj, ajji, aij
600 ff=f
601 m=size(a,1)
602 do 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
614 enddo
615 d=u1
616 ipiv(m)=m
617 do 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
648 enddo
649 end subroutine dldumf
650 
659 subroutine cldumf(a,ipiv,d,ff)! [ldum]
660 use pietc, only: u0,u1,c0,c1
661 complex(dpc), intent(inout) :: a(:,:)
662 complex(dpc), intent( out) :: d
663 integer(spi), intent( out) :: ipiv(:)
664 logical, intent( out) :: ff
665 integer(spi) :: m,i, j, jp, ibig, jm
666 complex(dpc) :: ajj, ajji, aij
667 real(dp) :: aam,aa,abig
668 real(dp),dimension(size(a,1)):: s
669 ff=f
670 m=size(a,1)
671 do 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
683 enddo
684 d=c1
685 ipiv(m)=m
686 do 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
717 enddo
718 end subroutine cldumf
719 
729 subroutine sudlmm(a,b,ipiv)! [udlmm]
730 use pietc_s, only: u1
731 integer(spi),dimension(:), intent(in) :: ipiv
732 real(sp), dimension(:,:),intent(in) :: a
733 real(sp), dimension(:,:),intent(inout) :: b
734 integer(spi):: m,i, k, l
735 real(sp) :: s,aiii
736 m=size(a,1)
737 do 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
751 enddo
752 end subroutine sudlmm
753 
763 subroutine dudlmm(a,b,ipiv)! [udlmm]
764 use pietc, only: u1
765 integer(spi),dimension(:), intent(in ) :: ipiv
766 real(dp), dimension(:,:),intent(in ) :: a
767 real(dp), dimension(:,:),intent(inout) :: b
768 integer(spi):: m,i, k, l
769 real(dp) :: s,aiii
770 m=size(a,1)
771 do 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
785 enddo
786 end subroutine dudlmm
787 
797 subroutine cudlmm(a,b,ipiv)! [udlmm]
798 use pietc, only: c1
799 integer(spi),dimension(:), intent(in ) :: ipiv
800 complex(dpc),dimension(:,:),intent(in ) :: a
801 complex(dpc),dimension(:,:),intent(inout) :: b
802 integer(spi):: m,i, k, l
803 complex(dpc):: s,aiii
804 m=size(a,1)
805 do 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
819 enddo
820 end subroutine cudlmm
821 
830 subroutine sudlmv(a,b,ipiv)! [udlmv]
831 use pietc_s, only: u1
832 integer(spi),dimension(:), intent(in ):: ipiv
833 real(sp), dimension(:,:),intent(in ):: a
834 real(sp), dimension(:), intent(inout):: b
835 integer(spi):: m,i, l
836 real(sp) :: s,aiii
837 m=size(a,1)
838 do 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
844 enddo
845 b(m)=b(m)/a(m,m)
846 do 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
850 enddo
851 end subroutine sudlmv
852 
861 subroutine dudlmv(a,b,ipiv)! [udlmv]
862 use pietc, only: u1
863 integer(spi),dimension(:), intent(in ) :: ipiv(:)
864 real(dp), dimension(:,:),intent(in ) :: a(:,:)
865 real(dp), dimension(:), intent(inout) :: b(:)
866 integer(spi):: m,i, l
867 real(dp) :: s,aiii
868 m=size(a,1)
869 do 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
875 enddo
876 b(m)=b(m)/a(m,m)
877 do 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
881 enddo
882 end subroutine dudlmv
883 
892 subroutine cudlmv(a,b,ipiv)! [udlmv]
893 use pietc, only: c1
894 integer(spi),dimension(:), intent(in ) :: ipiv(:)
895 complex(dpc),dimension(:,:),intent(in ) :: a(:,:)
896 complex(dpc),dimension(:), intent(inout) :: b(:)
897 integer(spi):: m,i, l
898 complex(dpc):: s,aiii
899 m=size(a,1)
900 do 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
906 enddo
907 b(m)=b(m)/a(m,m)
908 do 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
912 enddo
913 end subroutine cudlmv
914 
920 subroutine sl1lm(a,b) ! [l1lm]
921 real(sp),intent(in ):: a(:,:)
922 real(sp),intent(inout):: b(:,:)
923 logical:: ff
924 call sl1lmf(a,b,ff)
925 if(ff)stop 'In sl1lm; matrix singular, unable to continue'
926 end subroutine sl1lm
927 
933 subroutine dl1lm(a,b) ! [l1lm]
934 real(dp),intent(in ):: a(:,:)
935 real(dp),intent(inout):: b(:,:)
936 logical:: ff
937 call dl1lmf(a,b,ff)
938 if(ff)stop 'In dl1lm; matrix singular, unable to continue'
939 end subroutine dl1lm
940 
947 subroutine sl1lmf(a,b,ff)! [L1Lm]
948 use pietc_s, only: u0
949 real(sp),intent(in ):: a(:,:)
950 real(sp),intent(inout):: b(:,:)
951 logical, intent( out):: ff
952 integer(spi):: m,j, jm, jp, i
953 real(sp) :: s, bjji
954 m=size(a,1)
955 ff=f
956 do 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
972 enddo
973 end subroutine sl1lmf
974 
981 subroutine dl1lmf(a,b,ff) ! [L1Lm]
982 use pietc, only: u0,u1
983 real(dp),intent(in ) :: a(:,:)
984 real(dp),intent(inout) :: b(:,:)
985 logical, intent( out) :: ff
986 integer(spi):: m,j, jm, jp, i
987 real(dp) :: s, bjji
988 m=size(a,1)
989 ff=f
990 do 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
1006 enddo
1007 end subroutine dl1lmf
1008 
1015 subroutine sldlm(a,b,d)! [LdLm]
1016 real(sp),intent(in ):: a(:,:)
1017 real(sp),intent(inout):: b(:,:)
1018 real(sp),intent( out):: d(:)
1019 logical:: ff
1020 call sldlmf(a,b,d,ff)
1021 if(ff)stop 'In sldlm; matrix singular, unable to continue'
1022 end subroutine sldlm
1023 
1030 subroutine dldlm(a,b,d)! [LdLm]
1031 real(dp),intent(in ):: a(:,:)
1032 real(dp),intent(inout):: b(:,:)
1033 real(dp),intent( out):: d(:)
1034 logical:: ff
1035 call dldlmf(a,b,d,ff)
1036 if(ff)stop 'In dldlm; matrix singular, unable to continue'
1037 end subroutine dldlm
1038 
1046 subroutine sldlmf(a,b,d,ff) ! [LDLM]
1047 use pietc_s, only: u0,u1
1048 real(sp), intent(in ):: a(:,:)
1049 real(sp), intent(inout):: b(:,:)
1050 real(sp), intent( out):: d(:)
1051 logical, intent( out):: ff
1052 integer(spi):: m,j, jm, jp, i
1053 real(sp) :: bjji
1054 m=size(a,1)
1055 ff=f
1056 do 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
1073 enddo
1074 end subroutine sldlmf
1075 
1083 subroutine dldlmf(a,b,d,ff) ! [LDLM]
1084 use pietc, only: u0,u1
1085 real(dp), intent(IN ) :: a(:,:)
1086 real(dp), intent(INOUT) :: b(:,:)
1087 real(dp), intent( OUT) :: d(:)
1088 logical, intent( OUT) :: ff
1089 integer(spi):: m,j, jm, jp, i
1090 real(dp) :: bjji
1091 m=size(a,1)
1092 ff=f
1093 do 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
1108 enddo
1109 end subroutine dldlmf
1110 
1116 subroutine sinvu(a)! [invu]
1117 real(sp),dimension(:,:),intent(inout):: a
1118 a=transpose(a); call sinvl(a); a=transpose(a)
1119 end subroutine sinvu
1120 
1126 subroutine dinvu(a)! [invu]
1127 real(dp),dimension(:,:),intent(inout):: a
1128 a=transpose(a); call dinvl(a); a=transpose(a)
1129 end subroutine dinvu
1130 
1135 subroutine sinvl(a)! [invl]
1136 use pietc_s, only: u0,u1
1137 real(sp), intent(inout) :: a(:,:)
1138 integer(spi):: m,j, i
1139 m=size(a,1)
1140 do 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
1146 enddo
1147 end subroutine sinvl
1148 
1153 subroutine dinvl(a)! [invl]
1154 use pietc, only: u0,u1
1155 real(dp), intent(inout) :: a(:,:)
1156 integer(spi):: m,j, i
1157 m=size(a,1)
1158 do 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
1164 enddo
1165 end subroutine dinvl
1166 
1173 subroutine slinlv(a,u)! [invl]
1174 real(sp),intent(in ) :: a(:,:)
1175 real(sp),intent(inout) :: u(:)
1176 integer(spi):: i
1177 if(size(a,1) /= size(a,2) .or. size(a,1) /= size(u))&
1178  stop 'In slinlv; incompatible array dimensions'
1179 do i=1,size(u); u(i)=(u(i) - sum(u(:i-1)*a(i,:i-1)))/a(i,i); enddo
1180 end subroutine slinlv
1181 
1188 subroutine dlinlv(a,u)! [invl]
1189 real(dp),intent(in ) :: a(:,:)
1190 real(dp),intent(inout) :: u(:)
1191 integer(spi):: i
1192 if(size(a,1) /= size(a,2) .or. size(a,1) /= size(u))&
1193  stop 'In dlinlv; incompatible array dimensions'
1194 do i=1,size(u); u(i)=(u(i) - sum(u(:i-1)*a(i,:i-1)))/a(i,i); enddo
1195 end subroutine dlinlv
1196 
1203 subroutine slinuv(a,u)! [invu]
1204 real(sp),intent(in ) :: a(:,:)
1205 real(sp),intent(inout) :: u(:)
1206 integer(spi):: i
1207 if(size(a,1) /= size(a,2) .or. size(a,1) /= size(u))&
1208  stop 'In linuv; incompatible array dimensions'
1209 do i=size(u),1,-1; u(i)=(u(i) - sum(a(i+1:,i)*u(i+1:)))/a(i,i); enddo
1210 end subroutine slinuv
1211 
1218 subroutine dlinuv(a,u)! [invu]
1219 real(dp), intent(in ) :: a(:,:)
1220 real(dp), intent(inout) :: u(:)
1221 integer(spi) :: i
1222 if(size(a,1) /= size(a,2) .or. size(a,1) /= size(u))&
1223  stop 'In dlinuv; incompatible array dimensions'
1224 do i=size(u),1,-1; u(i)=(u(i) - sum(a(i+1:,i)*u(i+1:)))/a(i,i); enddo
1225 end subroutine dlinuv
1226 
1227 end module pmat
1228 
integer, parameter sp
Single precision real kind.
Definition: pkind.f90:10
integer, parameter dp
Double precision real kind.
Definition: pkind.f90:11
Standard integer, real, and complex single and double precision kinds.
Definition: pkind.f90:7
logical, parameter f
for pain-relief in logical ops
Definition: pietc.f90:18
real(dp), parameter u0
zero
Definition: pietc.f90:19
complex(dpc), parameter c1
complex one
Definition: pietc.f90:113
complex(dpc), parameter c0
complex zero
Definition: pietc.f90:112
logical, parameter t
for pain-relief in logical ops
Definition: pietc.f90:17
real(dp), parameter u1
one
Definition: pietc.f90:20
Some of the commonly used constants (pi etc) mainly for double-precision subroutines.
Definition: pietc.f90:14
integer, parameter spc
Single precision real kind.
Definition: pkind.f90:12
integer, parameter spi
Single precision integer kind.
Definition: pkind.f90:8
integer, parameter dpc
Double precision real kind.
Definition: pkind.f90:13