我完全迷失了。
我尝试将两个可选参数传递给fortran中的函数,这两个是未知长度的数组。代码编译得很好,但是当程序运行时,它会在评估PRESENT(arg)函数时崩溃。命令行中没有错误消息,而只是弹出Windows错误通知,并告诉我" main.exe已停止工作" 关于如何解决这个问题的任何想法?
这是代码,我删除了一切不必要的内容。
MODULE types
! Underlying data types: Bra, Ket, and Oper
type bra
complex*8, dimension(:,:), allocatable :: dat
integer*4 :: typ ! = "Bra"
integer*4, dimension(2) :: dims
end type bra
type ket
complex*8, dimension(:,:), allocatable :: dat
integer*4 :: typ ! = "Ket"
integer*4, dimension(2) :: dims
end type ket
type oper
complex*8, dimension(:,:), allocatable :: dat
integer*4 :: typ ! = "Operator"
integer*4, dimension(2) :: dims
end type oper
END MODULE types
MODULE basics
! The types are declared in an extra module, to be imported here
! Otherwise it is not possible to use derived types in procedures
use types
interface operator (*)
! "Quantum" multiplication
procedure otk ! Operator Times Ket O *|B > = |C>
end interface
CONTAINS
! Fock state
function fock(N,M)
! N is the dimension of the underlying array
! M is the number of photons inside
! M=1 is vacuum
integer*4 :: N,M
type(ket) :: fock
! Check is the passed dimensions are okay
if (N<2 .or. M<0 .or. M > N-1) then
print*,'Invalid input while making a fock state'
print*,'N=',N,'M=',M
stop
end if
! Allocate and initilaize with zeros
allocate(fock%dat(N,1))
fock%dat = (0d0,0d0)
! Now actually make the state by replacing a zero with 1
fock%dat(M+1,1) = (1d0,0d0)
! Set type of the object to 'ket'
fock%typ = 2
! Set the dimensions
fock%dims = [N,1]
end function fock
! Identity matrix
function qeye(N)
integer*4 :: N,i
type(oper) :: qeye
! Allocate and initilaize with zeros
allocate(qeye%dat(N,N))
qeye%dat = (0d0,0d0)
! Set diagonal elements to 1
do i = 1,N
qeye%dat(i,i) = (1d0,0d0)
end do
! Set type of the object to 'oper'
qeye%typ = 4
! Set the dimensions
qeye%dims = [N,N]
end function qeye
! Operator Times Ket
function otk(left, right)
type(oper), intent(in) :: left
type(ket), intent(in) :: right
type(ket) :: otk
! If the operator is as wide, as the state is high, do matrix multiplication
if (left%dims(2) == right%dims(1)) then
! Result is a Ket vector again
allocate(otk%dat(left%dims(1),1))
otk%dat = matmul(left%dat,right%dat)
! Also set data type and dimensions of the result
otk%dims = [right%dims(1),1]
otk%typ = 2
return
else
print*,'You are trying to use an operator on a ket of inconsistent dimensions'
print*,left%dims,'and',right%dims
stop
end if
end function otk
end module basics
MODULE RK
! Import modules to work with quantum objects
use types
use basics
contains
subroutine rungekutta(state,HAM,times,results)
! In-/Output:
! Starting state, also final state
type(ket) :: state
! Function delivering time dependent hamiltonian
type(oper), external :: HAM
! Array with times at which to do calculations
real*8, dimension(:) :: times
! Placeholder for the length of a given time step
real*8 :: t_0, t_step
! Optional array of ket states to hold all the intermediate results
type(ket), dimension(:),optional :: results
! Variables for internal calculations
type(ket) :: psi0
! Looping coefficients
integer*8 :: ii
! Start of the calculations
! (The actual Runge-Kutta method is different, but not needed now)
results(1) = state
do ii = 1, size(times)-1
t_0 = times(ii)
t_step = times(ii+1) - times(ii)
psi0 = results(ii)
results(ii+1) = HAM(t_0) * psi0
end do
! Save the last calculated state to the input/output variable
state = results(size(results))
end subroutine rungekutta
end MODULE RK
module dummy
! Import modules to work with quantum objects
use types
use basics
CONTAINS
! Define Hamiltonian function
function testHAM(t, freqs, coefs)
type(oper) :: testHAM
real*8 :: t
! Optional variables is the Hamiltonian is time dependent
real*8, dimension(:), optional :: freqs, coefs
testHAM = qeye(2)
! Variable part
if (.NOT.present(freqs)) then
print*,'gotcha'
end if
end function testHAM
end module dummy
program main
! Import modules to work with quantum objects
use types
use basics
use RK
! Import hamilton definition
use dummy
IMPLICIT NONE
! Define variables
type(ket) :: start, goal
real*8, dimension(:), allocatable :: timesarr
integer*4 :: N,i,M,j,k,l,mm
type(ket), dimension(:), allocatable :: results
! Set number of steps, and the total time
N = 5000
allocate(timesarr(N))
timesarr = [0d0,1d0]
start=fock(2,0)
! Allocate the vector holding the results
allocate(results(N))
results = start
call rungekutta(start,testHAM,timesarr,results)
end program main
我正在使用可选关键字和&#34;结果&#34;数组,以及其他地方,它工作正常。我真的很感激任何帮助,因为我真的没有心情绕过那些东西,因为它会让代码变得更加混乱:))
提前致谢!
答案 0 :(得分:1)
带有可选参数的过程需要一个显式接口,以便在引用过程的任何范围内可以访问过程。
提供的代码不符合此要求。
请注意,该过程引用了两次。
在执行顺序中,第一个引用 - 当testHAM
过程与主程序中调用rungekutta的HAM
伪参数相关联时 - 是可以的 - 显式接口可用(标识符)用于模块过程 - 因此显式接口是自动的。)
但执行顺序中的第二个引用 - 调用HAM
虚拟过程时 - 不行。使用带有external属性的类型声明语句声明伪参数“only”。这不会给程序带来明确的界面。
(根据语言原样 - 我的意见是,如果你必须(或者甚至只是“应该”)使用外部属性,那么你的编码就会表现出糟糕的风格。)
正确的直接方法是使用为伪过程参数提供显式接口的方法 - 可能通过接口块或带有 proc-interface 规范的过程声明语句。
如果虚拟过程的接口所需的相关特性与testHAM
过程的实际接口不匹配(这里假设rungekutta
过程不关心或想要了解可选参数),然后您可能需要使用包装程序或类似方法来转发过程调用。
编辑添加:虽然标准不要求它 - 但期望编译器发出此用法警告是合理的。虽然过程与带有隐式接口的伪过程的可选参数的关联是“合法的”,但是然后无论如何都不可能使用伪过程。这可能值得与您的Fortran处理器供应商讨论。
答案 1 :(得分:0)
MODULE types
! Underlying data types: Bra, Ket, and Oper
type bra
complex*8, dimension(:,:), allocatable :: dat
integer*4 :: typ ! = "Bra"
integer*4, dimension(2) :: dims
end type bra
type ket
complex*8, dimension(:,:), allocatable :: dat
integer*4 :: typ ! = "Ket"
integer*4, dimension(2) :: dims
end type ket
type oper
complex*8, dimension(:,:), allocatable :: dat
integer*4 :: typ ! = "Operator"
integer*4, dimension(2) :: dims
end type oper
END MODULE types
MODULE basics
! The types are declared in an extra module, to be imported here
! Otherwise it is not possible to use derived types in procedures
use types
interface operator (*)
! "Quantum" multiplication
procedure otk ! Operator Times Ket O *|B > = |C>
end interface
CONTAINS
! Fock state
function fock(N,M)
! N is the dimension of the underlying array
! M is the number of photons inside
! M=1 is vacuum
integer*4 :: N,M
type(ket) :: fock
! Check is the passed dimensions are okay
if (N<2 .or. M<0 .or. M > N-1) then
print*,'Invalid input while making a fock state'
print*,'N=',N,'M=',M
stop
end if
! Allocate and initilaize with zeros
allocate(fock%dat(N,1))
fock%dat = (0d0,0d0)
! Now actually make the state by replacing a zero with 1
fock%dat(M+1,1) = (1d0,0d0)
! Set type of the object to 'ket'
fock%typ = 2
! Set the dimensions
fock%dims = [N,1]
end function fock
! Identity matrix
function qeye(N)
integer*4 :: N,i
type(oper) :: qeye
! Allocate and initilaize with zeros
allocate(qeye%dat(N,N))
qeye%dat = (0d0,0d0)
! Set diagonal elements to 1
do i = 1,N
qeye%dat(i,i) = (1d0,0d0)
end do
! Set type of the object to 'oper'
qeye%typ = 4
! Set the dimensions
qeye%dims = [N,N]
end function qeye
! Operator Times Ket
function otk(left, right)
type(oper), intent(in) :: left
type(ket), intent(in) :: right
type(ket) :: otk
! If the operator is as wide, as the state is high, do matrix multiplication
if (left%dims(2) == right%dims(1)) then
! Result is a Ket vector again
allocate(otk%dat(left%dims(1),1))
otk%dat = matmul(left%dat,right%dat)
! Also set data type and dimensions of the result
otk%dims = [right%dims(1),1]
otk%typ = 2
return
else
print*,'You are trying to use an operator on a ket of inconsistent dimensions'
print*,left%dims,'and',right%dims
stop
end if
end function otk
end module basics
MODULE RK
! Import modules to work with quantum objects
use types
use basics
contains
subroutine rungekutta(state,HAM,times,results)
! In-/Output:
! Starting state, also final state
type(ket) :: state
! PeMa: Function delivering time dependent hamiltonian (now a correct interface)
interface
function HAM(t,freqs,coefs)
use types
! type(oper),external :: HAM
! Edit (see comments) :
type(oper) :: HAM
real(8) :: t
real(8), dimension(:),allocatable,optional :: freqs, coefs
end function
end interface
! PeMa: define testing arrays to test the otional arguments:
real(8), dimension(:),allocatable :: a, b
! Array with times at which to do calculations
real*8, dimension(:) :: times
! Placeholder for the length of a given time step
real*8 :: t_0, t_step
! Optional array of ket states to hold all the intermediate results
type(ket), dimension(:),optional :: results
! Variables for internal calculations
type(ket) :: psi0
! Looping coefficients
integer*8 :: ii
! Start of the calculations
! (The actual Runge-Kutta method is different, but not needed now)
!PeMa: my testing arrays
allocate(a(1:2))
allocate(b(1:2))
a=(/1d0,3d0/)
b=(/2d0,4d0/)
results(1) = state
do ii = 1, size(times)-1
t_0 = times(ii)
t_step = times(ii+1) - times(ii)
psi0 = results(ii)
!PeMa: use one of the next to lines and you see in the output that it's working now:
results(ii+1) = HAM(t_0,a,b) * psi0
!results(ii+1) = HAM(t_0) * psi0
end do
! Save the last calculated state to the input/output variable
state = results(size(results))
end subroutine rungekutta
end MODULE RK
module dummy
! Import modules to work with quantum objects
use types
use basics
CONTAINS
! Define Hamiltonian function
function testHAM(t, freqs, coefs)
type(oper) :: testHAM
real*8 :: t
! PeMa: Optional variables is the Hamiltonian is time dependent (I'm using allocatable to be sure about the 'position labeling' ... sorry can't say it better)
real*8, dimension(:), allocatable,optional :: freqs, coefs
testHAM = qeye(2)
! Variable part
!PeMa: I inserted some 'else' to test both possibilities:
if (.NOT.present(freqs)) then
print*,'gotcha'
else
print*,freqs,coefs
end if
end function testHAM
end module dummy
program main
! Import modules to work with quantum objects
use types
use basics
use RK
! Import hamilton definition
use dummy
IMPLICIT NONE
! Define variables
type(ket) :: start, goal
real*8, dimension(:), allocatable :: timesarr
integer*4 :: N,i,M,j,k,l,mm
type(ket), dimension(:), allocatable :: results
! Set number of steps, and the total time (PeMa: 5 is enough ;-) )
N = 5
allocate(timesarr(N))
timesarr = [0d0,1d0]
start=fock(2,0)
! Allocate the vector holding the results
allocate(results(N))
results = start
call rungekutta(start,testHAM,timesarr,results)
end program main
(希望)我改变了一些东西的所有要点都标有'PeMa'。现在它不仅在编译(可能在任何地方),而且实际上正在做它实际应该做的事情。您可以通过在rungecutta中使用不同的函数调用来命令输入和输出两行来测试它。 希望我能帮助你!最好