! calculate generalised inverse of real symmetric, halfstored matrix ! input file: non-zero elements of matrix, one line per element ! -> row no., column no., element (space separated) ! program will ask for file name & no. of rows/columns ! karin meyer program ginverse implicit none real(8), dimension(:), allocatable :: avec real(8) :: xx, det, zero=1.d-9 character(len=30) :: fname logical :: lex integer :: neqns, i, j, n, ii, nrank, ij integer, external :: ihmssf ! get file name write(*,*)'Give name of input file (max 30 char.s): ' read(*,'(a)',iostat=ii) fname if(ii/=0) then write(*,*)'error trying to read file name'; stop end if ! open file inquire(file=trim(fname),exist=lex) if( .not. lex )then write(*,*)'file "',trim(fname),'" does not seem to exist'; stop end if open(1,file=trim(fname),status='old',form='formatted',action='read') write(*,*)'"',trim(fname),'" opened ' write(*,*)'Give size (no. of rows/columns) of matrix: ' read(*,*,iostat=ii) neqns if(ii/=0) then write(*,*)'error trying to read number'; stop end if write(*,*)'No. of rows/columns specified = ',neqns ! allocate matrix allocate(avec(neqns*(neqns+1)/2), stat=ii) if( ii/= 0 ) then write(*,*)'error trying to allocate matrix'; stop end if ! read matrix n=0; avec=0.d0 do read(1,*,iostat=ii) i, j, xx; if( ii/=0 )exit if(i < 1 .or. i > neqns .or. j<1 .or. j> neqns ) then write(*,*)'invalid row or column no. encountered', i,j,xx; stop end if avec(ihmssf(i,j,neqns)) = xx; n=n+1 end do write(*,*)'No. of elements in matrix found =',n close(1) ! invert call dkmxhf( avec, det, zero, nrank, neqns, .true.) write(*,*)'Inversion done' write(*,*)'Rank of matrix =',nrank write(*,*)'Log determinant =', det n = count(mask=(avec/=0)) write(*,*)'No. of non-zero elements =',n ! write out matrix: 1st line has determinant & no. of elements! open(2,file='ginverse.out') write(2,*)det,n ! ... following lines have non-zero elements do i=1,neqns do j=1,i ij = ihmssf(i,j,neqns); if( avec(ij) == 0 ) cycle write(2,'(2i10,g18.8)')j,i,avec(ij) end do end do write(*,*)'Output file is: "ginverse.out" ' stop end program ginverse ! =============================== INTEGER FUNCTION IHMSSF(I,J,N) ! =============================== implicit none integer, intent(in) :: i, j, n integer :: i1, j1 IF(I.LE.J)THEN I1=I-1; IHMSSF=N*I1-I*I1/2+J ELSE J1=J-1; IHMSSF=N*J1-J*J1/2+I END IF RETURN END function ihmssf