GNU Fortran编译器的GNU扩展提供了GETCWD()很好的子例程,获取当前工作目录.然而,我的代码必须是移植到ifort和nagfor编译器,以及和我使用F2003功能.
那么,GETCWD()F2003及更高版本有替代品吗?
我在这里有标准,但它相当大,我现在已经经历了一段时间,并没有找到任何有用的东西......
我知道这个和这个,但我再次询问,因为第一个链接现在已经很旧了,第二个链接似乎没有得出结论性的答案。达成共识了吗?
我的问题很简单:
我有一个循环,其中包含可以DO同时运行的元素。我该使用哪种方法?
下面是在简单立方晶格上生成粒子的代码。
请注意,x、y 和 z 在 CONCURRENT 情况下必须是数组,但在 OpenMP 情况下则不然,因为它们可以定义为 PRIVATE。
我也使用DO CONCURRENT(据我从上面的链接了解,使用SIMD):
DO CONCURRENT (i = 1, npart)
x(i) = MODULO(i-1, npart_edge)
Rx(i) = space*x(i)
y(i) = MODULO( ( (i-1) / npart_edge ), npart_edge)
Ry(i) = space*y(i)
z(i) = (i-1) / npart_face
Rz(i) = space*z(i)
END DO
Run Code Online (Sandbox Code Playgroud)
或者我使用 …
我正在开发面向对象的Fortran代码,以实现具有抽象类型支持的多态性的数值优化。由于这是一种良好的TDD做法,因此我尝试以抽象类型编写所有优化测试class(generic_optimizer),然后由每个实例化的类(例如by)运行该测试type(newton_raphson)。
所有优化测试都具有对的调用call my_problem%solve(...),该调用的定义deferred与抽象类型相同,并且在每种派生类型中当然具有不同的实现。
问题是:如果在每个非抽象类中都将延迟函数定义为non_overridable,则会出现分段错误,例如:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) where
#0 0x0000000000000000 in ?? ()
#1 0x0000000000913efe in __newton_raphson_MOD_nr_solve ()
#2 0x00000000008cfafa in MAIN__ ()
#3 0x00000000008cfb2b in main ()
#4 0x0000003a3c81ed5d in __libc_start_main () from /lib64/libc.so.6
#5 0x00000000004048f9 in _start ()
Run Code Online (Sandbox Code Playgroud)
经过反复试验,我注意到如果删除non_overridable声明,就可以避免该错误。在这种情况下,这不是问题,但是我想强制执行此操作,因为此代码不太可能具有两个级别的多态性。我是否违反了该标准的任何要求?
这是重现该错误的示例代码。我一直在用gfortran 5.3.0和6.1.0进行测试。
module generic_type_module
implicit none
private
type, abstract, public :: generic_type
real(8) :: some_data
contains
procedure (sqrt_interface), deferred …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用该mpi_f08模块在一系列4、5和6级阵列上进行光晕交换。以前,我为此使用了子数组类型,但最终得到了很多结果,以致ifort无法跟踪所有它们,并在使用进行编译时开始破坏它们-ipo。
我正在使用以下代码
call MPI_Isend(Array(1:kthird, ksizex_l, 1:ksizey_l, 1:ksizet_l, 1:size5, 1:size6), size, MPI_Double_Complex, ip_xup, 0 + tag_offset, comm, reqs(1))
call MPI_Irecv(Array(1:kthird, 0, 1:ksizey_l, 1:ksizet_l, 1:size5, 1:size6), size, MPI_Double_Complex, ip_xdn, 0 + tag_offset, comm, reqs(2))
Run Code Online (Sandbox Code Playgroud)
(然后再致电MPI_WaitAll)
将ifort 2017与Intel MPI 2017一起为每条这样的行给出以下警告:
test_mpif08.F90(51): warning #8100: The actual argument is an array section or assumed-shape array, corresponding dummy argument that has either the VOLATILE or ASYNCHRONOUS attribute shall be an assumed-shape array. [ARRAY]
Run Code Online (Sandbox Code Playgroud)
尽管如此,光环交换对于等级4和-5阵列也能正常工作。但是,对于第6级数组,数组数据进出的位置完全错误,来自发送过程中光环的数据(不在传递给数组的段中MPI_Isend)出现在接收的大部分中进程(未传递到MPI_Irecv)。
使用ifort 2018和Intel …
我从Fortran 2008开始,我正在努力与OOP大力合作.看来,很少有材料可以解释2008语言标准中非常基本的OOP概念.
我找到了有关继承的信息,但我无法找到有关多态的任何信息.
所以,如果我想在C++中重载一个函数,我可以这样做(来自维基百科的例子):
// volume of a cube
int volume(const int s)
{
return s*s*s;
}
// volume of a cylinder
double volume(const double r, const int h)
{
return 3.1415926*r*r*static_cast<double>(h);
}
// volume of a cuboid
long volume(const long l, const int b, const int h)
{
return l*b*h;
}
Run Code Online (Sandbox Code Playgroud)
但是,我怎么能在Fortran 2008中做同样的事情呢?
亲爱的 Fortran 程序员,
有人知道,是否可以在 Fortran 2003 或更高版本中声明一个常量(参数)过程指针数组?
如下所示,我有一个切换器函数,它根据传入的整数参数调用不同的函数。它使用一组过程指针(包装在派生中)类型。该数组必须init()在运行时通过例程初始化,然后才能使用。有什么办法可以在编译期间初始化这个数组并避免这种初始化例程的必要性?它也可以定义为parameter,因为它的值在运行期间不会改变。
module testmod
implicit none
interface
function funcInterface() result(res)
integer :: res
end function funcInterface
end interface
type :: ptrWrap
procedure(funcInterface), nopass, pointer :: ptr
end type ptrWrap
type(ptrWrap) :: switcher(2)
contains
subroutine init()
switcher(1)%ptr => func1
switcher(2)%ptr => func2
end subroutine init
function callFunc(ii) result(res)
integer, intent(in) :: ii
integer :: res
res = switcher(ii)%ptr()
end function callFunc
function func1() result(res)
integer :: res …Run Code Online (Sandbox Code Playgroud) 我了解 Fortran 2008+ 中子模块的一般好处,但我无法理解其中一种语法选项的好处。
如果我想创建单独的模块过程(其中过程主体位于子模块中),我需要在父模块中创建一个接口。该接口必须包含子例程或函数标识符以及参数列表和意图。这都是有道理的。
然后子模块包含过程的实现,但可以选择语法:我可以重复子例程或函数的签名,或者,我可以简单地使用“模块过程”之后的接口中的名称。我本来想打出一个例子,但Fortran wiki完美地展示了它。
我的问题是:使用“模块过程”而不是“模块函数”或“模块子例程”的替代语法有什么好处,即过程类型、参数和意图在子模块文件中不重复?看来这只会使代码维护变得复杂,因为现在需要打开两个文件才能理解子例程或函数。我在这里错过了一些隐藏的好处吗(除了保存复制/粘贴之外)?
有没有办法在 Fortran 中将数组(向量、矩阵,甚至标量)设置为零?2003/2008 似乎将 Fortran 提升到了一个非常现代的水平,我想知道它们是否包含一种无需执行即可将数组值设置为零的简单方法
do i = 1,X
do j = 1,Y
A(i,j) = 0
enddo
enddo
Run Code Online (Sandbox Code Playgroud)
其中 X 是行数,Y 是二维矩阵中的列数。这可以推广到任意多个维度,但原理是相同的。
在 Matlab 中,这很容易用 zeros 函数完成,即,
A = zeros(X,Y)
Run Code Online (Sandbox Code Playgroud)
现代 Fortran 似乎将很多人们喜欢的关于 Matlab 和其他语言的东西融入到它的曲目中,所以我很好奇他们是否对这个简单而基本的任务有内在的东西。
或者,也许在现代 Fortran 中,没有必要通过初始化数组来清除内存中以前存储的任何值?
我想更短的方法就是去
real, dimension(X,Y) :: A
A = A*0.0 ! Set all elements to zero by multiplying matrix by scalar value 0
Run Code Online (Sandbox Code Playgroud)
但是关于内在的问题仍然存在。
如何使用 ISO Fortran Env 的内在函数以 Fortran 2008 惯用的方式设置函数的返回 KIND 值?
通常在主程序中,我可以只使用 ISO Fortran 内在函数,如下所示:
program name here
use iso_fortran_env
implicit none
integer, parameter :: double=REAL64
real(kind=double) :: some_variable
end program name here
Run Code Online (Sandbox Code Playgroud)
但是似乎没有一种方便的方法可以将这些内在函数用于外部函数,因为 REAL64 和 double 都只能在上面的 main 函数中定义。尝试在 main 中定义函数的 KIND 如下:
program name here
use iso_fortran_env
implicit none
integer, parameter :: double=REAL64
real(kind=double) :: some_function
! Do stuff
end program name here
real function some_function()
! Do stuff
end some_function
Run Code Online (Sandbox Code Playgroud)
至少在我的系统上,会引发类型不匹配错误(double 被定义为 KIND=8,并且在我的系统上默认实数被定义为 KIND=4)。我总是可以只使用real(kind=8) function some_function(),但为了可移植性我不想这样做。另外,在一个地方使用 …
我有一个代码,其中R使用了具有3N元素的一维数组。您可以将其视为N粒子的位置向量,例如R=[r1x,r1y,r1z,r2x,r2y,...]。请注意,为了简洁地使用数组,应将模式定义为 this。
在代码的部分中,我只需要对 x 坐标执行一些操作。我目前正在使用这样的东西:
Rx => R(1:3N-2:3)
Run Code Online (Sandbox Code Playgroud)
并Rx在随后的操作中使用。这使得访问不连续,但我想知道我是否可以希望有一种方法来矢量化操作。或者,可以使用在粒子上带有环的 OMP。我想在这个问题上得到专家的想法,尤其是在性能方面的最佳实践。
fortran ×10
fortran2008 ×10
fortran2003 ×4
arrays ×1
concurrency ×1
fortran2018 ×1
function ×1
gfortran ×1
module ×1
mpi ×1
oop ×1
openmp ×1
overloading ×1
pointers ×1
polymorphism ×1
simd ×1