时间数组超出建模界限?

时间:2015-06-03 18:32:40

标签: arrays fortran bounds

这些天我正试图用新的气象数据运行我的气候模型(以netcdf格式而不是旧的cray格式给出)。该模型编译顺利,但是当模拟时间时,模型在第一天运行良好,但在模拟的第二天停止,无论我使用什么开始日期,始终在同一时间步骤。错误是:

  

forrtl:severe(408):fort:(2):数组TIMEVALS的下标#1的值为141,大于140的上限。

所以我做了一些研究,并通过我的源代码查看了什么样的数组时间参考,我发现它指的是这个具有时间维度的新气象数据,这样的时间数组由140个元素组成。每个元素都是模型应该用于模拟的meteo数据的特定日期和时间......所以我开始相信这是我的代码的问题,但是我的同事已经能够运行模型而没有问题,这对我来说很奇怪。他在Makefile中使用一些不同的设置编译模型,我不知道这是否重要,我仍然不太熟悉fortran等。但是下面是使用这个TIMEVALS数组的代码的一部分:

gam_object <- gam(terms(event ~ s(time) + ., data=lapse_train), 
    data = lapse_train, family = "binomial") 

CASE(2) ! nudging data is in netcdf-format cfile = str_filter(ndg_file_nc,yr,mo,dy,hr,mi,se,ndgblock) CALL message(' Adjust date using file: ',TRIM(cfile)) IF (p_parallel_io) THEN INQUIRE(file=cfile,exist=found) IF (.NOT.found) & CALL finish('NudgingInit','Nudging data file not found.') ndgfile%format = NETCDF CALL IO_open (cfile, ndgfile, IO_READ) CALL IO_INQ_DIMID(ndgfile%file_id, 'time', ndimid) CALL IO_INQ_DIMLEN(ndgfile%file_id, ndimid, nts) CALL IO_INQ_VARID(ndgfile%file_id, 'time', nvarid) ALLOCATE (timevals(nts)) CALL IO_GET_VAR_DOUBLE (ndgfile%file_id, nvarid, timevals) ihead_nc(1) = FLOOR(timevals(1)) ! ihead_nc(1) is YYYYMMDD ihead_nc(2) = INT((timevals(1)-ihead_nc(1))*24._dp) ! ihead_nc(2) is HH DEALLOCATE (timevals) ENDIF IF (p_parallel) CALL p_bcast(ihead_nc, p_io) CALL inp_convert_date(ihead_nc(1),ihead_nc(2)*10000, ndg_date0) IF (p_parallel_io) THEN ! skip first record and read second header ALLOCATE (timevals(nts)) CALL IO_GET_VAR_DOUBLE (ndgfile%file_id, nvarid, timevals) ihead_nc(1) = FLOOR(timevals(2)) ! ihead_nc(1) is YYYYMMDD ihead_nc(2) = INT((timevals(2)-ihead_nc(1))*24._dp) ! ihead_nc(2) is HH DEALLOCATE (timevals) CALL IO_close(ndgfile) ENDIF IF (p_parallel) CALL p_bcast(ihead_nc, p_io) CALL inp_convert_date(ihead_nc(1),ihead_nc(2)*10000, ndg_date1) ndg_file指轻推(meteo数据) 你们有什么可能导致这个错误的想法吗?

1 个答案:

答案 0 :(得分:2)

我现在有时间详细说明我之前的评论。 (请注意,我使用斜体表示您可能会关注的术语。)

您报告的错误是运行时错误,而不是编译器在编译时能够看到的错误。如果您不了解运行时(即代码执行时)与编译时之间的区别(即编译器将源代码转换为可执行代码时) ) 做一些研究。此外,很明显,您(或某人)已指示编译器创建一个代码版本,该代码检查数组元素访问是否在数组范围内。在测试新软件时,这是一个非常重要的安全功能,但是当代码执行时会产生性能损失,一旦他们通过了测试,就会在没有这些检查的情况下进行编译。

我不知道您正在使用哪种编译器,但请查看其文档,以找到在运行时启用数组边界检查的选项。

错误消息非常明确 - 在代码中的某个时刻,它尝试访问仅包含140个元素的数组的元素141。我们无法告诉您这是怎么发生的,即使我们看到您的整个代码也可能不会。当加载的数据不符合程序员的期望时,通常会发生这种情况。当编程人员在编写循环时发生 off-by-one 错误时,通常也会发生这种情况。我们可能会从查看您的整个代码中发现这一点,但您处于比我们更好的位置。

你写

  

但是我的同事已经能够运行模型而没有任何问题   对我来说很奇怪。他用一些不同的设置编译了模型   在Makefile中,我不知道这是否重要,

嗯,是的,这很重要,这很重要。如果您编写访问具有140个元素的数组的元素141的代码Fortran,就像许多其他编译语言一样,将很乐意在元素140之后访问内存中的下一个位置。通常,您无法知道程序干扰的数据是什么。如果幸运的话,内存中的下一个位置位于操作系统已分配给程序的地址空间之外,操作系统会立即停止程序并报告分段错误。

如果你不走运,程序会继续快乐地读取和写入元素141,无论它是什么。

我推测你的同事没有实现数组边界检查他的代码版本。无论你是否告诉他他的代码(很可能)已被破坏,这取决于你。

那你怎么办呢?你调试程序。您可以通过多种方式执行此操作,其中最简单的方法是(在我看来)插入一些write语句来打印代码中关键点的变量值,以测试您对可能值的假设,可以,或实际上采取。更难,但值得在未来解决问题方面的初步努力,将是在调试器的控制下运行代码。在所有主要平台上都有几个可用于Fortran程序的好调试器。

相关问题