Fortran指向参数数组目标的指针

时间:2019-06-05 14:37:56

标签: pointers parameters fortran gfortran target

我在模块中有几个名称不同的参数数组:

subroutine sub(n,...
...
end

在此模块的例程中

para1

我想在n=1时使用para2,在n=2时使用real*8, pointer :: ptr(:) ,等等。有一些解决方案,一种是使数组paras = [para1 ,para2 ...]并正确索引,效果很好。但我想尝试使用指针

n

,然后根据PARAMETER attribute conflicts with TARGET attribute at (1)将其分配给不同的参数数组,但问题是“ parameter”。如果删除SAVE属性,则该例程的安全性较差,并且假定了parameter属性。

我错过了什么吗?为什么我们不能合并targetstatic func apply<T>(fn: (T ...) -> T, xs: [T]) -> T { return fn(xs) // gives '[T]' is not convertible to 'T' error } ?为此,有没有好的方法呢?

2 个答案:

答案 0 :(得分:2)

parametertarget属性确实存在冲突。具有target属性的对象必须是变量(Fortran 2018 8.5.17,C861);命名常量(具有parameter属性的对象)不是变量(F2018、8.5.13,C850)。

要使用目标数组,则必须使用变量。拥有一个“安全的”变量以防止其值被编程错误或类似情况所修改是很棘手的。有几种考虑因素可以阻止变量出现在变量定义上下文中。如果您可以安排这种状态,则编译器可能会发现您的错误。这样容易发生吗?

在纯过程和intent(in)伪参数之外,最诱人的禁止是使用受保护的模块变量:

module pars
  real, save, target, protected :: para1(74) = [...]
  real, save, target, protected :: para2(1) = [6]
end module

subroutine sub (...)
  use pars
  real, pointer :: p
  p => para1
end subroutine sub

要受到保护,这些值可以安全地在模块pars外部进行修改吗? las,即使这是真的,也无济于事:受到保护,我们甚至无法指向模块变量的指针。

总而言之,您的编译器不会发现容易检测到修改可变目标数组的编程错误,因此,如果要使用数组作为目标,则必须小心。

答案 1 :(得分:0)

在注释中@ ja72的建议之后,这是尝试对参数使用单个2D数组。这与gfortran-8.2(在MacOS10.11上)配合得很好。

import os
import numpy as np
import time
import matplotlib.pyplot as plt

# take a slice of the data
def slice_data(roi):
    dic = {}
    data = np.zeros((512,512,256))
    dic['data'] = np.squeeze( data[roi[0]:roi[1]+1, roi[2]:roi[3]+1, roi[4]:roi[5]+1] )
    return dic


# save slices if the data
def save_slices(roi, save=False):
    var = 'data'
    for i in range(0,6):
                # iterate to simulate a time series of data
        a = slice_data(roi)[var]
        var_dir = 'save_test/'
        if not os.path.exists(var_dir): os.makedirs(var_dir)
        file = var_dir + '{0:04d}{1}'.format(i,'.npy')

        if save is True:
            np.save(file, a)


## define slices
roix=[256, 256, 0, 512, 0, 256] # yz plane slice
roiy=[0, 512, 256, 256, 0, 256] # xz plane slice
roiz=[0, 512, 0, 512, 128, 128] # xy plane slice

## Calculate slices and do not save the results
dtx = []
dty = []
dtz = []
for i in range(100):
    time0 = time.time()
    save_slices(roix)
    time1 = time.time()
    dtx.append(time1-time0)

    time0 = time.time()
    save_slices(roiy)
    time1 = time.time()
    dty.append(time1-time0)


    time0 = time.time()
    save_slices(roiz)
    time1 = time.time()
    dtz.append(time1-time0)

plt.figure(1)
plt.plot(dtx)
plt.plot(dty)
plt.plot(dtz)
plt.title('time to run code without saving data')

print('mean time x-slice: {} sec'.format(np.mean(dtx)))
print('mean time y-slice: {} sec'.format(np.mean(dty)))
print('mean time z-slice: {} sec'.format(np.mean(dtz)))


## Calculate slices and do save the results
dtx = []
dty = []
dtz = []
for i in range(100):
    time0 = time.time()
    save_slices(roix, save=True)
    time1 = time.time()
    dtx.append(time1-time0)

    time0 = time.time()
    save_slices(roiy, save=True)
    time1 = time.time()
    dty.append(time1-time0)


    time0 = time.time()
    save_slices(roiz, save=True)
    time1 = time.time()
    dtz.append(time1-time0)

plt.figure(2)
plt.plot(dtx)
plt.plot(dty)
plt.plot(dtz)
plt.title('time to run code and save data')

print('mean time x-slice: {} sec'.format(np.mean(dtx)))
print('mean time y-slice: {} sec'.format(np.mean(dty)))
print('mean time z-slice: {} sec'.format(np.mean(dtz)))

但是,由于代码变得有点复杂(由于重塑),并且可能无法与旧的编译器一起使用,因此使用非参数数组可能会更直接...