标签: fortran90

编写健壮的"现代"Fortran代码

在一些科学环境中,你经常离不开FORTRAN,因为大多数开发人员只知道这个习语,并且有很多遗留代码和相关经验.坦率地说,高性能编程没有很多其他跨平台选项(C++可以完成任务,但语法,零启动数组和指针与某些人不兼容).

所以,让我们假设一个新项目,必须使用Fortran 90的,但我想建立最先进的软件架构出来的,同时与最新的编译器兼容(英特尔ifort,而且还包括Sun/HP/IBM编译)

所以我想要强加一些众所周知的常识,但在我的环境中还不是标准:

  • 全局变量禁止,没有getos,没有跳转标签implicit none
  • "面向对象编程"(具有数据类型和相关子例程的模块)
  • 模块化/可重用的功能,文档齐全,可重用的库
  • 断言/前提条件/不变量(使用预处理程序语句实现)
  • 所有(大多数)子程序和"对象"的单元测试
  • 一个强烈的"调试模式"(#ifdef DEBUG),带有更多检查和所有可能的英特尔编译器检查(数组边界,子程序接口等)
  • 统一和强制清晰的编码风格,使用代码处理工具助手.

所有这一切的目标是拥有值得信赖,可维护和模块化的代码.然而,在许多遗留代码中,可重用性不是一个重要的目标.

我四处搜寻有关面向对象的Fortran编程契约式引用(断言/前提条件的/ etc.),发现只有丑陋的和过时的文件,通过人与没有大规模参与项目进行语法和文章,和死了的项目.

有关此主题的任何好的URL,建议,参考文件/书籍?

oop fortran scientific-computing assertions fortran90

63
推荐指数
5
解决办法
1万
查看次数

Fortran SAVE声明

我已经阅读save了(英特尔)语言参考文档中的声明,但我无法完全理解它的作用.有人可以用简单的语言向我解释当save声明包含在模块中时它意味着什么吗?

fortran fortran90

38
推荐指数
2
解决办法
5万
查看次数

您为GFORTRAN调试器/编译器设置了哪些标志来捕获错误的代码?

我想我不会在任何教科书中找到它,因为回答这需要经验.我目前正处于测试/验证我的代码/狩猎漏洞以使其进入生产状态的阶段,任何错误都会导致许多人遭受痛苦,例如黑暗面.

  • 在为Fortran编译程序以进行调试时,您设置了哪种标志?

  • 你为生产系统设置了什么样的标志?

  • 在部署之前你做了什么?

生产版本ifort用作编译器,但我用我的测试gfortran.我做错了吗?

deployment debugging fortran gfortran fortran90

38
推荐指数
2
解决办法
3万
查看次数

你如何使用Fortran 90模块数据

假设您有一个包含大量变量,函数和子例程的Fortran 90模块.在您的USE陈述中,您遵循哪种惯例:

  1. 使用, only :语法显式声明您正在使用哪些变量/函数/子例程,例如 USE [module_name], only : variable1, variable2, ...
  2. 插入毯子USE [module_name]

一方面,该only子句使代码更加冗长.但是,它会强制您在代码中重复自己,如果您的模块包含许多变量/函数/子例程,那么事情就会开始变得难以驾驭.

这是一个例子:

module constants
  implicit none
  real, parameter :: PI=3.14
  real, parameter :: E=2.71828183
  integer, parameter :: answer=42
  real, parameter :: earthRadiusMeters=6.38e6
end module constants

program test
! Option #1:  blanket "use constants"
!  use constants
! Option #2:  Specify EACH variable you wish to use.
  use constants, only : PI,E,answer,earthRadiusMeters
  implicit none …
Run Code Online (Sandbox Code Playgroud)

fortran module conventions fortran90

36
推荐指数
3
解决办法
5万
查看次数

Fortran意图(inout)与省略意图

良好实践规定Fortran中的子例程参数应该都具有指定的意图(即intent(in),intent(out)或者如此问题intent(inout)所描述的):

subroutine bar (a, b)
    real, intent(in) :: a
    real, intent(inout) :: b
    b = b + a
    ...
Run Code Online (Sandbox Code Playgroud)

但是,未指定intent是有效的Fortran:

subroutine bar (a, b)
    real, intent(in) :: a
    real :: b
    b = b + a
    ...
Run Code Online (Sandbox Code Playgroud)

在编译时检查指定intent(inout)的参数和没有指定意图的参数之间是否存在任何真正的差异?如果我正在改进对较旧的,无意图的代码的意图,我还有什么可担心的吗?

fortran fortran90

33
推荐指数
3
解决办法
3万
查看次数

如何在Fortran中初始化二维数组

在C中,如果我没记错的话,您可以使用花括号语法轻松初始化数组:

int* a = new int[] { 1, 2, 3, 4 };
Run Code Online (Sandbox Code Playgroud)

当您希望初始化具有特定测试值的矩阵用于数学目的时,如何在Fortran中对二维数组执行相同的操作?(无需对单独的语句中的每个元素进行双重索引)

该数组由.定义

real, dimension(3, 3) :: a
Run Code Online (Sandbox Code Playgroud)

要么

real, dimension(:), allocatable :: a
Run Code Online (Sandbox Code Playgroud)

arrays fortran array-initialize fortran90

30
推荐指数
3
解决办法
9万
查看次数

如何检查Fortran数组是否包含值?

我已经看到这要求其他语言,但刚刚发现Fortran可以很好地处理数组,我想可能有一个简单的方法来做这个没有循环.

目前我正在搜索查看"最近邻居"的3D数组以查看它们是否包含字母"n",并且每当找到此值时,我希望它执行一些clusterLabel赋值(这与此问题无关) )

我想使用if(lastNeighArray.eq."n") then...<rest of code> 但由于显而易见的原因,它不喜欢根据值检查数组.它也不像我一样使用lastNeighArray(:),即使我希望它一次检查一个元素.where(lastNeighArray.eq."n")不起作用,因为我在where循环中有一个case语句,我得到错误WHERE statements and constructs must not be nested.

所以我有点卡住了.我真正想要的是类似when(lastNeighArray.eq."n")但不存在的东西.

我也看过了any,forall但他们似乎不是正确的选择.

arrays fortran if-statement where fortran90

30
推荐指数
1
解决办法
2万
查看次数

指针数组

我正在尝试实现一个指针数组,以便我可以遍历元素.但是我不确定如何正确地做到这一点:

TYPE(domain),POINTER              :: d01,d02,d03
TYPE(domain),DIMENSION(:),POINTER :: dom
...

dom(1) => d01
dom(2) => d02
dom(3) => d03
...
Run Code Online (Sandbox Code Playgroud)

然后:

...
IF(ASSOCIATED(dom(2),d02))THEN
...
Run Code Online (Sandbox Code Playgroud)

编译器(x86-64 Linux -tp istanbul-64上的pgf90 10.6-0 64位目标)给出了以下错误消息:

 PGF90-S-0074-Illegal number or type of arguments to associated - keyword argument pointer (test_ptr.f90: 10)
  0 inform,   0 warnings,   1 severes, 0 fatal for MAIN
Run Code Online (Sandbox Code Playgroud)

据我所知,如何对指针数组进行子集化是有问题的.两个dom(2)d02是秩0(标量指针).实现这个的正确方法是什么?

谢谢.

arrays fortran pointers fortran90

29
推荐指数
1
解决办法
6184
查看次数

在Fortran中正确使用模块,子例程和函数

我最近在向Fortran程序添加函数时学习了tinterface块.一切都很好,整洁,但现在我想在接口块中添加第二个功能.

这是我的界面块:

interface
    function correctNeighLabel (A,i,j,k)
    integer :: correctNeighLabel
    integer, intent(in) :: i,j,k
    integer,dimension(:,:,:),intent(inout) :: A
    end function

    function correctNeighArray (B,d,e,f)
        character :: correctNeighArray
    integer, intent(in) :: d,e,f
    character, dimension(:,:,:),intent(inout) :: B
    end function
end interface
Run Code Online (Sandbox Code Playgroud)

在我看来,这可能不是最好的选择.

我已经研究过子程序,但我不太相信它是正确的解决方案.我正在做的是相对简单的,我需要将参数传递给子例程,但我看到的所有子例程都是a)复杂的(即函数太复杂),和b)不接受参数,它们表现得好像他们操纵变量而不将它们传递给它们.

我没有真正正确地研究模块,但从我所看到的不适合使用的模块.

我应该在哪个时候使用,以及如何最好地使用它?

fortran module function subroutine fortran90

28
推荐指数
3
解决办法
4万
查看次数

"真正的*8"是什么意思?

用Fortran 90编写的程序手册说:"所有实际变量和参数都以64位精度(即real*8)指定."

根据维基百科,单精度对应于32位精度,而双精度对应于64位精度,因此显然程序使用双精度.

但是什么real*8意思呢?

我认为这8意味着8位数字跟随小数点.然而,维基百科似乎说单精度通常提供6-9位数,而双精度通常提供15-17位数.这是否意味着语句"64位精度"与real*8?不一致?

precision fortran bit fortran90

28
推荐指数
3
解决办法
5万
查看次数