How to generate Fortran subroutine with SymPy code

2019-05-18 20:27发布

I want to generate a Fortran subroutine with SymPy codegen utility. I can generate a Fortran function without problem with codegen(("f", x*y*z), "f95", "filename"). But I want to generate a Fortran subroutine so I can modify input arrays. How can I do this? The documentation is very poor.

标签: sympy codegen
1条回答
beautiful°
2楼-- · 2019-05-18 20:58

The codegen utility creates a function if there is a single scalar return value, and a subroutine otherwise. There is some support for arrays, but the array functionality won't be triggered unless you feed codegen an array like expression. The documentation is scattered, so I'll give you some pointers:

Take a look at the matrix-vector example in the autowrap documentation: http://docs.sympy.org/latest/modules/utilities/autowrap.html. Autowrap uses codegen behind the scenes.

In the current developer version there is also functionality for generating code that correspond to matrices with symbolic elements. See the examples for fcode() at http://docs.sympy.org/dev/modules/printing.html#fortran-printing.

Here is sample code that should output a Fortran 95 subroutine for a matrix-vector product:

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]

By saving these lines to my_file.py and running python my_file.py, I get the following output:

!******************************************************************************
!*                    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
查看更多
登录 后发表回答