我想使用SymPy codegen实用程序生成Fortran子例程。我可以codegen(("f", x*y*z), "f95", "filename")
生成一个没有问题的Fortran函数。但我想生成一个Fortran子例程,以便我可以修改输入数组。我怎样才能做到这一点?文档很差。
答案 0 :(得分:4)
如果存在单个标量返回值,则codegen实用程序会创建一个函数,否则会创建一个子例程。对数组有一些支持,但除非你为codegen提供类似表达式的数组,否则不会触发数组功能。文档是分散的,所以我会给你一些指示:
查看autowrap文档中的matrix-vector示例:http://docs.sympy.org/latest/modules/utilities/autowrap.html。 Autowrap在幕后使用codegen。
在当前的开发人员版本中,还有用于生成与具有符号元素的矩阵相对应的代码的功能。请参阅http://docs.sympy.org/dev/modules/printing.html#fortran-printing上的fcode()示例。
以下是应输出矩阵向量积的Fortran 95子例程的示例代码:
from sympy import *
from sympy.utilities.codegen import codegen
A, B, C = symbols('A B C', cls=IndexedBase)
m, n = symbols('m n', integer=True)
i = Idx('i', m)
j = Idx('j', n)
expr = Eq(C[i], A[i, j]*B[j])
result = codegen(('my_function', expr), 'f95', 'my_project')
print result[0][1]
通过将这些行保存到my_file.py并运行python my_file.py
,我得到以下输出:
!******************************************************************************
!* Code generated with sympy 0.7.5-git *
!* *
!* See http://www.sympy.org/ for more information. *
!* *
!* This file is part of 'project' *
!******************************************************************************
subroutine my_function(A, B, m, n, C)
implicit none
INTEGER*4, intent(in) :: m
INTEGER*4, intent(in) :: n
REAL*8, intent(in), dimension(1:m, 1:n) :: A
REAL*8, intent(in), dimension(1:n) :: B
REAL*8, intent(out), dimension(1:m) :: C
INTEGER*4 :: i
INTEGER*4 :: j
do i = 1, m
C(i) = 0
end do
do i = 1, m
do j = 1, n
C(i) = B(j)*A(i, j) + C(i)
end do
end do
end subroutine