dictionary.f90 Source File


Contents

Source Code


Source Code

module mod_dictionary
use error
use mod_mpi_info
use string
use tensor_type
implicit none
private

! type: int=1 dbl=2 cmplx=3 char=4 logi=5 ten=6 int_ary=7 dbl_ary=8 char_ary=9 logi_ary=10

integer,parameter::itemmaxn=100
integer,parameter::lenmax=10
integer,parameter::type_num=10
character(len=10),parameter:: type_name(type_num)=['integer   ','double    ','complex   ',&
	'character ','logical   ','tensor    ','int_ary   ','dbl_ary   ','char_ary  ','logi_ary  ']
character(len=2),parameter:: type_abbr(type_num)=['i ','d ','z ','a ','l ','t ','mi','md','ma','ml']
type dictionary

	private
	integer,allocatable::int_val(:)
	integer,allocatable::int_ary_val(:,:)
	integer,allocatable::int_ary_len(:)

	real(8),allocatable::double_val(:)
	real(8),allocatable::dbl_ary_val(:,:)
	integer,allocatable::dbl_ary_len(:)

	complex(8),allocatable::com_val(:)

	character(len=max_char_length),allocatable :: char_val(:)
	character(len=max_char_length),allocatable :: char_ary_val(:,:)
	integer,allocatable::char_ary_len(:)

	logical,allocatable :: logi_val(:)
	logical,allocatable :: logi_ary_val(:,:)
	integer,allocatable::logi_ary_len(:)

	type(tensor),allocatable :: ten_val(:)

	character(len=max_char_length),allocatable:: names(:,:)
	integer,allocatable::itemcurn(:)
	logical::inited=.false.

contains

	private
	procedure::init
	procedure,public::read
	procedure,public::print
	procedure,public::get_names
	procedure,public::sub_name
	procedure,public::sub_val
	procedure,public::clean
	procedure,public::rename
	procedure::isetvalue,dsetvalue,zsetvalue,asetvalue,lsetvalue,tsetvalue,&
		misetvalue,mdsetvalue,masetvalue,mlsetvalue
	generic,public::setvalue=>isetvalue,dsetvalue,zsetvalue,asetvalue,lsetvalue,tsetvalue,&
		misetvalue,mdsetvalue,masetvalue,mlsetvalue
	procedure::igetvalue,dgetvalue,zgetvalue,agetvalue,lgetvalue,tgetvalue,&
		migetvalue,mdgetvalue,magetvalue,mlgetvalue
	generic,public::getvalue=>igetvalue,dgetvalue,zgetvalue,agetvalue,lgetvalue,tgetvalue,&
		migetvalue,mdgetvalue,magetvalue,mlgetvalue
	procedure::insert_int,insert_dbl,insert_com,insert_char,insert_logi,insert_ten,&
		insert_int_ary,insert_dbl_ary,insert_char_ary,insert_logi_ary
	generic,public::insert=>insert_int,insert_dbl,insert_com,insert_char,insert_logi,insert_ten,&
		insert_int_ary,insert_dbl_ary,insert_char_ary,insert_logi_ary
	procedure,public::delete
	procedure,public::ii,di,zi,ai,li,ti,mii,mdi,mai,mli
	procedure,public::append
	procedure,public::check_contain
	procedure::find
	procedure,public::search
	procedure::append_by_name

end type

public dictionary

contains

subroutine init(D)
implicit none

	class(dictionary), intent(inout)::D

	allocate(D%int_val(itemmaxn))
	allocate(D%double_val(itemmaxn))
	allocate(D%com_val(itemmaxn))
	allocate(D%char_val(itemmaxn))
	allocate(D%logi_val(itemmaxn))
	allocate(D%ten_val(itemmaxn))
	allocate(D%int_ary_val(lenmax,itemmaxn))
	allocate(D%int_ary_len(itemmaxn))
	allocate(D%dbl_ary_val(lenmax,itemmaxn))
	allocate(D%dbl_ary_len(itemmaxn))
	allocate(D%char_ary_val(lenmax,itemmaxn))
	allocate(D%char_ary_len(itemmaxn))
	allocate(D%logi_ary_val(lenmax,itemmaxn))
	allocate(D%logi_ary_len(itemmaxn))
	allocate(D%names(itemmaxn,type_num))
	allocate(D%itemcurn(type_num))
	D%inited=.true.
	call D%clean()

end subroutine

subroutine clean(D)

	class(dictionary), intent(inout)::D
	integer::i

	if (.not. D%inited) call D%init()
	D%names=''
	D%itemcurn=0
	D%int_val=0
	D%double_val=0d0
	D%com_val=0d0
	D%char_val=''
	D%logi_val=.false.
	do i=1,D%itemcurn(6)
		call D%ten_val(i)%deallocate()
	end do
	D%int_ary_val=0
	D%int_ary_len=0
	D%dbl_ary_val=0d0
	D%dbl_ary_len=0
	D%char_ary_val=''
	D%char_ary_len=0
	D%logi_ary_val=.false.
	D%logi_ary_len=0


end subroutine

function get_names(D) result(res)

	class(dictionary), intent(in)::D
	character(len=max_char_length),allocatable::res(:)
	integer::num,type

	allocate(res(sum(D%itemcurn)))
	num=0
	do type=1,type_num
		if(D%itemcurn(type)>0) then
			res(num+1:num+D%itemcurn(type))=D%names(:D%itemcurn(type),type)
			num=num+D%itemcurn(type)
		end if
	end do

end function

function sub_val(D,value) result(res)

	class(dictionary), intent(in)::D
	type(dictionary)::res
	character(len=*), intent(in) :: value
	integer::i

	call res%init()
	if (.not. D%inited) return
	do i=1,D%itemcurn(4)
		if(D%char_val(i)==value)then
			call res%insert(D%names(i,4),value)
		end if
	end do

end function

subroutine insert_int(D,name,value)

	class(dictionary), intent(inout)::D
	character(len=*), intent(in) :: name
	integer, intent(in) :: value
	integer::type

	if (.not. D%inited) call D%init()
	type=1
	if(D%itemcurn(type)==itemmaxn)then
		call wc_error_stop('para-insert','num of integer parameter reaches limit')
	else
		D%itemcurn(type)=D%itemcurn(type)+1
		D%int_val(D%itemcurn(type))=value
		D%names(D%itemcurn(type),type)=name
	end if

end subroutine

subroutine insert_int_ary(D,name,value)

	class(dictionary), intent(inout)::D
	character(len=*), intent(in) :: name
	integer, intent(in) :: value(:)
	integer::type

	if (.not. D%inited) call D%init()
	type=7
	if(D%itemcurn(type)==itemmaxn)then
		call wc_error_stop('para-insert','num of integer_ary parameter reaches limit')
	else if (size(value)>lenmax) then
		call wc_error_stop('para-insert','length of integer_ary parameter reaches limit')
	else
		D%itemcurn(type)=D%itemcurn(type)+1
		D%int_ary_val(:size(value),D%itemcurn(type))=value
		D%int_ary_len(D%itemcurn(type))=size(value)
		D%names(D%itemcurn(type),type)=name
	end if

end subroutine

subroutine insert_dbl(D,name,value)

	class(dictionary), intent(inout)::D
	character(len=*), intent(in) :: name
	real(8), intent(in) :: value
	integer::type

	if (.not. D%inited) call D%init()
	type=2
	if(D%itemcurn(type)==itemmaxn)then
		call wc_error_stop('para-insert','num of real parameter reaches limit')
	else
		D%itemcurn(type)=D%itemcurn(type)+1
		D%double_val(D%itemcurn(type))=value
		D%names(D%itemcurn(type),type)=name
	end if

end subroutine

subroutine insert_dbl_ary(D,name,value)

	class(dictionary), intent(inout)::D
	character(len=*), intent(in) :: name
	real(8), intent(in) :: value(:)
	integer::type

	if (.not. D%inited) call D%init()
	type=8
	if(D%itemcurn(type)==itemmaxn)then
		call wc_error_stop('para-insert','num of dbl_ary parameter reaches limit')
	else if (size(value)>lenmax) then
		call wc_error_stop('para-insert','length of dbl_ary parameter reaches limit')
	else
		D%itemcurn(type)=D%itemcurn(type)+1
		D%dbl_ary_val(:size(value),D%itemcurn(type))=value
		D%dbl_ary_len(D%itemcurn(type))=size(value)
		D%names(D%itemcurn(type),type)=name
	end if

end subroutine

subroutine insert_com(D,name,value)

	class(dictionary), intent(inout)::D
	character(len=*), intent(in) :: name
	complex(8), intent(in) :: value
	integer::type

	if (.not. D%inited) call D%init()
	type=3
	if(D%itemcurn(type)==itemmaxn)then
		call wc_error_stop('para-insert','num of complex parameter reaches limit')
	else
		D%itemcurn(type)=D%itemcurn(type)+1
		D%com_val(D%itemcurn(type))=value
		D%names(D%itemcurn(type),type)=name
	end if

end subroutine

subroutine insert_char(D,name,value)

	class(dictionary), intent(inout)::D
	character(len=*), intent(in) :: name
	character(len=*), intent(in) :: value
	integer::type

	if (.not. D%inited) call D%init()
	type=4
	if(D%itemcurn(type)==itemmaxn)then
		call wc_error_stop('para-insert','num of character parameter reaches limit')
	else
		D%itemcurn(type)=D%itemcurn(type)+1
		D%char_val(D%itemcurn(type))=value
		D%names(D%itemcurn(type),type)=name
	end if

end subroutine

subroutine insert_char_ary(D,name,value)

	class(dictionary), intent(inout)::D
	character(len=*), intent(in) :: name
	character(len=*), intent(in) :: value(:)
	integer::type

	if (.not. D%inited) call D%init()
	type=9
	if(D%itemcurn(type)==itemmaxn)then
		call wc_error_stop('para-insert','num of character parameter reaches limit')
	else if (size(value)>lenmax) then
		call wc_error_stop('para-insert','length of character_ary parameter reaches limit')
	else
		D%itemcurn(type)=D%itemcurn(type)+1
		D%char_ary_val(:size(value),D%itemcurn(type))=value
		D%char_ary_len(D%itemcurn(type))=size(value)
		D%names(D%itemcurn(type),type)=name
	end if

end subroutine

subroutine insert_logi(D,name,value)

	class(dictionary), intent(inout)::D
	character(len=*), intent(in) :: name
	logical, intent(in) :: value
	integer::type
	
	if (.not. D%inited) call D%init()
	type=5
	if(D%itemcurn(type)==itemmaxn)then
		call wc_error_stop('para-insert','num of logical parameter reaches limit')
	else
		D%itemcurn(type)=D%itemcurn(type)+1
		D%logi_val(D%itemcurn(type))=value
		D%names(D%itemcurn(type),type)=name
	end if

end subroutine

subroutine insert_logi_ary(D,name,value)

	class(dictionary), intent(inout)::D
	character(len=*), intent(in) :: name
	logical, intent(in) :: value(:)
	integer::type
	
	if (.not. D%inited) call D%init()
	type=10
	if(D%itemcurn(type)==itemmaxn)then
		call wc_error_stop('para-insert','num of logical_ary parameter reaches limit')
	else if (size(value)>lenmax) then
		call wc_error_stop('para-insert','length of logical_ary parameter reaches limit')
	else
		D%itemcurn(type)=D%itemcurn(type)+1
		D%logi_ary_val(:size(value),D%itemcurn(type))=value
		D%logi_ary_len(D%itemcurn(type))=size(value)
		D%names(D%itemcurn(type),type)=name
	end if

end subroutine

subroutine insert_ten(D,name,value)

	class(dictionary), intent(inout)::D
	character(len=*), intent(in) :: name
	type(tensor), intent(in) :: value
	integer::type
	
	if (.not. D%inited) call D%init()
	type=6
	if(D%itemcurn(type)==itemmaxn)then
		call wc_error_stop('para-insert','num of logical parameter reaches limit')
	else
		D%itemcurn(type)=D%itemcurn(type)+1
		D%ten_val(D%itemcurn(type))=value
		D%names(D%itemcurn(type),type)=name
	end if

end subroutine

function ii(D,name) result(res)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	integer::res

	call D%igetvalue(name,res)

end function

function mii(D,name) result(res)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	integer,allocatable::res(:)

	call D%migetvalue(name,res)

end function

function di(D,name) result(res)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	real(8)::res

	call D%dgetvalue(name,res)

end function

function mdi(D,name) result(res)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	real(8),allocatable::res(:)

	call D%mdgetvalue(name,res)

end function

function zi(D,name) result(res)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	complex(8)::res

	call D%zgetvalue(name,res)

end function

function ai(D,name) result(res)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	character(len=max_char_length)::res

	call D%agetvalue(name,res)

end function

function mai(D,name) result(res)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	character(len=max_char_length),allocatable::res(:)

	call D%magetvalue(name,res)

end function

function li(D,name) result(res)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	logical::res

	call D%lgetvalue(name,res)

end function

function mli(D,name) result(res)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	logical,allocatable::res(:)

	call D%mlgetvalue(name,res)

end function

function ti(D,name) result(res)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	type(tensor)::res

	call D%tgetvalue(name,res)

end function


subroutine search(D,name,type,pos,existed)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	integer,intent(out)::type,pos
	logical,intent(out)::existed
	integer::i

	type=-1
	pos=-1
	existed=.false.

	if (D%inited) then
		do type=1,type_num
			do i=1,D%itemcurn(type)
				if(D%names(i,type) == name) then
					pos=i
					existed=.true.
				end if
			end do
			if(existed) exit
		end do
	end if

end subroutine

subroutine find(D,name,type,pos)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	integer,intent(out)::type,pos
	logical::existed
	integer::i

	call search(D,name,type,pos,existed)

	if (.not. existed) call wc_error_stop('dictionary.find',trim(name)//' not found in the paralist.')

end subroutine

function check_contain(D,name) result(res)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	logical::res
	integer::type,pos

	call D%search(name,type,pos,res)

end function

subroutine delete(D,name)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	integer::type,pos

	call D%find(name,type,pos)

	select case (type_name(type))
	case ('integer')
		D%int_val(pos:itemmaxn-1)=D%int_val(pos+1:itemmaxn)
	case ('double')
		D%double_val(pos:itemmaxn-1)=D%double_val(pos+1:itemmaxn)
	case ('complex')
		D%com_val(pos:itemmaxn-1)=D%com_val(pos+1:itemmaxn)
	case ('character')
		D%char_val(pos:itemmaxn-1)=D%char_val(pos+1:itemmaxn)
	case ('logical')
		D%logi_val(pos:itemmaxn-1)=D%logi_val(pos+1:itemmaxn)
	case ('tensor')
		D%ten_val(pos:itemmaxn-1)=D%ten_val(pos+1:itemmaxn)
	case ('int_ary')
		D%int_ary_val(:,pos:itemmaxn-1)=D%int_ary_val(:,pos+1:itemmaxn)
		D%int_ary_len(pos:itemmaxn-1)=D%int_ary_len(pos+1:itemmaxn)
	case ('dbl_ary')
		D%dbl_ary_val(:,pos:itemmaxn-1)=D%dbl_ary_val(:,pos+1:itemmaxn)
		D%dbl_ary_len(pos:itemmaxn-1)=D%dbl_ary_len(pos+1:itemmaxn)
	case ('char_ary')
		D%char_ary_val(:,pos:itemmaxn-1)=D%char_ary_val(:,pos+1:itemmaxn)
		D%char_ary_len(pos:itemmaxn-1)=D%char_ary_len(pos+1:itemmaxn)
	case ('logi_ary')
		D%logi_ary_val(:,pos:itemmaxn-1)=D%logi_ary_val(:,pos+1:itemmaxn)
		D%logi_ary_len(pos:itemmaxn-1)=D%logi_ary_len(pos+1:itemmaxn)
	end select

	D%names(pos:itemmaxn-1,type)=D%names(pos+1:itemmaxn,type)
	D%itemcurn(type)=D%itemcurn(type)-1

end subroutine

subroutine isetvalue(D,name,val,add_tag)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	integer,intent(in)::val
	logical,intent(in),optional::add_tag
	logical::add_tag_,existed
	integer::type,pos

	add_tag_=.false.
	if(present(add_tag))then
		add_tag_=add_tag
	end if

	call D%search(name,type,pos,existed)
	if( existed) then
		select case (type_name(type))
		case ('integer')
			D%int_val(pos)=val
		case ('double')
			D%double_val(pos)=val
		case ('complex')
			D%com_val(pos)=val
		case ('character')
			D%char_val(pos)=str(val)
		case default
			call wc_error_stop('para-setvalue','cannot change from int to '//trim(type_name(type)))
		end select
	else
		if(add_tag_)then
			call D%insert_int(name,val)
		else
			call wc_error_stop('para-setvalue','Var '//trim(name)//' not existes')
		end if
	end if

end subroutine

subroutine misetvalue(D,name,val,add_tag)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	integer,intent(in)::val(:)
	logical,intent(in),optional::add_tag
	logical::add_tag_,existed
	integer::type,pos

	if (size(val)>lenmax) then
		call wc_error_stop('para-setvalue','length of int_ary parameter reaches limit')
	end if

	add_tag_=.false.
	if(present(add_tag))then
		add_tag_=add_tag
	end if

	call D%search(name,type,pos,existed)
	if( existed) then
		select case (type_name(type))
		case ('int_ary')
			D%int_ary_val(:size(val),pos)=val
			D%int_ary_len(pos)=size(val)
		case default
			call wc_error_stop('para-setvalue','cannot change from int_ary to '//trim(type_name(type)))
		end select
	else
		if(add_tag_)then
			call D%insert_int_ary(name,val)
		else
			call wc_error_stop('para-setvalue','Var '//trim(name)//' not existes')
		end if
	end if

end subroutine

subroutine dsetvalue(D,name,val,add_tag)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	real(8),intent(in)::val
	integer::type,pos
	logical,intent(in),optional::add_tag
	logical::add_tag_,existed

	add_tag_=.false.
	if(present(add_tag))then
		add_tag_=add_tag
	end if

	call D%search(name,type,pos,existed)
	if( existed) then
		select case (type_name(type))
		case ('integer')
			D%int_val(pos)=val
		case ('double')
			D%double_val(pos)=val
		case ('complex')
			D%com_val(pos)=val
		case ('character')
			D%char_val(pos)=str(val)
		case default
			call wc_error_stop('para-setvalue','cannot change from real to '//trim(type_name(type)))
		end select
	else
		if(add_tag_)then
			call D%insert_dbl(name,val)
		else
			call wc_error_stop('para-setvalue','Var '//trim(name)//' not existes')
		end if
	end if

end subroutine

subroutine mdsetvalue(D,name,val,add_tag)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	real(8),intent(in)::val(:)
	integer::type,pos
	logical,intent(in),optional::add_tag
	logical::add_tag_,existed

	if (size(val)>lenmax) then
		call wc_error_stop('para-setvalue','length of dbl_ary parameter reaches limit')
	end if

	add_tag_=.false.
	if(present(add_tag))then
		add_tag_=add_tag
	end if

	call D%search(name,type,pos,existed)
	if( existed) then
		select case (type_name(type))
		case ('dbl_ary')
			D%dbl_ary_val(:size(val),pos)=val
			D%dbl_ary_len(pos)=size(val)
		case default
			call wc_error_stop('para-setvalue','cannot change from dbl_ary to '//trim(type_name(type)))
		end select
	else
		if(add_tag_)then
			call D%insert_dbl_ary(name,val)
		else
			call wc_error_stop('para-setvalue','Var '//trim(name)//' not existes')
		end if
	end if

end subroutine

subroutine zsetvalue(D,name,val,add_tag)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	complex(8),intent(in)::val
	integer::type,pos
	logical,intent(in),optional::add_tag
	logical::add_tag_,existed

	add_tag_=.false.
	if(present(add_tag))then
		add_tag_=add_tag
	end if

	call D%search(name,type,pos,existed)
	if( existed) then
		select case (type_name(type))
		case ('integer')
			D%int_val(pos)=val
		case ('double')
			D%double_val(pos)=val
		case ('complex')
			D%com_val(pos)=val
		case ('character')
			D%char_val(pos)=str(val)
		case default
			call wc_error_stop('para-setvalue','cannot change from complex to '//trim(type_name(type)))
		end select
	else
		if(add_tag_)then
			call D%insert_com(name,val)
		else
			call wc_error_stop('para-setvalue','Var '//trim(name)//' not existes')
		end if
	end if

end subroutine

subroutine asetvalue(D,name,val,add_tag)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	character(len=*),intent(in)::val
	integer::type,pos
	logical,intent(in),optional::add_tag
	logical::add_tag_,existed

	add_tag_=.false.
	if(present(add_tag))then
		add_tag_=add_tag
	end if

	call D%search(name,type,pos,existed)
	if( existed) then
		select case (type_name(type))
		case ('character')
			D%char_val(pos)=val
		case default
			call wc_error_stop('para-setvalue','cannot change from char to '//trim(type_name(type)))
		end select
	else
		if(add_tag_)then
			call D%insert_char(name,val)
		else
			call wc_error_stop('para-setvalue','Var '//trim(name)//' not existes')
		end if
	end if
	
end subroutine

subroutine masetvalue(D,name,val,add_tag)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	character(len=*),intent(in)::val(:)
	integer::type,pos
	logical,intent(in),optional::add_tag
	logical::add_tag_,existed

	if (size(val)>lenmax) then
		call wc_error_stop('para-setvalue','length of char_ary parameter reaches limit')
	end if

	add_tag_=.false.
	if(present(add_tag))then
		add_tag_=add_tag
	end if

	call D%search(name,type,pos,existed)
	if( existed) then
		select case (type_name(type))
		case ('char_ary')
			D%char_ary_val(:size(val),pos)=val
			D%char_ary_len(pos)=size(val)
		case default
			call wc_error_stop('para-setvalue','cannot change from char_ary to '//trim(type_name(type)))
		end select
	else
		if(add_tag_)then
			call D%insert_char_ary(name,val)
		else
			call wc_error_stop('para-setvalue','Var '//trim(name)//' not existes')
		end if
	end if
	
end subroutine

subroutine lsetvalue(D,name,val,add_tag)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	logical,intent(in)::val
	integer::type,pos
	logical,intent(in),optional::add_tag
	logical::add_tag_,existed

	add_tag_=.false.
	if(present(add_tag))then
		add_tag_=add_tag
	end if

	call D%search(name,type,pos,existed)
	if( existed) then
		call D%find(name,type,pos)
		select case (type_name(type))
		case ('character')
			D%char_val(pos)=val
		case ('logical')
			D%logi_val(pos)=val
		case default
			call wc_error_stop('para-setvalue','cannot change from logical to '//trim(type_name(type)))
		end select
	else
		if(add_tag_)then
			call D%insert_logi(name,val)
		else
			call wc_error_stop('para-setvalue','Var '//trim(name)//' not existes')
		end if
	end if

end subroutine

subroutine mlsetvalue(D,name,val,add_tag)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	logical,intent(in)::val(:)
	integer::type,pos
	logical,intent(in),optional::add_tag
	logical::add_tag_,existed

	if (size(val)>lenmax) then
		call wc_error_stop('para-setvalue','length of logi_ary parameter reaches limit')
	end if

	add_tag_=.false.
	if(present(add_tag))then
		add_tag_=add_tag
	end if

	call D%search(name,type,pos,existed)
	if( existed) then
		select case (type_name(type))
		case ('logi_ary')
			D%logi_ary_val(:size(val),pos)=val
			D%logi_ary_len(pos)=size(val)
		case default
			call wc_error_stop('para-setvalue','cannot change from logi_ary to '//trim(type_name(type)))
		end select
	else
		if(add_tag_)then
			call D%insert_logi_ary(name,val)
		else
			call wc_error_stop('para-setvalue','Var '//trim(name)//' not existes')
		end if
	end if

end subroutine

subroutine tsetvalue(D,name,val,add_tag)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	type(tensor),intent(in)::val
	integer::type,pos
	logical,intent(in),optional::add_tag
	logical::add_tag_,existed

	add_tag_=.false.
	if(present(add_tag))then
		add_tag_=add_tag
	end if

	call D%search(name,type,pos,existed)
	if( existed) then
		call D%find(name,type,pos)
		select case (type_name(type))
		case ('tensor')
			D%ten_val(pos)=val
		case default
			call wc_error_stop('para-setvalue','cannot change from tensor to '//trim(type_name(type)))
		end select
	else
		if(add_tag_)then
			call D%insert_ten(name,val)
		else
			call wc_error_stop('para-setvalue','Var '//trim(name)//' not existes')
		end if
	end if

end subroutine

subroutine igetvalue(D,name,val)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	integer,intent(inout)::val
	integer::type,pos

	call D%find(name,type,pos)

	select case (type_name(type))
	case ('integer')
		val=D%int_val(pos)
	case ('double')
		val=D%double_val(pos)
	case ('complex')
		val=D%com_val(pos)
	case default
		call wc_error_stop('para-getvalue','cannot change from '//trim(type_name(type))//'  to int')
	end select

end subroutine

subroutine migetvalue(D,name,val)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	integer,intent(inout),allocatable::val(:)
	integer::type,pos

	call D%find(name,type,pos)

	select case (type_name(type))
	case ('int_ary')
		allocate(val(D%int_ary_len(pos)))
		val=D%int_ary_val(:D%int_ary_len(pos),pos)
	case default
		call wc_error_stop('para-getvalue','cannot change from '//trim(type_name(type))//'  to int_ary')
	end select

end subroutine

subroutine dgetvalue(D,name,val)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	real(8),intent(inout)::val
	integer::type,pos

	call D%find(name,type,pos)
	select case (type_name(type))
	case ('integer')
		val=D%int_val(pos)
	case ('double')
		val=D%double_val(pos)
	case ('complex')
		val=D%com_val(pos)
	case default
		call wc_error_stop('para-getvalue','cannot change from '//trim(type_name(type))//'  to real')
	end select

end subroutine

subroutine mdgetvalue(D,name,val)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	real(8),intent(inout),allocatable::val(:)
	integer::type,pos

	call D%find(name,type,pos)
	select case (type_name(type))
	case ('dbl_ary')
		allocate(val(D%dbl_ary_len(pos)))
		val=D%dbl_ary_val(:D%dbl_ary_len(pos),pos)
	case default
		call wc_error_stop('para-getvalue','cannot change from '//trim(type_name(type))//'  to dbl_ary')
	end select

end subroutine

subroutine zgetvalue(D,name,val)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	complex(8),intent(inout)::val
	integer::type,pos

	call D%find(name,type,pos)
	select case (type_name(type))
	case ('integer')
		val=D%int_val(pos)
	case ('double')
		val=D%double_val(pos)
	case ('complex')
		val=D%com_val(pos)
	case default
		call wc_error_stop('para-getvalue','cannot change from '//trim(type_name(type))//'  to complex')
	end select

end subroutine

subroutine agetvalue(D,name,val)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	character(len=*),intent(inout)::val
	integer::type,pos

	call D%find(name,type,pos)

	select case (type_name(type))
	case ('integer')
		val=str(D%int_val(pos))
	case ('double')
		val=str(D%double_val(pos))
	case ('complex')
		val=str(D%com_val(pos))
	case ('character')
		val=D%char_val(pos)
	case ('logical')
		val=str(D%logi_val(pos))
	case ('char_ary')
		val=str(D%char_ary_val(:,pos))
	case default
		write(*,*)type
		call wc_error_stop('para-getvalue','cannot change from '//trim(type_name(type))//'  to char')
	end select
	
end subroutine

subroutine magetvalue(D,name,val)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	character(len=max_char_length),intent(inout),allocatable::val(:)
	integer::type,pos

	call D%find(name,type,pos)

	select case (type_name(type))
	case ('char_ary')
		allocate(val(D%char_ary_len(pos)))
		val=D%char_ary_val(:D%char_ary_len(pos),pos)
	case default
		call wc_error_stop('para-getvalue','cannot change from '//trim(type_name(type))//'  to char_ary')
	end select
	
end subroutine

subroutine lgetvalue(D,name,val)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	logical,intent(inout)::val
	integer::type,pos

	call D%find(name,type,pos)
	select case (type_name(type))
	case ('logical')
		val=D%logi_val(pos)
	case default
		call wc_error_stop('para-getvalue','cannot change from '//trim(type_name(type))//'  to logical')
	end select

end subroutine

subroutine mlgetvalue(D,name,val)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	logical,intent(inout),allocatable::val(:)
	integer::type,pos

	call D%find(name,type,pos)
	select case (type_name(type))
	case ('logi_ary')
		allocate(val(D%logi_ary_len(pos)))
		val=D%logi_ary_val(:D%logi_ary_len(pos),pos)
	case default
		call wc_error_stop('para-getvalue','cannot change from '//trim(type_name(type))//'  to logi_ary')
	end select

end subroutine

subroutine tgetvalue(D,name,val)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::name
	type(tensor),intent(inout)::val
	integer::type,pos

	call D%find(name,type,pos)
	select case (type_name(type))
	case ('tensor')
		val=D%ten_val(pos)
	case default
		call wc_error_stop('para-getvalue','cannot change from '//trim(type_name(type))//'  to tensor')
	end select

end subroutine

subroutine rename(D,name,new_name)

	class(dictionary),intent(inout)::D
	character(len=*),intent(in)::name
	character(len=*),intent(inout)::new_name
	integer::type,pos

	call D%find(name,type,pos)
	D%names(pos,type)=new_name

end subroutine

subroutine append_by_name(D,D2,names)

	class(dictionary),intent(inout)::D
	class(dictionary),intent(in)::D2
	character(len=*),intent(in)::names(:)
	type(dictionary)::out_list
	integer::i,type,pos

	do i=1,size(names)
		call D2%find(names(i),type,pos)
		select case (type_name(type))
		case ('integer')
			call D%insert(names(i),D2%int_val(pos))
		case ('int_ary')
			call D%insert(names(i),D2%int_ary_val(:D2%int_ary_len(pos),pos))
		case ('double')
			call D%insert(names(i),D2%double_val(pos))
		case ('dbl_ary')
			call D%insert(names(i),D2%dbl_ary_val(:D2%dbl_ary_len(pos),pos))
		case ('complex')
			call D%insert(names(i),D2%com_val(pos))
		case ('character')
			call D%insert(names(i),D2%char_val(pos))
		case ('char_ary')
			call D%insert(names(i),D2%char_ary_val(:D2%char_ary_len(pos),pos))
		case ('logical')
			call D%insert(names(i),D2%logi_val(pos))
		case ('logi_ary')
			call D%insert(names(i),D2%logi_ary_val(:D2%logi_ary_len(pos),pos))
		case ('tensor')
			call D%insert(names(i),D2%ten_val(pos))
		end select
	end do

end subroutine

function sub_name(D,names) result(out_list)

	class(dictionary),intent(in)::D
	character(len=*),intent(in)::names(:)
	type(dictionary)::out_list

	if(sum(D%itemcurn)>0) then
		call out_list%append_by_name(D,names)
	end if

end function

subroutine print(D,unit,end_tag_)

	class(dictionary),intent(in)::D
	integer,intent(in),optional::unit
	logical,intent(in),optional::end_tag_
	logical::end_tag
	integer::k,i,type
	character(len=max_char_length+20):: formatl

	end_tag=.true.
	if(present(end_tag_)) end_tag=end_tag_

	if (.not. D%inited) then
		if(present(unit) .and. end_tag) write(unit,*) '/'
		return 
	end if

	do type=1,type_num
		do k=1,D%itemcurn(type)
			formatl=type_abbr(type)
			formatl(4:)=D%names(k,type)
			select case(type_name(type))
			case('integer')
				formatl(20:)=str(D%int_val(k))
			case('double')
				formatl(20:)=str(D%double_val(k))
			case('complex')
				formatl(20:)=str(D%com_val(k))
			case('character')
				formatl(20:)=D%char_val(k)
			case('logical')
				formatl(20:)=str(D%logi_val(k))
			case('tensor')
				formatl(20:)='printed below'
			case('int_ary')
				formatl(20:)=str(D%int_ary_len(k))//' items:'
			case('dbl_ary')
				formatl(20:)=str(D%dbl_ary_len(k))//' items:'
			case('char_ary')
				formatl(20:)=str(D%char_ary_len(k))//' items:'
			case('logi_ary')
				formatl(20:)=str(D%logi_ary_len(k))//' items:'
			end select
			if(present(unit))then
				write(unit,*) trim(formatl)
			else
				call write_message(formatl)
			end if

			select case(type_name(type))
			case('tensor')
				if(present(unit))then
					call D%ten_val(k)%write(unit)
				else
					call D%ten_val(k)%print()
				end if
			case('int_ary')
				do i=1,D%int_ary_len(k)
					formatl=''
					formatl(20:)=str(D%int_ary_val(i,k))
					if(present(unit))then
						write(unit,*) trim(formatl)
					else
						call write_message(formatl)
					end if
				end do
			case('dbl_ary')
				do i=1,D%dbl_ary_len(k)
					formatl=''
					formatl(20:)=str(D%dbl_ary_val(i,k))
					if(present(unit))then
						write(unit,*) trim(formatl)
					else
						call write_message(formatl)
					end if
				end do
			case('char_ary')
				do i=1,D%char_ary_len(k)
					formatl=''
					formatl(20:)=D%char_ary_val(i,k)
					if(present(unit))then
						write(unit,*) trim(formatl)
					else
						call write_message(formatl)
					end if
				end do
			case('logi_ary')
				do i=1,D%logi_ary_len(k)
					formatl=''
					formatl(20:)=str(D%logi_ary_val(i,k))
					if(present(unit))then
						write(unit,*) trim(formatl)
					else
						call write_message(formatl)
					end if
				end do
			end select
		end do
	end do

	if(present(unit) .and. end_tag) write(unit,*) '/'

end subroutine

subroutine read(G,unit)

	class(dictionary),intent(inout)::G
	integer,intent(in)::unit
	character(len=max_char_length)::cur_class
	character(len=10*max_char_length)::line
	character(len=4)::type
	integer::io_stat,len,i,pos

	character(len=max_char_length)::no_use,cur_name
	integer::ival 
	real(8)::dval 
	complex(8)::zval 
	character(len=max_char_length)::aval 
	logical::lval 
	type(tensor)::tval
	integer,allocatable::mival(:)
	real(8),allocatable::mdval(:)
	character(len=max_char_length),allocatable::maval(:)
	logical,allocatable::mlval(:)

	if (.not. G%inited) call G%init()
	call G%clean()

	read(unit,'(A)',IOSTAT=io_stat) line
	do while(.true.)
		if(io_stat/=0) call wc_error_stop('dictionary.read','EOF before identifier "/"')
		line=adjustl(line)
		type=''
		if(len_trim(line)>0) then
			pos=scan(line,' '//achar(9)) ! achar(9) for tab
			type=line(1:pos-1)
		end if
		select case(type)
		case('i')
			read(line(pos:),*) cur_name,ival
			call G%insert(cur_name,ival)
		case('d')
			read(line(pos:),*) cur_name,dval
			call G%insert(cur_name,dval)
		case('z')
			read(line(pos:),*) cur_name,zval
			call G%insert(cur_name,zval)
		case('a')
			read(line(pos:),*) cur_name,aval
			call G%insert(cur_name,aval)
		case('l')
			read(line(pos:),*) cur_name,lval
			call G%insert(cur_name,lval)
		case('t')
			read(line(pos:),*) cur_name
			call tval%read(unit)
			call G%insert(cur_name,tval)
		case('mi')
			read(line(pos:),*)cur_name,len
			if(allocated(mival)) deallocate(mival)
			allocate(mival(len))
			do i=1,len
				read(unit,*,IOSTAT=io_stat) mival(i)
				if(io_stat/=0) call wc_error_stop('dictionary.read','array reading stopped')
			end do
			call G%insert(cur_name,mival)
		case('md')
			read(line(pos:),*)cur_name,len
			if(allocated(mdval)) deallocate(mdval)
			allocate(mdval(len))
			do i=1,len
				read(unit,*,IOSTAT=io_stat) mdval(i)
				if(io_stat/=0) call wc_error_stop('dictionary.read','array reading stopped')
			end do
			call G%insert(cur_name,mdval)
		case('ma')
			read(line(pos:),*)cur_name,len
			if(allocated(maval)) deallocate(maval)
			allocate(maval(len))
			do i=1,len
				read(unit,*,IOSTAT=io_stat) maval(i)
				if(io_stat/=0) call wc_error_stop('dictionary.read','array reading stopped')
			end do
			call G%insert(cur_name,maval)
		case('ml')
			read(line(pos:),*)cur_name,len
			if(allocated(mlval)) deallocate(mlval)
			allocate(mlval(len))
			do i=1,len
				read(unit,*,IOSTAT=io_stat) mlval(i)
				if(io_stat/=0) call wc_error_stop('dictionary.read','array reading stopped')
			end do
			call G%insert(cur_name,mlval)
		case('/')
			exit
		end select

		read(unit,'(A)',IOSTAT=io_stat) line
	end do

end subroutine

subroutine append(P1,P2)

	class(dictionary),intent(inout)::P1
	type(dictionary),intent(in)::P2

	if(sum(P2%itemcurn)>0) then
		call P1%append_by_name(P2,P2%get_names())
	end if

end subroutine

end module