Fortran的数组动态大小,容易R函数序列() [英] Fortran array with dynamic size, as easy the R function seq()

查看:277
本文介绍了Fortran的数组动态大小,容易R函数序列()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想编写Fortran code,像R函数序列()的作品。例如:

  X<  - 序列(0,1,0.1)

会给矢量

  X<  -  C(0,0.1,0.2,...,1)

我将通过仅改变在SEQ第二个参数运行几个模拟在其上序列的长度将发生变化,R中这是很容易完成的,()。我试图做这样的事情Fortran中有动态数组和功能分配给动态改变数组的大小。这至今还没有工作,导致误差

 计划接收信号SIGSEGV:段错误 - 无效的内存引用。回溯跟踪此错误:
#0 0x2B371ED7C7D7
#1 0x2B371ED7CDDE
#2 0x2B371F3B8FEF
#3 0x401BE9在MAIN__在test3D.f90:?
分段错误(核心转储)

所以我想知道是否有模仿R函数序列()Fortran中的行为的简单方法。

有关进一步的参考见下文

程序

 程序ffl第
隐无
整数参数:: N = 2 ** 12
整数::男,J,L,O,NUM,R,POSI
实(KIND = 8),尺寸(N)::结果
实(KIND = 8):: DT,DK,DP,DTT,laenge,基底,periode,C
实(KIND = 8),尺寸(N,N)::健身,k_opt
实(种类= 8):: T0,T1,T2,T3
实(KIND = 8),尺寸(:),可分配::Ť
实(KIND = 8),尺寸(N):: K,P,TT1
实(KIND = 8),尺寸(6):: x_new,资源,Q0
实(KIND = 8),尺寸(6):: K1,K2,K3,K4
实(KIND = 8):: TS = 0.0
实(KIND = 8):: KS = 0.0,克= 1.0
实(KIND = 8):: PS = 0.1,PE = 40.0
实(KIND = 8):: TTS = 0.0,TTE = 1.0
实(KIND = 8),尺寸(6):: U0,F1,F2,F3,U1
外部::衍生物!计算矢量
DK =(KE-KS)/实(N)!计算分辨率
DP =(PE-PS)/实(N)!计算分辨率
DTT =(TTE-TTS)/实(N)!计算分辨率
K(1)= KS!对于k第一个值= 0.0
P(1)= PS!对于p第一个值= 0.001
TT1(1)= TTS!对于TTS = 0.0第一个值NUM = 10做M = 1,N
    K(M)= K(M-1)+ DK!设置分辨率DT基底前pression矢量
    TT1(M)= TT1(M-1)+ DTT
做到底做M = 1,N
    ρ(M)= PS + 0.1
做到底做M = 1,N
    periode = P(米)    做J = 1,N
    laenge = TT1(J)        做L = 1,N
        基底= K(L)            C = NUM​​ * periode!计算模拟的长度
            DT =(C-TS)/实(N)!计算时间分辨率
            R = 1
            T(1)= TS!第一时间值设定为T1 = 0            分配(T(1))!初始化数组维            做一段时间(TS + DT< c)
                T(R)= TS
                TS = TS + DT
                R = R + 1个
                调用resize_array
            做到底            !初始条件
            Q0(1)= 0! X
            Q0(2)=基础! ÿ
            Q0(3)= 0! ž
            Q0(4)= 0!一个
            Q0(5)= 1! b
            Q0(6)= 0! W¯¯            x_new = Q0!设置初始条件
            !解决在使用一个四阶龙格 - 库塔法模型
            做O = 1,N
                调用衍生物(基底,periode,laenge,叔(升),x_new,K1)                T1 = T(O)+ DT / 2
                F1 = x_new +(DT * K1)/ 2
                调用衍生物(基底,periode,laenge,T1,F1,K2)                T2 = T(O)+ DT / 2
                F2 = x_new +(DT * K2)/ 2
                调用衍生物(基底,periode,laenge,T2,F2,K3)                T3 = T(O)+ DT
                F3 = x_new +(DT * K3)/ 2
                调用衍生物(基底,periode,laenge,T3,F3,K4)                RES = x_new +(DT *(K1 + 2 * K2 + 2 * K3 + K4))/ 6
                如果(RES(2)LT;基),那么
                    RES(2)=基础
                万一                结果(N)=水库(6)            做到底
         健身(J,L)= MAXVAL(结果)/ C
         做到底
    写(*,*)健身
    !POSI = MAXLOC(健身(:,J))
    !k_opt(M,J)= K(POSI)!输入该值到最佳K矩阵
    做到底
做到底
!写(*,*)k_opt
!回k_opt包含!子程序增加了阵列的由1的大小
子程序resize_array
真实的,尺寸(:),可分配:: tmp_arr
整数::新新=尺寸(T)+ 1分配(tmp_arr(新))
tmp_arr(1:新的)= T
DEALLOCATE(T)分配(T(大小(tmp_arr)))
T = tmp_arr结束子程序resize_array
最终方案ffl第


解决方案

Fortran 2003的分配后,可分配数组有(重新)分配,程序

 程序的Xgrid
隐无
真正的,可分配:: X(:)
整数:: I,N
做N = 5,10,5
   X = 0.1 * [(I,I = 0,n)的]
   写(*,('X =',100(1X,F0.1)))x
做到底
最终方案的Xgrid

与gfortran 4.8.0编译

,显示一个Fortran单行相当于SEQ(),使输出

X = 0.0 .1 .2 .3 .4 0.5

X = 0.0 .1 .2 .3 .4 0.5 0.6 0.7 0.8 0.9 1.0

I would like to write Fortran code that works like the R function seq(). E.g.:

x <- seq(0,1,0.1)

will give the vector

x <- c(0, 0.1, 0.2, ..., 1)

I will run several simulations over which the length of the sequence will change, in R this is easily done, by just varying the second argument in seq(). I have tried to do something like this in Fortran with dynamical arrays and the function ALLOCATE to dynamically change the size of the array. This has not worked so far and lead to the error

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x2B371ED7C7D7
#1  0x2B371ED7CDDE
#2  0x2B371F3B8FEF
#3  0x401BE9 in MAIN__ at test3D.f90:?
Segmentation fault (core dumped)

so I was wondering whether there is an easy way to mimic the behaviour of the R function seq() in Fortran.

For further reference see the program below

program ffl
implicit none
integer, parameter           :: n = 2**12                  
integer                      :: m,j,l,o,num,r,posi         
real(kind=8), dimension(n)   :: results 
real(kind=8)                 :: dt,dk,dp, dtt, laenge, basal, periode,c      
real(kind=8), dimension(n,n) :: fitness, k_opt  
real(kind=8)                 :: t0,t1,t2,t3      
real(kind=8), dimension(:),allocatable    :: t   
real(kind=8), dimension(n)   :: k,p, tt1  
real(kind=8), dimension(6)   :: x_new, res, q0 
real(kind=8), dimension(6)   :: k1,k2,k3,k4    
real(kind=8)                 :: ts = 0.0    
real(kind=8)                 :: ks = 0.0, ke = 1.0  
real(kind=8)                 :: ps = 0.1, pe = 40.0  
real(kind=8)                 :: tts = 0.0, tte = 1.0  
real(kind=8), dimension(6)   :: u0,f1,f2,f3,u1    
external                     :: derivate 

! computing the vectors 
dk=(ke-ks)/real(n)    ! calculating resolution
dp=(pe-ps)/real(n)    ! calculating resolution
dtt=(tte-tts)/real(n) ! calculating resolution
k(1) = ks             ! first value for k = 0.0
p(1) = ps             ! first value for p = 0.001
tt1(1) = tts          ! first value for tts = 0.0

num = 10

do m = 1,n         
    k(m) = k(m-1)+dk ! setting the basal expression vector with resolution dt 
    tt1(m) = tt1(m-1)+dtt
end do

do m = 1,n
    p(m) = ps + 0.1
end do

do m = 1,n
    periode = p(m)

    do j = 1,n
    laenge = tt1(j)

        do l = 1,n
        basal = k(l)

            c = num * periode    ! calculating the length of the simulation
            dt=(c-ts)/real(n)    ! calculating time resolution
            r = 1
            t(1) = ts            ! setting first time value to t1 = 0

            allocate(t(1))       ! Initialize array dimension

            do while (ts + dt < c)
                t(r) = ts
                ts = ts + dt
                r = r + 1
                call resize_array
            end do

            ! initial conditions
            q0(1) = 0     ! x
            q0(2) = basal ! y
            q0(3) = 0     ! z
            q0(4) = 0     ! a
            q0(5) = 1     ! b
            q0(6) = 0     ! w 

            x_new = q0 ! set initial conditions
            ! Solving the model using a 4th order Runge-Kutta method
            do o = 1,n
                call derivate(basal,periode,laenge,t(l),x_new,k1)  

                t1 = t(o) + dt/2      
                f1 = x_new + (dt*k1)/2
                call derivate(basal,periode,laenge,t1,f1,k2)      

                t2 = t(o) + dt/2      
                f2 = x_new + (dt*k2)/2
                call derivate(basal,periode,laenge,t2,f2,k3)      

                t3 = t(o) + dt
                f3 = x_new + (dt*k3)/2
                call derivate(basal,periode,laenge,t3,f3,k4)      

                res = x_new + (dt*(k1+2*k2+2*k3+k4))/6
                if (res(2) < basal) then
                    res(2) = basal
                endif

                results(n) = res(6)

            end do
         fitness(j,l) = maxval(results)/c 
         end do
    write(*,*) fitness   
    !posi = maxloc(fitness(:,j)) 
    !k_opt(m,j) = k(posi)      ! inputting that value into the optimal k matrix
    end do
end do
!write(*,*) k_opt
!return k_opt

contains

! The subroutine increases the size of the array by 1
subroutine resize_array
real,dimension(:),allocatable :: tmp_arr
integer :: new

new = size(t) + 1

allocate(tmp_arr(new))
tmp_arr(1:new)=t
deallocate(t)

allocate(t(size(tmp_arr)))
t=tmp_arr

end subroutine resize_array   
end program ffl

解决方案

Fortran 2003 has (re-)allocation upon assignment for allocatable arrays, and the program

program xgrid
implicit none
real, allocatable :: x(:)
integer           :: i,n
do n=5,10,5
   x = 0.1*[(i,i=0,n)]
   write (*,"('x =',100(1x,f0.1))") x
end do
end program xgrid

compiled with gfortran 4.8.0, shows a Fortran one-liner equivalent to seq(), giving output

x = .0 .1 .2 .3 .4 .5

x = .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1.0

这篇关于Fortran的数组动态大小,容易R函数序列()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆