在一些科学环境中,你经常离不开FORTRAN,因为大多数开发人员只知道这个习语,并且有很多遗留代码和相关经验.坦率地说,高性能编程没有很多其他跨平台选项(C++可以完成任务,但语法,零启动数组和指针与某些人不兼容).
所以,让我们假设一个新项目,必须使用Fortran 90的,但我想建立最先进的软件架构出来的,同时与最新的编译器兼容(英特尔ifort,而且还包括Sun/HP/IBM编译)
所以我想要强加一些众所周知的常识,但在我的环境中还不是标准:
implicit none等#ifdef DEBUG),带有更多检查和所有可能的英特尔编译器检查(数组边界,子程序接口等)所有这一切的目标是拥有值得信赖,可维护和模块化的代码.然而,在许多遗留代码中,可重用性不是一个重要的目标.
我四处搜寻有关面向对象的Fortran编程契约式引用(断言/前提条件的/ etc.),发现只有丑陋的和过时的文件,通过人与没有大规模参与项目进行语法和文章,和死了的项目.
有关此主题的任何好的URL,建议,参考文件/书籍?
我已经阅读save了(英特尔)语言参考文档中的声明,但我无法完全理解它的作用.有人可以用简单的语言向我解释当save声明包含在模块中时它意味着什么吗?
我想我不会在任何教科书中找到它,因为回答这需要经验.我目前正处于测试/验证我的代码/狩猎漏洞以使其进入生产状态的阶段,任何错误都会导致许多人遭受痛苦,例如黑暗面.
在为Fortran编译程序以进行调试时,您设置了哪种标志?
你为生产系统设置了什么样的标志?
在部署之前你做了什么?
生产版本ifort用作编译器,但我用我的测试gfortran.我做错了吗?
假设您有一个包含大量变量,函数和子例程的Fortran 90模块.在您的USE陈述中,您遵循哪种惯例:
, only :语法显式声明您正在使用哪些变量/函数/子例程,例如 USE [module_name], only : variable1, variable2, ...?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中的子例程参数应该都具有指定的意图(即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)的参数和没有指定意图的参数之间是否存在任何真正的差异?如果我正在改进对较旧的,无意图的代码的意图,我还有什么可担心的吗?
在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) 我已经看到这要求其他语言,但刚刚发现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但他们似乎不是正确的选择.
我正在尝试实现一个指针数组,以便我可以遍历元素.但是我不确定如何正确地做到这一点:
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(标量指针).实现这个的正确方法是什么?
谢谢.
我最近在向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 ×10
fortran90 ×10
arrays ×3
module ×2
assertions ×1
bit ×1
conventions ×1
debugging ×1
deployment ×1
function ×1
gfortran ×1
if-statement ×1
oop ×1
pointers ×1
precision ×1
subroutine ×1
where ×1