cumulator.f90 Source File


Contents

Source Code


Source Code

module mod_cumu
use tensor_type
use tnsp_ext
use error
implicit none
private

type cumulator
	private
	real(8)::dcumu
	complex(8)::zcumu
	type(tensor)::tcumu
	real(8)::weight
	character(len=1)::type='f' ! f means undefined

contains
	private
	procedure,public::init
	procedure::iadd
	procedure::dadd
	procedure::zadd
	procedure::tadd
	generic,public::add=>iadd,dadd,zadd,tadd
	procedure,public::clean
	procedure,public::dave
	procedure,public::zave
	procedure,public::tave
	procedure,public::get_weight
end type

public cumulator

contains

subroutine init(C,type,T)

	class(cumulator),intent(inout) :: C
	character(len=1),intent(in) :: type
	class(tensor),intent(in),optional ::T
	
	select case(type)
	case('d')
		C%type='d'
	case('z')
		C%type='z'
	case('t')
		C%type='t'
		if(.not.present(T))then
			call wc_error_stop('cumu.init','tensor prototype needed!')
		else
			call C%tcumu%allocate(T)
			call C%tcumu%static()
		end if
	case default
		call wc_error_stop('cumu.init','input type unidentified!')
	end select
	call C%clean()

end subroutine

subroutine iadd(C,val,weight_)

	class(cumulator),intent(inout) :: C
	integer,intent(in)::val
	real(8),intent(in),optional::weight_
	real(8) :: weight
	type(tensor)::name
	
	if(present(weight_))then
		weight=weight_
	else
		weight=1d0
	end if

	select case(C%type)
	case('d')
		C%dcumu=C%dcumu+val*weight
	case('z')
		C%zcumu=C%zcumu+val*weight
	case('t')
		if(.not. abs(val)<1d-10)then ! otherwise 0 is added
			call wc_error_stop('cumu.add','tensor input needed!')
		end if
	case('f')
		call wc_error_stop('cumu.add','cumulator used before initiated!')
	end select

	C%weight=C%weight+weight

end subroutine

subroutine dadd(C,val,weight_)

	class(cumulator),intent(inout) :: C
	real(8),intent(in)::val
	real(8),intent(in),optional::weight_
	real(8) :: weight
	type(tensor)::name
	
	if(present(weight_))then
		weight=weight_
	else
		weight=1d0
	end if

	select case(C%type)
	case('d')
		C%dcumu=C%dcumu+val*weight
	case('z')
		C%zcumu=C%zcumu+val*weight
	case('t')
		if(.not. abs(val)<1d-10)then ! otherwise 0 is added
			call wc_error_stop('cumu.add','tensor input needed!')
		end if
	case('f')
		call wc_error_stop('cumu.add','cumulator used before initiated!')
	end select

	C%weight=C%weight+weight

end subroutine

subroutine zadd(C,val,weight_)

	class(cumulator),intent(inout) :: C
	complex(8),intent(in)::val
	real(8),intent(in),optional::weight_
	real(8) :: weight
	type(tensor)::name
	
	if(present(weight_))then
		weight=weight_
	else
		weight=1d0
	end if
	
	select case(C%type)
	case('d')
		C%dcumu=C%dcumu+val*weight
	case('z')
		C%zcumu=C%zcumu+val*weight
	case('t')
		call wc_error_stop('cumu.add','tensor input needed!')
	case('f')
		call wc_error_stop('cumu.add','cumulator used before initiated!')
	end select
	
	C%weight=C%weight+weight

end subroutine

subroutine tadd(C,val,weight_)

	class(cumulator),intent(inout) :: C
	class(tensor),intent(inout)::val
	real(8),intent(in),optional::weight_
	real(8) :: weight
	type(tensor)::name
	
	if(present(weight_))then
		weight=weight_
	else
		weight=1d0
	end if
	
	select case(C%type)
	case('d','z')
		call wc_error_stop('cumu.add','real or complex input needed!')
	case('t')
		name=C%tcumu%getname()
		call val%permute(name%ai())
		C%tcumu=C%tcumu+val*weight
	case('f')
		call wc_error_stop('cumu.add','cumulator used before initiated!')
	end select
	
	C%weight=C%weight+weight

end subroutine

subroutine clean(C)

	class(cumulator),intent(inout) :: C

	select case(C%type)
	case('d')
		C%dcumu=0d0
	case('z')
		C%zcumu=dcmplx(0d0,0d0)
	case('t')
		call C%tcumu%zero()
	case('f')
		call wc_error_stop('cumu.clean','cumulator used before initiated!')
	end select
	C%weight=0d0

end subroutine

function dave(C,comm,root) result(res)

	class(cumulator),intent(inout) :: C
	integer,intent(in),optional::comm,root
	integer::my_rank,nproc,ierr
	real(8)::res,totcumu,totweight

	select case(C%type)
	case('d')
		if(present(comm))then
			if(present(root))then
				call MPI_Comm_size(comm,nproc, ierr)
				call MPI_Comm_rank(MPI_COMM_WORLD,my_rank,ierr)
				if(root>=nproc) call wc_error_stop('cumu.dave','root id >= number of processors!')
				call MPI_reduce(C%dcumu,totcumu,1,MPI_REAL8,MPI_SUM,root,comm,ierr)
				call MPI_reduce(C%weight,totweight,1,MPI_REAL8,MPI_SUM,root,comm,ierr)
				if(my_rank==root)then
					if(totweight==0d0) call wc_error_stop('cumu.dave','total weight is 0!')
					res=totcumu/totweight
				end if
			else
				call MPI_allreduce(C%dcumu,totcumu,1,MPI_REAL8,MPI_SUM,comm,ierr)
				call MPI_allreduce(C%weight,totweight,1,MPI_REAL8,MPI_SUM,comm,ierr)
				if(totweight==0d0) call wc_error_stop('cumu.dave','total weight is 0!')
				res=totcumu/totweight
			end if 
		else
			if(C%weight==0d0) call wc_error_stop('cumu.dave','total weight is 0!')
			res=C%dcumu/C%weight
		end if
	case('z')
		call wc_error_stop('cumu.dave','please use zave for complex value!')
	case('t')
		call wc_error_stop('cumu.dave','please use tave for tensor value!')
	case('f')
		call wc_error_stop('cumu.dave','cumulator used before initiated!')
	end select

end function

function zave(C,comm,root) result(res)

	class(cumulator),intent(inout) :: C
	integer,intent(in),optional::comm,root
	integer::my_rank,nproc,ierr
	complex(8)::res,totcumu
	real(8)::totweight

	select case(C%type)
	case('d')
		call wc_error_stop('cumu.zave','please use dave for real value!')
	case('z')
		if(present(comm))then
			if(present(root))then
				call MPI_Comm_size(comm,nproc, ierr)
				call MPI_Comm_rank(comm,my_rank,ierr)
				if(root>=nproc) call wc_error_stop('cumu.zave','root id >= number of processors!')
				call MPI_reduce(C%zcumu,totcumu,1,MPI_DOUBLE_COMPLEX,MPI_SUM,root,comm,ierr)
				call MPI_reduce(C%weight,totweight,1,MPI_REAL8,MPI_SUM,root,comm,ierr)
				if(my_rank==root)then
					if(totweight==0d0) call wc_error_stop('cumu.zave','total weight is 0!')
					res=totcumu/totweight
				end if
			else
				call MPI_allreduce(C%zcumu,totcumu,1,MPI_DOUBLE_COMPLEX,MPI_SUM,comm,ierr)
				call MPI_allreduce(C%weight,totweight,1,MPI_REAL8,MPI_SUM,comm,ierr)
				if(totweight==0d0) call wc_error_stop('cumu.zave','total weight is 0!')
				res=totcumu/totweight
			end if 
		else
			if(C%weight==0d0) call wc_error_stop('cumu.zave','total weight is 0!')
			res=C%zcumu/C%weight
		end if
	case('t')
		call wc_error_stop('cumu.zave','please use tave for tensor value!')
	case('f')
		call wc_error_stop('cumu.zave','cumulator used before initiated!')
	end select

end function

function tave(C,comm,root) result(res)

	class(cumulator),intent(inout) :: C
	integer,intent(in),optional::comm,root
	integer::my_rank,nproc,ierr
	real(8)::totweight
	type(tensor)::res,totcumu

	select case(C%type)
	case('d')
		call wc_error_stop('cumu.tave','please use dave for real value!')
	case('z')
		call wc_error_stop('cumu.tave','please use zave for complex value!')
	case('t')
		if(present(comm))then
			if(present(root))then
				call MPI_Comm_size(comm,nproc, ierr)
				call MPI_Comm_rank(comm,my_rank,ierr)
				if(root>=nproc) call wc_error_stop('cumu.tave','root id >= number of processors!')
				call wc_reduce_Tensor(C%tcumu,totcumu,MPI_SUM,root,comm,ierr)
				call MPI_reduce(C%weight,totweight,1,MPI_REAL8,MPI_SUM,root,comm,ierr)
				if(my_rank==root)then
					if(totweight==0d0) call wc_error_stop('cumu.tave','total weight is 0!')
					res=totcumu/totweight
				end if
			else
				call wc_allreduce_Tensor(C%tcumu,totcumu,MPI_SUM,comm,ierr)
				call MPI_allreduce(C%weight,totweight,1,MPI_REAL8,MPI_SUM,comm,ierr)
				if(totweight==0d0) call wc_error_stop('cumu.tave','total weight is 0!')
				res=totcumu/totweight
			end if 
		else
			if(C%weight==0d0) call wc_error_stop('cumu.tave','total weight is 0!')
			res=C%tcumu/C%weight
		end if
	case('f')
		call wc_error_stop('cumu.tave','cumulator used before initiated!')
	end select

end function

function get_weight(C,comm,root) result(res)

	class(cumulator),intent(inout) :: C
	integer,intent(in),optional::comm,root
	integer::nproc,ierr
	real(8)::res,totcumu,totweight

	res=0
	if(C%type=='f') call wc_error_stop('cumu.get_weight','cumulator used before initiated!')
	if(present(comm))then
		if(present(root))then
			call MPI_Comm_size(comm,nproc, ierr)
			if(root>=nproc) call wc_error_stop('cumu.get_weight','root id >= number of processors!')
			call MPI_reduce(C%weight,res,1,MPI_REAL8,MPI_SUM,root,comm,ierr)
		else
			call MPI_allreduce(C%weight,res,1,MPI_REAL8,MPI_SUM,comm,ierr)
		end if 
	else
		res=C%weight
	end if

end function

end module