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.

- 1,834
- 2
- 20
- 33
1 Answers
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

- 943
- 6
- 10
-
2I'm looking into your second link and I can't set the standard to Fortran 95. When I write `fcode(x, standard=95)`, it says `TypeError: Unknown setting 'standard'`. Do you know what's the problem? I'm using python 2.7 and SymPy 0.7.5 – Michael Aug 28 '14 at 15:21
-
2It appears that the 'standard' argument must have been added recently, and will probably be available in 0.7.6. To get a more modern formatting of the code, you can use `fcode(x, source_format='free')`. – Ø. Jensen Aug 28 '14 at 16:24
-
Sorry but I just can't get it to work. Could you please show me a concrete example to generate a Fortran subroutine with python codegen? My goal is to generate a compilable Fortran code. I'm new with python, I'm using sympy to facilitate the job to write long math expressions. – Michael Aug 29 '14 at 18:55
-
By the way, I recently updated my sympy from the git repo and now `fcode(x, standard=95)` works. It was lacking a lot of functionalities appearing on the documentation. – Michael Aug 30 '14 at 01:11
-
1The second link goes to the docs for the release currently under development. – Ø. Jensen Aug 30 '14 at 08:45
-
My problem is quite similar, but I haven't figured out how to give the output of the subroutine in the way that is required by the FORTRAN code I need to generate - http://stackoverflow.com/questions/39045066/generate-fortran-subroutine-with-sympy-codegen-for-a-system-of-equations – Ohm Aug 19 '16 at 17:52