Skip navigation.

Posts tagged with "fortran"

MOVE_ALLOC in Fortran 2003

When Steve Lionel answered on comp.lang.fortran about “how to rename an array”, He told in Fortran 2003 there’s a MOVE_ALLOC intrinsic subroutine/function which has been implemented in Intel Visual Fortran 9.1.028 and later.

Just quote as follows:

This lets you move the “allocation” of one array (with its data) to another, the original array now being unallocated. With this, expanding an array requires one copy and two arrays allocated for a while, but it saves a second copy that would be required without it.

Let’s say you have an array A that you want to double its size while preserving the original data.

Without MOVE_ALLOC you’d do this:

OLD_SIZE = SIZE(A)
ALLOCATE (TEMP_ARRAY(OLD_SIZE)
TEMP_ARRAY = A ! First copy
DEALLOCATE (A)
ALLOCATE (A(2*OLD_SIZE))
A(1:OLD_SIZE) = TEMP_ARRAY ! Second copy
DEALLOCATE (TEMP_ARRAY)

With MOVE_ALLOC you can do this:

ALLOCATE (TEMP_ARRAY(2*SIZE(A))
TEMP_ARRAY(1:SIZE(A)) = A
CALL MOVE_ALLOC (TEMP_ARRAY, A)
! TEMP_ARRAYis now unallocated

You say you are using “Visual Fortran” but don’t provide further details. MOVE_ALLOC is supported in Intel Visual Fortran 9.1.028 and higher, not in Compaq or Digital Visual Fortran. For Intel Visual Fortran, you’ll currently find it described only in the Release Notes and not the regular manuals.

Steve


speed machine vs human

,

exactly? :headbang:

矩阵存储

,

一个 real(8) 或者 double precision 变量占用8字节

一个 real(8) 类型,大小10000x10000的矩阵,占用的存储空间就是

10000**2*8/1024/1024 ~= 762.94Mbyte


工程分析中用到的矩阵往往是具有特殊性质的,比如对称、稀疏、N对角等等。如果将矩阵中所有元素一一记下,包括有意义的和无意义的(零元素),就会浪费太多空间,当然目前的计算机内存价格已经很低了,对于小规模的矩阵来说根本不需要考虑这个问题。但是以上面那个矩阵为例,对于个人计算来说,它的规模也不算小了,如果利用其可能的特殊性质进行存储和处理,往往会事半功倍。

如果是对称矩阵可以取上三角阵或者下三角阵存储,可以节省大于一半的空间。
如果是稀疏矩阵,只需要记录各非零元素的值及其所在的行列位置。
如果是N对角矩阵,只需按照分别记录各个对角线的位置以及其中的元素值即可。

由于矩阵数值运算方法和存储格式相关,所以具体使用的存储格式应该根据问题不同、求解器不同而灵活变通。

Call Fortran Dll from Python with ctypes (IV)

, ,

数组array在Fortran Dll中总是按照地址传送的,因此无论如何在ctypes中都要用byref()来操作。而ctypes对C中array的描述就是一个相同数据类型的序列(sequence)

使用内置数据类型构造数组

myarray = c_int*10       # 定义一维整型数组,大小为10
myarray = c_double*42    # 定义一维双精度浮点数数组,大小为42

x = myarray()            # 实例化


一维数组

一维数组的构造使用数据类型乘以一个数值,该数值代表数组大小
# array  1 dimension
print 'test 1-dimension array'
n = c_int(10)
xarray = c_int * n.value
x = xarray(1,2,3,4,5,6,7,8,9,10)
m = c_int(7)
yarray = c_double*m.value
y = yarray()
d.array1(byref(n), byref(x), byref(m), byref(y))

print x
for i in y: print i;

相应fortran代码
subroutine array1(n, x, m, y)
  !DEC$ ATTRIBUTES DLLEXPORT, ALIAS:'array1' :: array1
  integer :: n
  integer, dimension(n) :: x
  real(8), dimension(m) :: y

  if (m>n) then
     y(1:n) = x
  else if (m<n) then
     y = x(1:m)
  endif
end subroutine array1

二维数组

二位数组的构造是用某个数据类型乘以多个数值,这些数值分别对应各个维数
 
# array 2 dimension
print 'test 2-dimension array'
m = c_int(3)
n = c_int(5)
xarray = c_int * m.value * n.value
x = xarray()

print x
d.array2(byref(n), byref(m), byref(x))

for j in range(n.value):
    for i in range(m.value):
        print j, i, x[j][i]

对应fortran代码
subroutine array2(m, n, x)
  !DEC$ ATTRIBUTES DLLEXPORT, ALIAS:'array2' :: array2
  integer :: n, m
  integer, dimension(m, n) :: x
 
  do i=1, m  ! 5 
    do j = 1, n  ! 3
            x(i,j) = i*j
    end do
  end do

end subroutine array2


ctypes中定义的二维数组看起来有点儿奇怪是不是:sst:

Call Fortran Dll from Python with ctypes (III)

,

Fortran的复数在C中以structure表示

  • complex(4) --> struct complex4 { float real, imag; };
  • complex(8) --> struct complex8 { double real, imag; };


在ctypes中构造一个结构很简单,只要继承Structure这个类就可以了,但是这个子类必须具有_fields_属性

# complex(4) structure
class Complex4(Structure):
    _fields_ = [('real', c_float),
               ('imag', c_float)]

x = Complex4(c_float(2.0), c_float(3.1415926))
y = Complex4()

d.cmpx(byref(x), byref(y))

print 'x:', x.real, x.imag, 'y:', y.real, y.imag


对应的Fortran子程序。注意这里使用alias来任意指定输出函数的名字为'cmpx',如果没有alias,则输出的函数名为原函数的名字大写'TESTCOMPLEX',还是使用alias比较灵活一些。
subroutine testcomplex(x, y)

  ! Expose subroutine cmpx to users of this DLL
  !
  !DEC$ ATTRIBUTES DLLEXPORT, ALIAS:'cmpx' :: testcomplex

  ! Variables
  complex:: x, y

  y = x + x

end subroutine cmpx