1000 lines
24 KiB
FortranFixed
1000 lines
24 KiB
FortranFixed
subroutine inv_det_matix(a,n,np,a_inv,
|
|
& lnabsdet,signunit,ierr)
|
|
implicit none
|
|
!
|
|
! Invert a matrix and calculate ln(dabs(determinant)) and the assoaciated
|
|
! sign
|
|
!
|
|
!-------------Inputs-------------------------------
|
|
!a: matrix to be inverted
|
|
!n: the actual dimension of a
|
|
!np: the declared dimension of a
|
|
!
|
|
!-------------Outputs------------------------------
|
|
!a_inv: inverse matrix of a
|
|
!lnabsdet: the ln(|det|a||)
|
|
!signunit: det|a| = signunit*exp(lnabsdet)
|
|
!ierr: =0, ok; =1, matrix a is singular
|
|
|
|
|
|
integer n,np,indx(np),i,j,ierr,numneg
|
|
double precision a(np,np),a_inv(np,np),
|
|
& copya(np,np),d,signunit,lnabsdet
|
|
|
|
ierr=0
|
|
do i=1,n
|
|
do j=1,n
|
|
copya(i,j)=a(i,j)
|
|
a_inv(i,j)=0.0d0
|
|
enddo
|
|
a_inv(i,i)=1.0d0
|
|
enddo
|
|
call ludcmp(copya,n,np,indx,d,ierr)
|
|
numneg=0
|
|
lnabsdet=0.0d0
|
|
do j=1,n
|
|
if(copya(j,j).eq.0.0d0)then
|
|
! singular matrix and the determinant is zero
|
|
ierr=1
|
|
signunit=-1.0d+100
|
|
lnabsdet=-1.0d+100
|
|
return
|
|
endif
|
|
if(copya(j,j).lt.0.0d0)then
|
|
numneg=numneg+1
|
|
endif
|
|
lnabsdet=lnabsdet+dlog(dabs(copya(j,j)))
|
|
enddo
|
|
if(d.lt.0.0d0)then
|
|
numneg=numneg+1
|
|
endif
|
|
if(mod(numneg,2).eq.0)then
|
|
signunit=1.0d0
|
|
else
|
|
signunit=-1.0d0
|
|
endif
|
|
do j=1,n
|
|
call lubksb(copya,n,np,indx,a_inv(1,j))
|
|
enddo
|
|
return
|
|
end
|
|
|
|
subroutine svd_inv_det_matix(a,n,np,a_inv,
|
|
& lnabsdet,signunit,ierr)
|
|
implicit none
|
|
!
|
|
! Invert a matrix and calculate ln(dabs(determinant)) and the assoaciated
|
|
! sign
|
|
!
|
|
!-------------Inputs-------------------------------
|
|
!a: matrix to be inverted
|
|
!n: the actual dimension of a
|
|
!np: the declared dimension of a
|
|
!
|
|
!-------------Outputs------------------------------
|
|
!a_inv: inverse matrix of a
|
|
!lnabsdet: the ln(|det|a||)
|
|
!signunit: det|a| = signunit*exp(lnabsdet)
|
|
!ierr: =0, ok; =1, matrix a is singular
|
|
|
|
integer n,np,indx(np),i,j,ierr
|
|
double precision a(np,np),a_inv(np,np),
|
|
& copya(np,np),w(np),v(np,np),
|
|
& d,signunit,signunitu,signunitv,
|
|
& lnabsdet,lnabsdetu,lnabsdetv,copyatrans(np,np),
|
|
& vinw(np,np)
|
|
|
|
ierr=0
|
|
do i=1,n
|
|
do j=1,n
|
|
copya(i,j)=a(i,j)
|
|
enddo
|
|
enddo
|
|
call svdcmp(copya(1:n,1:n),n,n,np,np,w,v(1:n,1:n),ierr)
|
|
do i=1,n
|
|
do j=1,n
|
|
vinw(i,j)=v(i,j)/w(j)
|
|
enddo
|
|
enddo
|
|
|
|
call matrixtranspose(n,n,copya(1:n,1:n),
|
|
& copyatrans(1:n,1:n))
|
|
call matrixproduct(n,n,vinw(1:n,1:n),n,
|
|
& copyatrans(1:n,1:n),a_inv(1:n,1:n))
|
|
|
|
call det_matix(copya(1:n,1:n),n,n,lnabsdetu,signunitu,ierr)
|
|
call det_matix(v(1:n,1:n),n,n,lnabsdetv,signunitv,ierr)
|
|
|
|
lnabsdet=0.0d0
|
|
do j=1,n
|
|
lnabsdet=lnabsdet+dlog(w(j))
|
|
enddo
|
|
|
|
signunit=signunitu*signunitv
|
|
|
|
return
|
|
end
|
|
|
|
|
|
subroutine det_matix(a,n,np,lnabsdet,signunit,ierr)
|
|
implicit none
|
|
!
|
|
! calculate ln(dabs(determinant)) and the assoaciated sign
|
|
!
|
|
!-------------Inputs-------------------------------
|
|
!a: matrix to be inverted
|
|
!n: the actual dimension of a
|
|
!np: the declared dimension of a
|
|
!
|
|
!-------------Outputs------------------------------
|
|
!lnabsdet: the ln(|det|a||)
|
|
!signunit: det|a| = signunit*exp(lnabsdet)
|
|
!ierr: =1, ok; =0, matrix a is singular
|
|
|
|
|
|
integer n,np,indx(np),i,j,ierr,numneg
|
|
double precision a(np,np),a_inv(np,np),
|
|
& copya(np,np),d,signunit,lnabsdet
|
|
|
|
ierr=1
|
|
do i=1,n
|
|
do j=1,n
|
|
copya(i,j)=a(i,j)
|
|
enddo
|
|
enddo
|
|
|
|
call ludcmp(copya(1:n,1:n),n,np,indx,d,ierr)
|
|
numneg=0
|
|
lnabsdet=0.0d0
|
|
do j=1,n
|
|
if(copya(j,j).eq.0.0d0)then
|
|
! singular matrix and the determinant is zero
|
|
ierr=1
|
|
signunit=-1.0d+100
|
|
lnabsdet=-1.0d+100
|
|
return
|
|
endif
|
|
if(copya(j,j).lt.0.0d0)then
|
|
numneg=numneg+1
|
|
endif
|
|
lnabsdet=lnabsdet+dlog(dabs(copya(j,j)))
|
|
enddo
|
|
if(d.lt.0.0d0)then
|
|
numneg=numneg+1
|
|
endif
|
|
if(mod(numneg,2).eq.0)then
|
|
signunit=1.0d0
|
|
else
|
|
signunit=-1.0d0
|
|
endif
|
|
return
|
|
end
|
|
|
|
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
double precision function tracematrix(m,a)
|
|
implicit none
|
|
integer m,i
|
|
double precision a(m,m)
|
|
|
|
tracematrix=0.0d0
|
|
do i=1,m
|
|
tracematrix=tracematrix+a(i,i)
|
|
enddo
|
|
return
|
|
end
|
|
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
subroutine matrixproduct(ma,n,a,nb,b,c)
|
|
implicit none
|
|
!
|
|
! matrix product c=ab
|
|
!
|
|
integer ma,n,nb
|
|
double precision a(ma,n),b(n,nb),c(ma,nb)
|
|
integer i,j,k
|
|
do i=1,ma
|
|
do j=1,nb
|
|
c(i,j)=0.0d0
|
|
do k=1,n
|
|
c(i,j)=c(i,j)+a(i,k)*b(k,j)
|
|
enddo
|
|
enddo
|
|
enddo
|
|
return
|
|
end
|
|
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
subroutine matrixsum(m,n,a,b,c)
|
|
implicit none
|
|
!
|
|
! matrix sum c=a+b
|
|
!
|
|
integer m,n
|
|
double precision a(m,n),b(m,n),c(m,n)
|
|
integer i,j
|
|
do i=1,m
|
|
do j=1,n
|
|
c(i,j)=a(i,j)+b(i,j)
|
|
enddo
|
|
enddo
|
|
return
|
|
end
|
|
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
subroutine matrixdif(m,n,a,b,c)
|
|
implicit none
|
|
!
|
|
! matrix difference c=a-b
|
|
!
|
|
integer m,n
|
|
double precision a(m,n),b(m,n),c(m,n)
|
|
integer i,j
|
|
do i=1,m
|
|
do j=1,n
|
|
c(i,j)=a(i,j)-b(i,j)
|
|
enddo
|
|
enddo
|
|
return
|
|
end
|
|
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
subroutine matrixtranspose(m,n,a,b)
|
|
implicit none
|
|
!
|
|
! matrix transpose b=a^T
|
|
!
|
|
integer m,n
|
|
double precision a(m,n),b(n,m)
|
|
integer i,j
|
|
do i=1,m
|
|
do j=1,n
|
|
b(j,i)=a(i,j)
|
|
enddo
|
|
enddo
|
|
return
|
|
end
|
|
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
SUBROUTINE svbksb(u,w,v,m,n,mp,np,b,x)
|
|
implicit none
|
|
INTEGER m,mp,n,np,NMAX
|
|
double precision b(mp),u(mp,np),v(np,np),w(np),x(np)
|
|
PARAMETER (NMAX=1500)
|
|
INTEGER i,j,jj
|
|
double precision s,tmp(NMAX)
|
|
do 12 j=1,n
|
|
s=0.0d0
|
|
if(w(j).ne.0.0d0)then
|
|
do 11 i=1,m
|
|
s=s+u(i,j)*b(i)
|
|
11 continue
|
|
s=s/w(j)
|
|
endif
|
|
tmp(j)=s
|
|
12 continue
|
|
do 14 j=1,n
|
|
s=0.0d0
|
|
do 13 jj=1,n
|
|
s=s+v(j,jj)*tmp(jj)
|
|
13 continue
|
|
x(j)=s
|
|
14 continue
|
|
return
|
|
END
|
|
C (C) Copr. 1986-92 Numerical Recipes Software v%1jw#<0(9p#3.
|
|
|
|
SUBROUTINE svdcmp(a,m,n,mp,np,w,v,ierr)
|
|
implicit none
|
|
INTEGER m,mp,n,np,NMAX
|
|
,ierr
|
|
double precision a(mp,np),v(np,np),w(np)
|
|
PARAMETER (NMAX=1500)
|
|
CU USES pythag
|
|
INTEGER i,its,j,jj,k,l,nm
|
|
double precision anorm,c,f,g,h,s,scale,x,y,z,
|
|
& rv1(NMAX),pythag
|
|
g=0.0d0
|
|
scale=0.0d0
|
|
anorm=0.0d0
|
|
do 25 i=1,n
|
|
l=i+1
|
|
rv1(i)=scale*g
|
|
g=0.0d0
|
|
s=0.0d0
|
|
scale=0.0d0
|
|
if(i.le.m)then
|
|
do 11 k=i,m
|
|
scale=scale+dabs(a(k,i))
|
|
11 continue
|
|
if(scale.ne.0.0d0)then
|
|
do 12 k=i,m
|
|
a(k,i)=a(k,i)/scale
|
|
s=s+a(k,i)*a(k,i)
|
|
12 continue
|
|
f=a(i,i)
|
|
g=-dsign(dsqrt(s),f)
|
|
h=f*g-s
|
|
a(i,i)=f-g
|
|
do 15 j=l,n
|
|
s=0.0d0
|
|
do 13 k=i,m
|
|
s=s+a(k,i)*a(k,j)
|
|
13 continue
|
|
f=s/h
|
|
do 14 k=i,m
|
|
a(k,j)=a(k,j)+f*a(k,i)
|
|
14 continue
|
|
15 continue
|
|
do 16 k=i,m
|
|
a(k,i)=scale*a(k,i)
|
|
16 continue
|
|
endif
|
|
endif
|
|
w(i)=scale*g
|
|
g=0.0d0
|
|
s=0.0d0
|
|
scale=0.0d0
|
|
if((i.le.m).and.(i.ne.n))then
|
|
do 17 k=l,n
|
|
scale=scale+dabs(a(i,k))
|
|
17 continue
|
|
if(scale.ne.0.0d0)then
|
|
do 18 k=l,n
|
|
a(i,k)=a(i,k)/scale
|
|
s=s+a(i,k)*a(i,k)
|
|
18 continue
|
|
f=a(i,l)
|
|
g=-dsign(dsqrt(s),f)
|
|
h=f*g-s
|
|
a(i,l)=f-g
|
|
do 19 k=l,n
|
|
rv1(k)=a(i,k)/h
|
|
19 continue
|
|
do 23 j=l,m
|
|
s=0.0d0
|
|
do 21 k=l,n
|
|
s=s+a(j,k)*a(i,k)
|
|
21 continue
|
|
do 22 k=l,n
|
|
a(j,k)=a(j,k)+s*rv1(k)
|
|
22 continue
|
|
23 continue
|
|
do 24 k=l,n
|
|
a(i,k)=scale*a(i,k)
|
|
24 continue
|
|
endif
|
|
endif
|
|
anorm=dmax1(anorm,(dabs(w(i))+dabs(rv1(i))))
|
|
25 continue
|
|
do 32 i=n,1,-1
|
|
if(i.lt.n)then
|
|
if(g.ne.0.0d0)then
|
|
do 26 j=l,n
|
|
v(j,i)=(a(i,j)/a(i,l))/g
|
|
26 continue
|
|
do 29 j=l,n
|
|
s=0.0d0
|
|
do 27 k=l,n
|
|
s=s+a(i,k)*v(k,j)
|
|
27 continue
|
|
do 28 k=l,n
|
|
v(k,j)=v(k,j)+s*v(k,i)
|
|
28 continue
|
|
29 continue
|
|
endif
|
|
do 31 j=l,n
|
|
v(i,j)=0.0d0
|
|
v(j,i)=0.0d0
|
|
31 continue
|
|
endif
|
|
v(i,i)=1.0d0
|
|
g=rv1(i)
|
|
l=i
|
|
32 continue
|
|
do 39 i=min(m,n),1,-1
|
|
l=i+1
|
|
g=w(i)
|
|
do 33 j=l,n
|
|
a(i,j)=0.0d0
|
|
33 continue
|
|
if(g.ne.0.0d0)then
|
|
g=1.0d0/g
|
|
do 36 j=l,n
|
|
s=0.0d0
|
|
do 34 k=l,m
|
|
s=s+a(k,i)*a(k,j)
|
|
34 continue
|
|
f=(s/a(i,i))*g
|
|
do 35 k=i,m
|
|
a(k,j)=a(k,j)+f*a(k,i)
|
|
35 continue
|
|
36 continue
|
|
do 37 j=i,m
|
|
a(j,i)=a(j,i)*g
|
|
37 continue
|
|
else
|
|
do 38 j= i,m
|
|
a(j,i)=0.0d0
|
|
38 continue
|
|
endif
|
|
a(i,i)=a(i,i)+1.0d0
|
|
39 continue
|
|
do 49 k=n,1,-1
|
|
do 48 its=1,30
|
|
do 41 l=k,1,-1
|
|
nm=l-1
|
|
if((dabs(rv1(l))+anorm).eq.anorm) goto 2
|
|
if((dabs(w(nm))+anorm).eq.anorm) goto 1
|
|
41 continue
|
|
1 c=0.0d0
|
|
s=1.0d0
|
|
do 43 i=l,k
|
|
f=s*rv1(i)
|
|
rv1(i)=c*rv1(i)
|
|
if((dabs(f)+anorm).eq.anorm) goto 2
|
|
g=w(i)
|
|
h=pythag(f,g)
|
|
w(i)=h
|
|
h=1.0d0/h
|
|
c= (g*h)
|
|
s=-(f*h)
|
|
do 42 j=1,m
|
|
y=a(j,nm)
|
|
z=a(j,i)
|
|
a(j,nm)=(y*c)+(z*s)
|
|
a(j,i)=-(y*s)+(z*c)
|
|
42 continue
|
|
43 continue
|
|
2 z=w(k)
|
|
if(l.eq.k)then
|
|
if(z.lt.0.0d0)then
|
|
w(k)=-z
|
|
do 44 j=1,n
|
|
v(j,k)=-v(j,k)
|
|
44 continue
|
|
endif
|
|
goto 3
|
|
endif
|
|
if(its.eq.30)then
|
|
ierr=0
|
|
return
|
|
endif
|
|
x=w(l)
|
|
nm=k-1
|
|
y=w(nm)
|
|
g=rv1(nm)
|
|
h=rv1(k)
|
|
f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0d0*h*y)
|
|
g=pythag(f,1.0d0)
|
|
f=((x-z)*(x+z)+h*((y/(f+dsign(g,f)))-h))/x
|
|
c=1.0d0
|
|
s=1.0d0
|
|
do 47 j=l,nm
|
|
i=j+1
|
|
g=rv1(i)
|
|
y=w(i)
|
|
h=s*g
|
|
g=c*g
|
|
z=pythag(f,h)
|
|
rv1(j)=z
|
|
c=f/z
|
|
s=h/z
|
|
f= (x*c)+(g*s)
|
|
g=-(x*s)+(g*c)
|
|
h=y*s
|
|
y=y*c
|
|
do 45 jj=1,n
|
|
x=v(jj,j)
|
|
z=v(jj,i)
|
|
v(jj,j)= (x*c)+(z*s)
|
|
v(jj,i)=-(x*s)+(z*c)
|
|
45 continue
|
|
z=pythag(f,h)
|
|
w(j)=z
|
|
if(z.ne.0.0d0)then
|
|
z=1.0d0/z
|
|
c=f*z
|
|
s=h*z
|
|
endif
|
|
f= (c*g)+(s*y)
|
|
x=-(s*g)+(c*y)
|
|
do 46 jj=1,m
|
|
y=a(jj,j)
|
|
z=a(jj,i)
|
|
a(jj,j)= (y*c)+(z*s)
|
|
a(jj,i)=-(y*s)+(z*c)
|
|
46 continue
|
|
47 continue
|
|
rv1(l)=0.0d0
|
|
rv1(k)=f
|
|
w(k)=x
|
|
48 continue
|
|
3 continue
|
|
49 continue
|
|
return
|
|
END
|
|
C (C) Copr. 1986-92 Numerical Recipes Software v%1jw#<0(9p#3.
|
|
|
|
double precision FUNCTION pythag(a,b)
|
|
double precision a,b
|
|
double precision absa,absb
|
|
absa=dabs(a)
|
|
absb=dabs(b)
|
|
if(absa.gt.absb)then
|
|
pythag=absa*dsqrt(1.0d0+(absb/absa)**2)
|
|
else
|
|
if(absb.eq.0.0d0)then
|
|
pythag=0.0d0
|
|
else
|
|
pythag=absb*dsqrt(1.0d0+(absa/absb)**2)
|
|
endif
|
|
endif
|
|
return
|
|
END
|
|
C (C) Copr. 1986-92 Numerical Recipes Software v%1jw#<0(9p#3.
|
|
|
|
|
|
subroutine xmprove(N,NP,a,b,x,mark)
|
|
implicit none
|
|
INTEGER i,j,idum,N,NP,indx(N),mark
|
|
double precision d,a(NP,NP),b(N),x(N),aa(NP,NP)
|
|
|
|
do 12 i=1,N
|
|
x(i)=b(i)
|
|
do 11 j=1,N
|
|
aa(i,j)=a(i,j)
|
|
11 continue
|
|
12 continue
|
|
call ludcmp(aa,N,NP,indx,d,mark)
|
|
if (mark .eq. 0) goto 20
|
|
call lubksb(aa,N,NP,indx,x)
|
|
call mprove(a,aa,N,NP,indx,b,x)
|
|
20 continue
|
|
return
|
|
END
|
|
|
|
|
|
SUBROUTINE mprove(a,alud,n,np,indx,b,x)
|
|
implicit none
|
|
INTEGER n,np,indx(n),NMAX
|
|
double precision a(np,np),alud(np,np),b(n),x(n)
|
|
PARAMETER (NMAX=500)
|
|
CU USES lubksb
|
|
INTEGER i,j
|
|
double precision r(NMAX)
|
|
DOUBLE PRECISION sdp
|
|
do 12 i=1,n
|
|
sdp=-b(i)
|
|
do 11 j=1,n
|
|
sdp=sdp+(a(i,j))*(x(j))
|
|
11 continue
|
|
r(i)=sdp
|
|
12 continue
|
|
call lubksb(alud,n,np,indx,r)
|
|
do 13 i=1,n
|
|
x(i)=x(i)-r(i)
|
|
13 continue
|
|
return
|
|
END
|
|
|
|
SUBROUTINE ludcmp(a,n,np,indx,d,mark)
|
|
implicit none
|
|
INTEGER n,np,indx(n),NMAX
|
|
double precision d,a(np,np),TINY
|
|
PARAMETER (NMAX=500,TINY=1.0d-20)
|
|
INTEGER i,imax,j,k,mark
|
|
double precision aamax,dum,sum,vv(NMAX)
|
|
mark=1
|
|
|
|
d=1.0d0
|
|
do 12 i=1,n
|
|
aamax=0.0d0
|
|
do 11 j=1,n
|
|
if (dabs(a(i,j)).gt.aamax) aamax=dabs(a(i,j))
|
|
11 continue
|
|
if (aamax.eq.0.0d0) then
|
|
! singular matrix
|
|
mark=0
|
|
return
|
|
end if
|
|
vv(i)=1.0d0/aamax
|
|
12 continue
|
|
do 19 j=1,n
|
|
do 14 i=1,j-1
|
|
sum=a(i,j)
|
|
do 13 k=1,i-1
|
|
sum=sum-a(i,k)*a(k,j)
|
|
13 continue
|
|
a(i,j)=sum
|
|
14 continue
|
|
aamax=0.0d0
|
|
do 16 i=j,n
|
|
sum=a(i,j)
|
|
do 15 k=1,j-1
|
|
sum=sum-a(i,k)*a(k,j)
|
|
15 continue
|
|
a(i,j)=sum
|
|
dum=vv(i)*dabs(sum)
|
|
if (dum.ge.aamax) then
|
|
imax=i
|
|
aamax=dum
|
|
endif
|
|
16 continue
|
|
if (j.ne.imax)then
|
|
do 17 k=1,n
|
|
dum=a(imax,k)
|
|
a(imax,k)=a(j,k)
|
|
a(j,k)=dum
|
|
17 continue
|
|
d=-d
|
|
vv(imax)=vv(j)
|
|
endif
|
|
indx(j)=imax
|
|
if(a(j,j).eq.0.0d0)a(j,j)=TINY
|
|
if(j.ne.n)then
|
|
dum=1.0d0/a(j,j)
|
|
do 18 i=j+1,n
|
|
a(i,j)=a(i,j)*dum
|
|
18 continue
|
|
endif
|
|
19 continue
|
|
return
|
|
END
|
|
|
|
SUBROUTINE lubksb(a,n,np,indx,b)
|
|
implicit none
|
|
INTEGER n,np,indx(n)
|
|
double precision a(np,np),b(n)
|
|
INTEGER i,ii,j,ll
|
|
double precision sum
|
|
ii=0
|
|
do 12 i=1,n
|
|
ll=indx(i)
|
|
sum=b(ll)
|
|
b(ll)=b(i)
|
|
if (ii.ne.0)then
|
|
do 11 j=ii,i-1
|
|
sum=sum-a(i,j)*b(j)
|
|
11 continue
|
|
else if (sum.ne.0.0d0) then
|
|
ii=i
|
|
endif
|
|
b(i)=sum
|
|
12 continue
|
|
do 14 i=n,1,-1
|
|
sum=b(i)
|
|
do 13 j=i+1,n
|
|
sum=sum-a(i,j)*b(j)
|
|
13 continue
|
|
b(i)=sum/a(i,i)
|
|
14 continue
|
|
return
|
|
END
|
|
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
subroutine svdlinsys(n,np,a,b,x)
|
|
implicit none
|
|
!
|
|
! Solving a linear system ax=b through singular value decomposition
|
|
integer n,np
|
|
double precision a(np,np),b(np),x(np)
|
|
integer i,j,ierr
|
|
double precision u(np,np),w(np),v(np,np),
|
|
& wmax,ftol,wmin
|
|
parameter(ftol=1.0d-7)
|
|
|
|
do i=1,n
|
|
do j=1,n
|
|
u(i,j)=a(i,j)
|
|
enddo
|
|
enddo
|
|
call svdcmp(u(1:n,1:n),n,n,np,np,w,v(1:n,1:n),ierr)
|
|
wmax=0.0d0
|
|
do j=1,n
|
|
if(w(j).gt.wmax)wmax=w(j)
|
|
enddo
|
|
wmin=wmax*ftol
|
|
do j=1,n
|
|
if(w(j).lt.wmin)w(j)=0.0d0
|
|
enddo
|
|
call svbksb(u(1:n,1:n),w,v(1:n,1:n),n,n,np,np,b,x)
|
|
return
|
|
end
|
|
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
|
|
SUBROUTINE qrdcmp(a,n,np,c,d,sing)
|
|
implicit none
|
|
INTEGER n,np
|
|
DOUBLE PRECISION a(np,np),c(n),d(n)
|
|
LOGICAL sing
|
|
INTEGER i,j,k
|
|
DOUBLE PRECISION scale,sigma,sum,tau
|
|
sing=.false.
|
|
do 17 k=1,n-1
|
|
scale=0.0d0
|
|
do 11 i=k,n
|
|
scale=dmax1(scale,dabs(a(i,k)))
|
|
11 continue
|
|
if(scale.eq.0.0d0)then
|
|
sing=.true.
|
|
c(k)=0.0d0
|
|
d(k)=0.0d0
|
|
else
|
|
do 12 i=k,n
|
|
a(i,k)=a(i,k)/scale
|
|
12 continue
|
|
sum=0.0d0
|
|
do 13 i=k,n
|
|
sum=sum+a(i,k)**2
|
|
13 continue
|
|
sigma=dsign(dsqrt(sum),a(k,k))
|
|
a(k,k)=a(k,k)+sigma
|
|
c(k)=sigma*a(k,k)
|
|
d(k)=-scale*sigma
|
|
do 16 j=k+1,n
|
|
sum=0.0d0
|
|
do 14 i=k,n
|
|
sum=sum+a(i,k)*a(i,j)
|
|
14 continue
|
|
tau=sum/c(k)
|
|
do 15 i=k,n
|
|
a(i,j)=a(i,j)-tau*a(i,k)
|
|
15 continue
|
|
16 continue
|
|
endif
|
|
17 continue
|
|
d(n)=a(n,n)
|
|
if(d(n).eq.0.0d0)sing=.true.
|
|
return
|
|
END
|
|
c
|
|
SUBROUTINE qrupdt(r,qt,n,np,u,v)
|
|
implicit none
|
|
INTEGER n,np
|
|
DOUBLE PRECISION r(np,np),qt(np,np),u(np),v(np)
|
|
CU USES rotate
|
|
INTEGER i,j,k
|
|
do 11 k=n,1,-1
|
|
if(u(k).ne.0.0d0)goto 1
|
|
11 continue
|
|
k=1
|
|
1 do 12 i=k-1,1,-1
|
|
call rotate(r,qt,n,np,i,u(i),-u(i+1))
|
|
if(u(i).eq.0.0d0)then
|
|
u(i)=dabs(u(i+1))
|
|
else if(dabs(u(i)).gt.dabs(u(i+1)))then
|
|
u(i)=dabs(u(i))*dsqrt(1.0d0+(u(i+1)/u(i))**2)
|
|
else
|
|
u(i)=dabs(u(i+1))*dsqrt(1.0d0+(u(i)/u(i+1))**2)
|
|
endif
|
|
12 continue
|
|
do 13 j=1,n
|
|
r(1,j)=r(1,j)+u(1)*v(j)
|
|
13 continue
|
|
do 14 i=1,k-1
|
|
call rotate(r,qt,n,np,i,r(i,i),-r(i+1,i))
|
|
14 continue
|
|
return
|
|
END
|
|
c
|
|
SUBROUTINE rsolv(a,n,np,d,b)
|
|
implicit none
|
|
INTEGER n,np
|
|
DOUBLE PRECISION a(np,np),b(n),d(n)
|
|
INTEGER i,j
|
|
DOUBLE PRECISION sum
|
|
b(n)=b(n)/d(n)
|
|
do 12 i=n-1,1,-1
|
|
sum=0.0d0
|
|
do 11 j=i+1,n
|
|
sum=sum+a(i,j)*b(j)
|
|
11 continue
|
|
b(i)=(b(i)-sum)/d(i)
|
|
12 continue
|
|
return
|
|
END
|
|
c
|
|
SUBROUTINE rotate(r,qt,n,np,i,a,b)
|
|
implicit none
|
|
INTEGER n,np,i
|
|
DOUBLE PRECISION a,b,r(np,np),qt(np,np)
|
|
INTEGER j
|
|
DOUBLE PRECISION c,fact,s,w,y
|
|
if(a.eq.0.0d0)then
|
|
c=0.0d0
|
|
s=dsign(1.0d0,b)
|
|
else if(dabs(a).gt.dabs(b))then
|
|
fact=b/a
|
|
c=dsign(1.0d0/dsqrt(1.0d0+fact**2),a)
|
|
s=fact*c
|
|
else
|
|
fact=a/b
|
|
s=dsign(1.0d0/dsqrt(1.0d0+fact**2),b)
|
|
c=fact*s
|
|
endif
|
|
do 11 j=i,n
|
|
y=r(i,j)
|
|
w=r(i+1,j)
|
|
r(i,j)=c*y-s*w
|
|
r(i+1,j)=s*y+c*w
|
|
11 continue
|
|
do 12 j=1,n
|
|
y=qt(i,j)
|
|
w=qt(i+1,j)
|
|
qt(i,j)=c*y-s*w
|
|
qt(i+1,j)=s*y+c*w
|
|
12 continue
|
|
return
|
|
END
|
|
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
subroutine symmatindex(ndim,icolrow,indexi)
|
|
implicit none
|
|
|
|
integer ndim,icolrow,indexi(ndim)
|
|
|
|
! this subroutine determines the sequence number of the elements of the row i
|
|
! or column i of a symmetric matrix that is stored in compact form (diagonal included)
|
|
! The compact form stores the upper triangle of the matrix sequentially
|
|
! column by column
|
|
! 1, 2, 4, 7, 11,
|
|
! 3, 5, 8, 12,
|
|
! 6, 9, 13,
|
|
! 10 14,
|
|
! 15,
|
|
! Note that it does not matter whether it is row or column because the matrix is
|
|
! symmetric
|
|
integer j,icompactpostri
|
|
|
|
indexi(1)=icompactpostri(1,icolrow)
|
|
do j=2,icolrow
|
|
indexi(j)=indexi(j-1)+1
|
|
enddo
|
|
do j=icolrow+1,ndim
|
|
indexi(j)=icompactpostri(icolrow,j)
|
|
enddo
|
|
return
|
|
end
|
|
!
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
subroutine ivarjvartri(invars,nvars,indexvars,
|
|
& ivar,jvar,istart,jstart)
|
|
implicit none
|
|
!
|
|
!This subroutine has two functions:
|
|
!1.Given the position number in the vector that stores the upper triangle
|
|
! (including the diagonal elements) of a symmetric matrix, determine the cell position
|
|
! (ivar,jvar) indices in the actual matrix.
|
|
!2. Determine the starting cell position in the symmetric matrix formed by all
|
|
! elements of the nvars variables. The number of elements
|
|
! indexed by ivar or jvar is specified in indexvars.
|
|
|
|
integer invars,nvars,indexvars(nvars),ivar,jvar,
|
|
& istart,jstart
|
|
integer n0
|
|
|
|
jvar=int((1.0d0+dsqrt(dble(8*invars-7)))/2.0d0)
|
|
ivar=invars-(jvar*(jvar-1))/2
|
|
if(ivar.gt.jvar)then
|
|
! rounding error
|
|
jvar=jvar+1
|
|
ivar=invars-(jvar*(jvar-1))/2
|
|
endif
|
|
|
|
20 istart=0
|
|
do n0=1,ivar-1
|
|
istart=istart+indexvars(n0)
|
|
enddo
|
|
istart=istart+1
|
|
jstart=0
|
|
do n0=1,jvar-1
|
|
jstart=jstart+indexvars(n0)
|
|
enddo
|
|
jstart=jstart+1
|
|
return
|
|
end subroutine ivarjvartri
|
|
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
subroutine ivarjvaroff(invars,nvars,indexvars,
|
|
& ivar,jvar,istart,jstart)
|
|
implicit none
|
|
!
|
|
!This subroutine has two functions:
|
|
!1.Given the position number in the vector that stores the upper triangle
|
|
! (not including the diagonal elements) of a symmetric matrix, determine the cell position
|
|
! (ivar,jvar) indices in the actual matrix.
|
|
!2. Determine the starting cell position in the expanded matrix. The number of elements
|
|
! indexed by ivar or jvar is specified in indexvars.
|
|
|
|
integer invars,nvars,indexvars(nvars),ivar,jvar,
|
|
& istart,jstart
|
|
integer n0
|
|
|
|
jvar=int((3.0d0+dsqrt(dble(8*invars-7)))/2.0d0)
|
|
ivar=invars-((jvar-2)*(jvar-1))/2
|
|
if(ivar.ge.jvar)then
|
|
! rounding error
|
|
jvar=jvar+1
|
|
ivar=invars-((jvar-2)*(jvar-1))/2
|
|
endif
|
|
istart=0
|
|
do n0=1,ivar-1
|
|
istart=istart+indexvars(n0)
|
|
enddo
|
|
istart=istart+1
|
|
jstart=0
|
|
do n0=1,jvar-1
|
|
jstart=jstart+indexvars(n0)
|
|
enddo
|
|
jstart=jstart+1
|
|
return
|
|
end subroutine ivarjvaroff
|
|
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
integer function icompactpostri(irow0,jcol0)
|
|
implicit none
|
|
!
|
|
! determine the position of the cell (irow,jcol) in the vector
|
|
! that stores the upper triangle of a symmetric matrix, including
|
|
! the diagonal elements.
|
|
! irow <=jcol
|
|
|
|
integer irow0,jcol0
|
|
|
|
icompactpostri=irow0+(jcol0*(jcol0-1))/2
|
|
|
|
return
|
|
end
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
integer function icompactposoff(irow0,jcol0)
|
|
implicit none
|
|
!
|
|
! determine the position of the cell (irow,jcol) in the vector
|
|
! that stores the upper triangle of a symmetric matrix, not including
|
|
! the diagonal elements.
|
|
! irow < jcol-1
|
|
|
|
integer irow0,jcol0
|
|
|
|
icompactposoff=irow0+((jcol0-1)*(jcol0-2))/2
|
|
return
|
|
end
|
|
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
subroutine istartjstart(ivar,jvar,nvars,
|
|
& indexvars,istart,jstart)
|
|
implicit none
|
|
|
|
integer nvars,indexvars(nvars),ivar,jvar,istart,
|
|
& jstart,n0
|
|
!
|
|
istart=0
|
|
do n0=1,ivar-1
|
|
istart=istart+indexvars(n0)
|
|
enddo
|
|
istart=istart+1
|
|
jstart=0
|
|
do n0=1,jvar-1
|
|
jstart=jstart+indexvars(n0)
|
|
enddo
|
|
jstart=jstart+1
|
|
return
|
|
end subroutine istartjstart
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
|
integer function getwhichvar(ipos,nvars,indexvars)
|
|
implicit none
|
|
!
|
|
! determine to which variable ipos belongs
|
|
integer ipos,nvars,indexvars(nvars),n0,i
|
|
!
|
|
n0=0
|
|
i=0
|
|
10 i=i+1
|
|
n0=n0+indexvars(i)
|
|
if(ipos.le.n0)then
|
|
getwhichvar=i
|
|
return
|
|
endif
|
|
goto 10
|
|
end
|
|
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |