sparse.f90 Source File

This File Depends On

sourcefile~~sparse.f90~~EfferentGraph sourcefile~sparse.f90 sparse.f90 sourcefile~array.f90 array.f90 sourcefile~array.f90->sourcefile~sparse.f90 sourcefile~kinds.f90 kinds.f90 sourcefile~kinds.f90->sourcefile~sparse.f90 sourcefile~kinds.f90->sourcefile~array.f90
Help

Files Dependent On This One

sourcefile~~sparse.f90~~AfferentGraph sourcefile~sparse.f90 sparse.f90 sourcefile~testsparse.f90 testSparse.f90 sourcefile~sparse.f90->sourcefile~testsparse.f90 sourcefile~basicsolvers.f90 basicSolvers.f90 sourcefile~sparse.f90->sourcefile~basicsolvers.f90 sourcefile~solvers.f90 solvers.f90 sourcefile~sparse.f90->sourcefile~solvers.f90 sourcefile~basicsolvers.f90->sourcefile~testsparse.f90 sourcefile~solvers.f90->sourcefile~testsparse.f90
Help

Source Code


Source Code

module sparse_mod
	use kinds_mod
	use array_mod
	implicit none
	private
	
	!=========!
	!= Types =!
	!=========!
	
	type::spvec_t
		integer,dimension(:),allocatable::i
		real(wp),dimension(:),allocatable::v
	contains
		procedure::get => get_v
		procedure::set => set_v
		procedure::add => add_v
		procedure::toDense => toDense_v
	end type
	
	type::sparse_t
		integer::N
		integer::M
		type(spvec_t),dimension(:),allocatable::rows
	contains
		procedure::get => get_m
		procedure::set => set_m
		procedure::add => add_m
		procedure::expand
		procedure::getDiagonal
		procedure::toDense => toDense_m
		procedure::toText => toText_m
	end type
	
	!==============!
	!= Interfaces =!
	!==============!
	
	interface operator(+)
		module procedure add_uv
		module procedure add_vu
		module procedure add_vv
	end interface
	
	interface operator(*)
		module procedure mul_rv
		module procedure mul_vr
	end interface
	
	interface operator(.o.)
		module procedure dot_uv
		module procedure dot_vu
		module procedure dot_vv
		
		module procedure dot_um
		module procedure dot_mu
		module procedure dot_vm
		module procedure dot_mv
		
		module procedure dot_mm
	end interface
	
	interface matmul
		module procedure dot_mu
		module procedure dot_mv
		module procedure dot_mm
	end interface
	
	interface sum
		module procedure sum_v
	end interface
	
	interface minval
		module procedure minval_v
		module procedure minval_m
	end interface
	
	interface maxval
		module procedure maxval_v
		module procedure maxval_m
	end interface
	
	interface transpose
		module procedure transpose_m
	end interface
	
	!===========!
	!= Exports =!
	!===========!
	
	public::spvec_t
	public::sparse_t
	
	public::newSpvec
	public::newSparse
	
	public::operator(+)
	public::operator(*)
	public::operator(.o.)
	public::matmul
	public::sum
	public::minval
	public::maxval
	public::transpose
	
contains

	!===========!
	!= Utility =!
	!===========!

	function newSpvec() result(o)
		type(spvec_t)::o
		
		allocate(o%i(0))
		allocate(o%v(0))
	end function newSpvec

	function newSparse(N,M) result(o)
		integer,intent(in)::N
		integer,intent(in)::M
		type(sparse_t)::o
		
		integer::k
		
		o%N = N
		o%M = M
		allocate(o%rows(N))
		
		do k=1,N
			o%rows(k) = newSpvec()
		end do
	end function newSparse

	!=======================!
	!= Methods for spvec_t =!
	!=======================!

	function get_v(self,i) result(o)
		class(spvec_t),intent(in)::self
		integer,intent(in)::i
		real(wp)::o
		
		o = sum(self%v,self%i==i)
	end function get_v

	subroutine set_v(self,i,v)
		class(spvec_t),intent(inout)::self
		integer,intent(in)::i
		real(wp),intent(in)::v
		
		logical::doAppend
		integer::k
		
		doAppend = .true.
		
		do k=1,size(self%i)
			if(self%i(k)/=i) cycle
			self%v(k) = v
			doAppend = .false.
		end do
		
		if(doAppend) then
			self%i = [self%i,i]
			self%v = [self%v,v]
		end if
	end subroutine set_v

	subroutine add_v(self,i,v)
		class(spvec_t),intent(inout)::self
		integer,intent(in)::i
		real(wp),intent(in)::v
		
		logical::doAppend
		integer::k
		
		doAppend = .true.
		
		do k=1,size(self%i)
			if(self%i(k)/=i) cycle
			self%v(k) = self%v(k)+v
			doAppend = .false.
		end do
		
		if(doAppend) then
			self%i = [self%i,i]
			self%v = [self%v,v]
		end if
	end subroutine add_v

	function toDense_v(self,N) result(o)
		class(spvec_t),intent(in)::self
		integer,intent(in)::N
		real(wp),dimension(:),allocatable::o
		
		integer::i,k
		
		allocate(o(N))
		o = 0.0_wp
		do k=1,size(self%i)
			i = self%i(k)
			o(i) = self%v(k)
		end do
	end function toDense_v

	!=========================!
	!= Overloads for spvec_t =!
	!=========================!

	function add_uv(u,v) result(o)
		real(wp),dimension(:),intent(in)::u
		type(spvec_t),intent(in)::v
		real(wp),dimension(:),allocatable::o
		
		integer::i,k
		
		o = u
		do k=1,size(v%i)
			i = v%i(k)
			o(i) = o(i)+v%v(k)
		end do
	end function add_uv

	function add_vu(v,u) result(o)
		type(spvec_t),intent(in)::v
		real(wp),dimension(:),intent(in)::u
		real(wp),dimension(:),allocatable::o
		
		integer::i,k
		
		o = u
		do k=1,size(v%i)
			i = v%i(k)
			o(i) = o(i)+v%v(k)
		end do
	end function add_vu

	function add_vv(u,v) result(o)
		type(spvec_t),intent(in)::u
		type(spvec_t),intent(in)::v
		type(spvec_t)::o
		
		integer::i,k
		
		o%i = deDup([u%i,v%i])
		allocate(o%v(size(o%i)))
		
		do k=1,size(o%i)
			i = o%i(k)
			o%v(k) = u%get(i)+v%get(i)
		end do
	end function add_vv

	function mul_rv(r,v) result(o)
		real(wp),intent(in)::r
		type(spvec_t),intent(in)::v
		type(spvec_t)::o
		
		o%i = v%i
		o%v = r*v%v
	end function mul_rv

	function mul_vr(v,r) result(o)
		type(spvec_t),intent(in)::v
		real(wp),intent(in)::r
		type(spvec_t)::o
		
		o%i = v%i
		o%v = r*v%v
	end function mul_vr

	function dot_uv(u,v) result(o)
		real(wp),dimension(:),intent(in)::u
		type(spvec_t),intent(in)::v
		real(wp)::o
		
		o = sum(u(v%i)*v%v)
	end function dot_uv

	function dot_vu(v,u) result(o)
		type(spvec_t),intent(in)::v
		real(wp),dimension(:),intent(in)::u
		real(wp)::o
		
		o = sum(u(v%i)*v%v)
	end function dot_vu

	function dot_vv(u,v) result(o)
		type(spvec_t),intent(in)::u
		type(spvec_t),intent(in)::v
		real(wp)::o
		
		integer::i,k
		
		o = 0.0_wp
		do k=1,size(u%i)
			i = u%i(k)
			o = o+u%v(k)*v%get(i)
		end do
	end function dot_vv

	function sum_v(l) result(o)
		type(spvec_t),dimension(:),intent(in)::l
		type(spvec_t)::o
		
		integer::i,j,k
		real(wp)::v
		
		o%i = deDup( [( l(k)%i , k=1,size(l) )] )
		allocate(o%v(size(o%i)))
		
		do k=1,size(l)
			do j=1,size(l(k)%i)
				i = l(k)%i(j)
				v = l(k)%v(j)
				call o%add(i,v)
			end do
		end do
	end function sum_v

	function minval_v(v) result(o)
		type(spvec_t),intent(in)::v
		real(wp)::o
		
		o = minval(v%v)
	end function minval_v

	function maxval_v(v) result(o)
		type(spvec_t),intent(in)::v
		real(wp)::o
		
		o = maxval(v%v)
	end function maxval_v

	!========================!
	!= Methods for sparse_t =!
	!========================!

	function get_m(self,i,j) result(o)
		class(sparse_t),intent(in)::self
		integer,intent(in)::i
		integer,intent(in)::j
		real(wp)::o
		
		o = self%rows(i)%get(j)
	end function get_m

	subroutine set_m(self,i,j,v)
		class(sparse_t),intent(inout)::self
		integer,intent(in)::i
		integer,intent(in)::j
		real(wp),intent(in)::v
		
		call self%rows(i)%set(j,v)
	end subroutine set_m

	subroutine add_m(self,i,j,v)
		class(sparse_t),intent(inout)::self
		integer,intent(in)::i
		integer,intent(in)::j
		real(wp),intent(in)::v
		
		call self%rows(i)%add(j,v)
	end subroutine add_m

	subroutine expand(self,r,c,A)
		class(sparse_t),intent(inout)::self
		integer,dimension(:),intent(in)::r,c
		real(wp),dimension(size(r),size(c)),intent(in)::A
		
		integer::i,j,k,l
		
		do k=1,size(r)
			i = r(k)
			if(i>self%N) cycle
			do l=1,size(c)
				j = c(l)
				if(j>self%M) cycle
				
				call self%add(i,j,A(k,l))
			end do
		end do
	end subroutine expand

	function getDiagonal(self) result(o)
		class(sparse_t),intent(in)::self
		real(wp),dimension(:),allocatable::o
		
		integer::i
		
		allocate(o(self%N))
		do i=1,self%N
			o(i) = self%get(i,i)
		end do
	end function getDiagonal

	function toDense_m(self) result(o)
		class(sparse_t),intent(in)::self
		real(wp),dimension(:,:),allocatable::o
		
		integer::i
		
		allocate(o(self%N,self%M))
		o = 0.0_wp
		do i=1,self%N
			o(i,1:self%M) = self%rows(i)%toDense(self%M)
		end do
	end function toDense_m

	subroutine toText_m(self,iou)
		class(sparse_t),intent(in)::self
		integer,intent(in)::iou
		
		integer::i,j,k
		real(wp)::v
		
		do i=1,self%N
			do k=1,size(self%rows(i)%i)
				j = self%rows(i)%i(k)
				v = self%rows(i)%v(k)
				write(iou,*) i,j,v
			end do
		end do
	end subroutine toText_m

	!==========================!
	!= Overloads for sparse_t =!
	!==========================!

	function dot_um(u,A) result(o)
		real(wp),dimension(:),intent(in)::u
		type(sparse_t),intent(in)::A
		real(wp),dimension(:),allocatable::o
		
		integer::i
		
		allocate(o(A%M))
		o = 0.0_wp
		do i=1,A%N
			o = o+u(i)*A%rows(i)%toDense(A%M)
		end do
	end function dot_um

	function dot_mu(A,u) result(o)
		type(sparse_t),intent(in)::A
		real(wp),dimension(:),intent(in)::u
		real(wp),dimension(:),allocatable::o
		
		integer::k
		
		allocate(o(A%N))
		do k=1,size(o)
			o(k) = A%rows(k).o.u
		end do
	end function dot_mu

	function dot_vm(v,A) result(o)
		type(spvec_t),intent(in)::v
		type(sparse_t),intent(in)::A
		type(spvec_t)::o
		
		integer::i,k
		
		o = newSpvec()
		
		do k=1,size(v%i)
			i = v%i(k)
			o = o+v%v(i)*A%rows(i)
		end do
	end function dot_vm

	function dot_mv(A,v) result(o)
		type(sparse_t),intent(in)::A
		type(spvec_t),intent(in)::v
		type(spvec_t)::o
		
		real(wp)::tol,r
		integer::i
		
		tol = (2.0_wp**5)*epsilon(1.0_wp)
		o = newSpvec()
		
		do i=1,A%N
			r = A%rows(i).o.v
			if(abs(r)>tol) call o%set(i,r)
		end do
	end function dot_mv

	function dot_mm(A,B) result(o)
		type(sparse_t),intent(in)::A
		type(sparse_t),intent(in)::B
		type(sparse_t)::o
		
		integer::i
		
		o = newSparse(A%N,B%M)
		do i=1,o%N
			o%rows(i) = A%rows(i).o.B
		end do
	end function dot_mm

	function minval_m(A) result(o)
		type(sparse_t),intent(in)::A
		real(wp)::o
		
		integer::i
		
		o = minval([( minval(A%rows(i)%v) , i=1,A%N )])
	end function minval_m

	function maxval_m(A) result(o)
		type(sparse_t),intent(in)::A
		real(wp)::o
		
		integer::i
		
		o = maxval([( maxval(A%rows(i)%v) , i=1,A%N )])
	end function maxval_m

	function transpose_m(A) result(o)
		type(sparse_t),intent(in)::A
		type(sparse_t)::o
		
		integer::i,j,k
		real(wp)::v
		
		o = newSparse(A%M,A%N)
		
		do i=1,A%N
			do k=1,size(A%rows(i)%i)
				j = A%rows(i)%i(k)
				v = A%rows(i)%v(k)
				call o%set(j,i,v)
			end do
		end do
	end function transpose_m

end module sparse_mod