Files
piscal/dataassim/math/algebra/matrixoper.f
2022-09-12 16:40:28 +00:00

1001 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,scaling,x,y,z,
& rv1(NMAX),pythag
g=0.0d0
scaling=0.0d0
anorm=0.0d0
do 25 i=1,n
l=i+1
rv1(i)=scaling*g
g=0.0d0
s=0.0d0
scaling=0.0d0
if(i.le.m)then
do 11 k=i,m
scaling=scaling+dabs(a(k,i))
11 continue
if(scaling.ne.0.0d0)then
do 12 k=i,m
a(k,i)=a(k,i)/scaling
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)=scaling*a(k,i)
16 continue
endif
endif
w(i)=scaling*g
g=0.0d0
s=0.0d0
scaling=0.0d0
if((i.le.m).and.(i.ne.n))then
do 17 k=l,n
scaling=scaling+dabs(a(i,k))
17 continue
if(scaling.ne.0.0d0)then
do 18 k=l,n
a(i,k)=a(i,k)/scaling
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)=scaling*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 scaling,sigma,sum,tau
sing=.false.
do 17 k=1,n-1
scaling=0.0d0
do 11 i=k,n
scaling=dmax1(scaling,dabs(a(i,k)))
11 continue
if(scaling.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)/scaling
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)=-scaling*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
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&