Fortran Coder

查看: 538|回复: 11

[子程序] 数组实参传递到虚参出错

[复制链接]

4

帖子

1

主题

0

精华

新人

F 币
23 元
贡献
12 点
发表于 2018-6-26 09:00:49 | 显示全部楼层 |阅读模式
大家好,我修改的程序在编译时没有报错,运行时通过print *,语句发现有一个数组传递到subroutine的虚参后发生很诡异的问题:主文件为f90,涉及错误的代码复制如下:
! ... Run plume model
             CALL lineplu_v1(iyr,rjulday,wselev,dfelev,kms,dfLgth, &
                            lambnot,salamb,patm, diamm, plmdim, &
                            qscfm, frconot,                     & ! boundary conditions
                            ksrc, hcell,                        &
                            zamb (1:kms),                       &
                            Tamb (1:kms),                       &
                            DOamb(1:kms),                       &
                            elevt, qwt , tplumt, comgpt,        &
                            qwd(1:ksrc), bwd(1:ksrc), ktop, oteff)

! ....Run double plume model
             CALL doubplu_v1(iyr,rjulday,wselev,dfelev,kms,dfLgth, &
                               lambnot,salamb,patm, diamm, plmdim, &
                               qscfm, frconot,                     & ! boundary conditions
                               ksrc, hcell,                        &
                               zamb (1:kms),                       &
                               Tamb (1:kms),                       &
                               DOamb(1:kms),                       &
                               elevt, qwt , tplumt, comgpt,        &
                               qwd(1:ksrc), bwd(1:ksrc), kob, oteff)


其中,lineplu_v1是保存在另一个f77文件下的subroutine;我根据它为原型修改后的subroutine叫做doubplu_v1,保存在同一个f77文件下。

运行lineplu_v1时,zamb (1:kms)这个数组的传递正确,如果跳过lineplu_v1,运行doubplu_v1, zamb (1:kms)的值变得很奇怪,我在doubplu_v1的函数开头(变量声明以后位置)写了print *, locat (1:layers), (对应的虚参)结果本来应该是从-0.25到20.75之间的数字居然全都变成9.9290E-318这样大小的值。

以下是两个subroutine的声明部分:

SUBROUTINE DOUBPLU_v1(YEAR,JULDAY,WSEL,DIFFEL,LAYERS,LDIFF,LAMBNOT,
     +SALAMB,PATM,DIAMM,LAKE,QSCFM,FRCONOT,LAYDIFF,HCELL,LOCAT,TE,CO2M,
     +ELEVOB,QWOB,TPLUMEOB,COMGPOB,QWD,BWD,LAYOB,OTEFF)

C----------------------------
SUBROUTINE LINEPLU_v1(YEAR,JULDAY,WSEL,DIFFEL,LAYERS,LDIFF,LAMBNOT,
     +SALAMB,PATM,DIAMM,LAKE,QSCFM,FRCONOT,LAYDIFF,HCELL,LOCAT,TE,CO2M,
     +ELEVT,QWT,TPLUMET,COMGPT,QWD,BWD,LAYTOP,OTEFF)



可能是我接触fortran时间太短,自己尝试debug了几天,摸不着头脑.....如果有好心的大神有想法的话烦请指点我一下。我现在一边向人求助一边已经打算在subroutine里手动输入 locat(1:layers)的值了......

如果您阅读到这里,非常感谢。

回复

使用道具 举报

465

帖子

3

主题

0

精华

大宗师

F 币
3150 元
贡献
1867 点

水王勋章元老勋章热心勋章

发表于 2018-6-26 09:36:53 | 显示全部楼层
数组zamb没有初始化或赋值

4

帖子

1

主题

0

精华

新人

F 币
23 元
贡献
12 点
 楼主| 发表于 2018-6-26 13:22:52 | 显示全部楼层
pasuka 发表于 2018-6-26 09:36
数组zamb没有初始化或赋值

谢谢您的回答,但是在主程序里有赋值语句,而且我在call subroutine前方插入print *, zamb (1:kms),输出的值是正确的;
而且如果zamb没有正确赋值,不可能call lineplu_v1的时候,参数传递是正确的啊。(我在lineplu_v1变量声明下方插入print*, locat(1:layers),输出值正确,和zamb (1:kms)完全一样。

我在想subroutine里声明变量的时候是否有什么因素会造成参数传递错误?

465

帖子

3

主题

0

精华

大宗师

F 币
3150 元
贡献
1867 点

水王勋章元老勋章热心勋章

发表于 2018-6-26 14:14:07 | 显示全部楼层
藍原なみだ 发表于 2018-6-26 13:22
谢谢您的回答,但是在主程序里有赋值语句,而且我在call subroutine前方插入print *, zamb (1:kms),输出 ...

函数的输入参数顺序混淆了?
一个函数有超过二位数的输入值,看走眼也是完全有可能的

91

帖子

3

主题

0

精华

版主

F 币
450 元
贡献
275 点

贡献勋章管理勋章帅哥勋章元老勋章星光勋章规矩勋章

发表于 2018-6-26 15:10:43 | 显示全部楼层
subroutine的声明部分,                               請列出各"虛參"的type/dimension宣告
CALL lineplu_v1(...). CALL doubplu_v1(...), 請列出各"實參"的type/dimension宣告

4

帖子

1

主题

0

精华

新人

F 币
23 元
贡献
12 点
 楼主| 发表于 2018-6-27 19:19:51 | 显示全部楼层
本帖最后由 藍原なみだ 于 2018-6-27 19:23 编辑
chiangtp 发表于 2018-6-26 15:10
subroutine的声明部分,                               請列出各"虛參"的type/dimension宣告
CALL lineplu_ ...

subroutine lineplu_v1的宣告:

REAL*8 ALPHA,AREA,B,CO2,COMG,CN2,CNMG,DS,DZ,DENSEA,DENSEP,DENSEW,
     +DIAMM,E,FDO,FDN,FRACO,FRACN,FSAL,FTEMP,FGO,FGN,G,GAMMA,HO2,HN2,
     +KOLN,KOLO,L,LAMBDA,MOMENT,N,PI,PO,PN,PSTD,PZ,QSCFM,QSCMS,QW,QGAS,
     +RB,RGAS,SALAMB,SALPLU,TAMB,TPLUME,TSTD,V,VB,VBUB,VG,VGUESS,
     +YO2,YN2,Z,AA,BB,CC,BNOT,LNOT,ELEV,DT,TE(1000),XLOC,DEPTH,
     +CO2M(1000),LOCAT(1000),DOAMB,COMGP,CNMGP,WSEL,PATM,SAL(1000),
     +DIFFEL,GROSSMT,FGONOT,DNAMB,DMPR,TAVG,SUMTEMP,SUMSAL,
     +LAMBNOT,FRCONOT,RBNOT,H,DYDX(8),Y(8),YOUT(8),
     +DENSE20,OTEFF,FRNOT,VDIFF,FR,BUOY,DCO2,QGFRAC,LDIFF,TDS(1000),
     +JDAY,EL(70),DELTAC,COMGNOT,ELEVT,QWT,TPLUMET,COMGPT,QWD(500),
     +PWD(500),BWD(500),AWD(500),
     +HWITH,HCELL,JULDAY,BTOP,BEQUIV
      INTEGER II,IJ,IK,IN,JJ,LL,NEQN,NN,MI,JK,JL,LAKE,LAYTOP
     +LAYERS,KM,KN,KO,KP,ROWS,KQ,KR,KU,KV,KW,KX,KY,KZ,KS,LAYDIFF,YEAR
      INTEGER NELS

subroutine doubplu_v1的宣告:

REAL*8 ALPHA,ALPHAA,ALPHAI,ALPHAO,AREA,B,BO,BH(1000),CO2,CO2H(1000),COMG,CN2,
     +CN2H(1000),CNMG,DS,DZ,DENSEA,DENSEAH(1000),DENSEP,DENSEW,DENSEWH(1000),
     +DIAMM,E,EH(1000),EO,EOH(1000),FDO,FDOO,FDN,FDNO,FRACO,FRACN,FSAL,FSALO,
     +FTEMP,FTEMPO,FGO,FGOO,FGN,FGNO,G,GAMMA,HO2,HO2H(ID),HN2,HN2H(ID),
     +KOLN,KOLNH(1000),KOLO,KOLOH(1000),L,LAMBDA,MOMENT,MOMENTO,N,PI,PO,
     +POH(1000),PN,PNH(1000),PSTD,PZ,QSCFM,QSCMS,QW,QWO,QGAS,
     +RB,RB(1000),RGAS,SALAMB,SALPLU,SALPLUH(1000),SALPLUO,SALPLUOH(1000),TAMB,
     +TAMBH(1000),TPLUME,TPLUMEH(1000),TPLUMEO,TPLUMEOH(1000),TSTD,
     +V,VH(1000),VI,VO,VOH(1000),VB,VBH(1000),VBUB,VG,VGUESS,VGUESSO,
     +YO2,YN2,Z,AA,BB,CC,BNOT,LNOT,ELEV,DT,TE(1000),XLOC,DEPTH,
     +CO2M,LOCAT(1000),DOAMB,
     +COMGP,COMGPH(1000),CNMGP,CNMGPH(1000),WSEL,PATM,SAL(1000),
     +DIFFEL,GROSSMT,FGONOT,DNAMB,DMPR,TAVG,SUMTEMP,SUMSAL,
     +LAMBNOT,FRCONOT,RBNOT,H,DYDX(8),Y(8),YOUT(8),
     +DENSE20,OTEFF,FRNOT,FRNOTO,VDIFF,FR,BUOY,DCO2,QGFRAC,LDIFF,TDS(1000),
     +JDAY,EL(70),DELTAC,COMGNOT,ELEVT,ELEVOB,QWT,QWOB,TPLUMET,TPLUMEOB,
     +COMGPT,COMGPOB,QWD(500),PWD(500),BWD(500),AWD(500),
     +HWITH,HCELL,JULDAY,BTOP,BOB,BEQUIV
      INTEGER II,IJ,IK,IN,JJ,LL,NEQN,NN,MI,JK,JL,LAKE,LAYTOP,LAYOB,
     +LAYERS,KM,KN,KO,KP,ROWS,KQ,KR,KU,KV,KW,KX,KY,KZ,KS,LAYDIFF,YEAR
      INTEGER NELS,ID,IDM

各个实参的宣告:INTEGER :: iyr, imon, iday, ihr
                           INTEGER :: im, im1, i1, jm, jm1, j1, km, km1, k1, ndx, ndy, ndz, nts, &
            & ndim, maxnz, nw, inw, ibdwd, ifirst, ilast, jfirst, jlast
                           REAL(8) :: wselev, dfelev, dflgth, hcell, rjulday, lambnot, diamm
                           REAL(8) :: elevt, qwt, tplumt, comgpt, tplum0, comgp0, qscfm, frconot
                           REAL(8), DIMENSION (1:km1) :: zamb, Tamb, DOamb ! B.C.
                           REAL(8), DIMENSION (1:km1) :: qwd               ! Outflow rate
                           REAL(8), DIMENSION (1:km1) :: bwd               ! Radius of circular plume
                           REAL*8 :: oteff
                           INTEGER :: nn, inn, i, j, k, kk, l, k1s, kms, nwl, ktop, kob, ksrc, plmdim, itr

我今天尝试强制把locat(1:layers)的正确值在subroutine里赋值,结果运行程序还是出现severe (174) segmentation fault。网上查了一下,可能是数组太大了,于是设定了unlimited stack,并且编译语句后面加上 -heap-arrays,但没有用...参数传递仍然不正确。
                           

91

帖子

3

主题

0

精华

版主

F 币
450 元
贡献
275 点

贡献勋章管理勋章帅哥勋章元老勋章星光勋章规矩勋章

发表于 2018-6-27 20:28:26 | 显示全部楼层
藍原なみだ 发表于 2018-6-27 19:19
subroutine lineplu_v1的宣告:

REAL*8 ALPHA,AREA,B,CO2,COMG,CN2,CNMG,DS,DZ,DENSEA,DENSEP,DENSEW,

1. REAL(8) 是 REAL(KIND=8),  REAL*8 是 8-byte REAL, 兩者不一定相同 (compiler dependent)
    如果有問題, compile-time 應該就知道, 所以就不是這個問題
    建議你通通改為 REAL*8, 或是
    INTEGER, PARAMETER :: r8=SELECTED_REAL_KIND(P=15)
    REAL(KIND=r8) :: ...

2. 請問你的 compiler ?

3. 請告知 完整的 SUBROUTINE title
   SUBROUTIEN doubplu_v1(...)
   SUBROUTINE lineplu_v1(...)

4. 請先自己檢查 "虛參"與"實參"的對應 是否一致

5. ksrc=?, km1=?
    REAL(8), DIMENSION (1:km1) :: qwd, bwd
    CALL lineplu_v1(..., qwd(1:ksrc), bwd(1:ksrc), ...)

91

帖子

3

主题

0

精华

版主

F 币
450 元
贡献
275 点

贡献勋章管理勋章帅哥勋章元老勋章星光勋章规矩勋章

发表于 2018-6-27 21:03:25 | 显示全部楼层
chiangtp 发表于 2018-6-27 20:28
1. REAL(8) 是 REAL(KIND=8),  REAL*8 是 8-byte REAL, 兩者不一定相同 (compiler dependent)
    如果有 ...

1. 虛參CO2M有問題,   對應的實參是 DOamb(1:kms)
in SUBROUTINE DOUBPLU_v1,  REAL*8 :: CO2M
in SUBROUTINE LINEPLU_v1,     REAL*8 :: CO2M(1000)

2. 實參 salamb 與 patm 的 type?

3. runtime時, 請確認: km1=1000, krsc=500

91

帖子

3

主题

0

精华

版主

F 币
450 元
贡献
275 点

贡献勋章管理勋章帅哥勋章元老勋章星光勋章规矩勋章

发表于 2018-6-27 21:08:12 | 显示全部楼层
4. 實參: CALL ABC(..., zamb (1:kms), Tamb (1:kms), DOamb(1:kms), ..., qwd(1:ksrc), bwd(1:ksrc), ...), array-setction的用法, 沒有必要
   --->  CALL ABC(..., zamb, Tamb, DOamb, ..., qwd, bwd, ...)

91

帖子

3

主题

0

精华

版主

F 币
450 元
贡献
275 点

贡献勋章管理勋章帅哥勋章元老勋章星光勋章规矩勋章

发表于 2018-6-27 21:17:45 | 显示全部楼层
應該就是錯在這裡: in SUBROUTINE DOUBPLU_v1
REAL*8 :: CO2M   --->  REAL*8 :: CO2M(1000)
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

QQ|捐赠本站|Archiver|关于我们 About Us|群聊|Fcode

GMT+8, 2018-11-16 21:46

Powered by Discuz! X3.2

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表