Fortran 中 Error: Rank mismatch...... (scalar and rank-1)该怎么解决

本文介绍使用Fortran语言处理NetCDF文件时遇到的Rankmismatch错误及其解决方法。通过调整编译参数或代码实现,确保高版本编译器下的程序兼容性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在学习如何用Fortran语言读写netcdf文件。在学习过程中遇到了一大堆问题,特此记录。

问题一:在使用 gfortran 对 fortran代码编译时总是提示 Rank mismatch… (scalar and rank-1) 的错误信息。搞了好久终于搞定了。

相似问题的截图可见这个提问链接https://ask.csdn.net/questions/1093237
在这里插入图片描述

解决小伙伴问题的方法如下:
方法1. 使用gfortan编译时,加入-fallow-argument-mismatch 参数解决 Rank mismatch 编译错误。 如下:gfortran -g -fallow-argument-mismatch ReadAndWriteNC.f90 -I/usr/local/include -L/usr/local/bin -lnetcdf -o ReadAndWriteNC
方法2. 在你的代码中进行修改。使用 dim1pass(1) 替换 135 行中 status=nf_def_var(ncid,‘longitude’,nf_real,1,nlon1id,nlongit1id) 的nlon1id。同理使用dim1pass(2) 替换nlat1id;dim1pass(3)替换ndep1id等

造成这种问题出现的原因,可能与F77和F90参数传递时的要求不一样有关。低版本的编译器中对参数要求较低,但在高版本的编译器中,你传递的参数类型不一致时编译器会报错。我自己理解的,不对之处,希望大神批评指正!
看到了官方网站给出导致该问题出现的原因及解决方案,跟我给出的方案原理一致。重新在这里补充下。希望对你们有用。https://gcc.gnu.org/gcc-10/porting_to.html
大概意思就是:发生编译错误的位置,其参数需要传递的是数组,而你传递的是标量。这样高版本的编译器是不允许的,因此就会提示编译错误。我们可以通过方法一的方式将该错误降为警告提示,从而顺利编译。或者通过将标量转为一个数组来消除错误。

太懒了。就不写我运行代码的错误案例了。直接写我改好的得了。注释里写的应该比较清楚了。

program ReadAndWriteNC
    implicit none
    include "netcdf.inc"

    INTEGER :: STATUS, &    !状态码 用于检查错误
               ncID         !nc文件的ID

    ! 经、纬度、时间以及变量的ID           
    INTEGER :: latVarID,  & !
               lonVarID,  & !
               timeVarID, &
               ncVarID

    ! 经、纬度、时间等维度的ID
    INTEGER :: latDimID, &
               lonDimID, &
               timeDimID
    ! 变量的维度(包括经、纬度、时间、level、海拔等等)
    INTEGER :: ncVarDims(3)

    INTEGER :: i, j, t
    
    INTEGER, PARAMETER :: nlat=180, nlon=360, ntime=12
    ! 定义储存经、纬度、时间以及变量的数值的向量、矩阵或者数组
    REAL, DIMENSION(nlon) :: lonVarValue
    REAL, DIMENSION(nlat) :: latVarValue
    REAL, DIMENSION(ntime) :: timeVarValue
    REAL, DIMENSION(nlon, nlat, ntime) :: tmp
  
    CHARACTER*9, PARAMETER :: fileName = "ncFile.nc"
    
    print*, '开始运行!'
    
    ! 创建nc文件
    STATUS = NF_CREATE(TRIM(fileName), 0, ncID)
    IF (STATUS .NE. NF_NOERR) CALL CHECK(STATUS)

    ! ! 定义经度、纬度和时间维度
    ! NF_DEF_DIM (INTEGER NCID, CHARACTER*(*) NAME, INTEGER LEN, INTEGER dimid)
    STATUS = NF_DEF_DIM(ncID, 'lon', nlon, lonDimID)
    IF (STATUS .NE. NF_NOERR) CALL CHECK(STATUS)
    
    STATUS = NF_DEF_DIM(ncID, 'lat', nlat, latDimID)
    IF (STATUS .NE. NF_NOERR) CALL CHECK(STATUS)
    
    STATUS = NF_DEF_DIM(ncID, 'time', ntime, timeDimID) ! 用NF_UNLIMITED替换LEN(ntime)表示无限维
    IF (STATUS .NE. NF_NOERR) CALL CHECK(STATUS)
      
    ! ! 定义经度、纬度和时间变量 并 写入相关属性
    !  NF_DEF_VAR(INTEGER NCID, CHARACTER*(*) NAME, INTEGER XTYPE, INTEGER NVDIMS, INTEGER VDIMS(*), INTEGER varid)
    ! 并 写入相关属性
    
    ! ncVarDims(1) = lonDimID  
    ! ncVarDims(2) = latDimID
    ! ncVarDims(3) = timeDimID
    ! 与以下代码 ncVarDims = (/ lonDimID, latDimID, timeDimID /) 相同
    ncVarDims = (/ lonDimID, latDimID, timeDimID /)
    ! !!!!!!! 特别注意 !!!!!!!!
    ! 如果直接将lonDimID填入下面ncVarDims(1)的位置,高版本的gfortran会提示 Rank mismatch 编译错误
    ! 也可以在编译时加入-fallow-argument-mismatch 解决 Rank mismatch 编译错误的问题 如下:
    ! gfortran -g -fallow-argument-mismatch ReadAndWriteNC.f90 -I/usr/local/include -L/usr/local/bin -lnetcdf -o
    ! 导致问题的原因可能在于F77和F90参数接口的问题
    CALL CHECK(nf_def_var(ncID, "lon", NF_FLOAT, 1, ncVarDims(1), lonVarID))   ! ncVarDims(1) = lonDimID
    CALL CHECK(nf_put_att_text(ncID, lonVarID, "long_name", 9,"longitude"))
    CALL CHECK(nf_put_att_text(ncID, lonVarID, "units", 12, "degrees_east"))

    CALL CHECK(nf_def_var(ncID, "lat", NF_FLOAT, 1, ncVarDims(2), latVarID))   ! ncVarDims(2) = latDimID
    CALL CHECK(nf_put_att_text(ncID, latVarID, "long_name", 8,"latitude"))
    CALL CHECK(nf_put_att_text(ncID, latVarID, "units", 13, "degrees_north"))

    CALL CHECK(nf_def_var(ncID, "time", NF_FLOAT, 1, ncVarDims(3), timeVarID)) ! ncVarDims(3) = timeDimID
    CALL CHECK(nf_put_att_text(ncID, timeVarID, "long_name", 22,"month since 2010-01-01"))
    CALL CHECK(nf_put_att_text(ncID, timeVarID, "units", 5, "month"))
    
    STATUS = NF_DEF_VAR (ncID, 'tmp', NF_FLOAT, 3, ncVarDims, ncVarID)         ! ncVarDims = (/ lonDimID, latDimID, timeDimID /)
    IF (STATUS .NE. NF_NOERR) CALL CHECK(STATUS)
    CALL CHECK(nf_put_att_text(ncID, ncVarID, "long_name", 20, "temperature of China"))
    CALL CHECK(nf_put_att_text(ncID, ncVarID, "units", 8, "degree_C"))
      
    ! 添加全局属性
    CALL CHECK(nf_put_att_text(ncID, nf_global, "Source", 23, "Created by ZhangDaJiang"))
    
    ! 结束定义模式
    CALL CHECK(nf_enddef(ncID))
    
    ! 将经度、纬度、时间以及数据变量的数值放入定义好的变量中      
    ! 经度值
    do i = 1, 360
      lonVarValue(i) = -180.0+(i-1.0)*1.0
    end do
    ! 维度值
    do j = 1, 180
      latVarValue(j) = -90.0+(j-1.0)*1.0
    end do
    ! 时间值
    do t = 1, 12
      timeVarValue(t) = t*1.0
    end do
    ! 变量值
    do t = 1, 12
      do i = 1, 360
        do j = 1, 180
          tmp(i,j,t)=5.0*t
        end do
      end do
    end do

    ! 将经度、纬度、时间以及数据变量的数值放入定义好的变量中
    CALL CHECK(nf_put_var_real(ncID, lonVarID, lonVarValue))
    CALL CHECK(nf_put_var_real(ncID, latVarID, latVarValue))
    CALL CHECK(nf_put_var_real(ncID, timeVarID, timeVarValue))
    CALL CHECK(nf_put_var_real(ncID, ncVarID, tmp))

    ! 关闭文件
    CALL CHECK(nf_close(ncid))
    print*, '运行完毕!'
    
    contains
    subroutine CHECK(STATUS)
    INTEGER, intent (in) :: STATUS
      if  (STATUS .NE. nf_noerr) then ! nf_noerr=0 表示没有错误
        print *, nf_strerror(STATUS)
        stop 'stopped'
      endif
    end subroutine CHECK
    ! -----
      
  end program ReadAndWriteNC
  
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值