You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sympy Codegen生成Fortran矩阵代码的两类技术问题咨询

Sympy Codegen生成Fortran代码的两个技术问题

我用Sympy处理了一组含符号表达式的矩阵,通过codegen成功生成了.f90文件并能在其他代码中调用,但还有两个问题需要解决:

  1. 如何在codegen中指定生成双精度实数类型的代码?
  2. 当前每个矩阵对应的Fortran子程序只包含参与计算的参数,怎么让每个子程序接收所有变量作为参数(哪怕部分变量没参与计算),实现统一调用格式:CALL matA11(all_the_variables_in_the_f90_file,name_matrix)和CALL matA21(all_the_variables_in_the_f90_file,name_matrix),避免用户逐个指定参数。

生成的测试用.f90文件示例

subroutine matA11(Gamma1, g, p0, rho0, yml, out_8665343569832042533)
implicit none
REAL*8, intent(in) :: Gamma1
REAL*8, intent(in) :: g
REAL*8, intent(in) :: p0
REAL*8, intent(in) :: rho0
REAL*8, intent(in) :: yml
REAL*8, intent(out), dimension(1:4, 1:4) :: out_8665343569832042533

out_8665343569832042533(1, 1) = 0
out_8665343569832042533(2, 1) = 0
out_8665343569832042533(3, 1) = 0
out_8665343569832042533(4, 1) = rho0*yml/(Gamma1*p0)
out_8665343569832042533(1, 2) = 0
out_8665343569832042533(2, 2) = 0
out_8665343569832042533(3, 2) = 0
out_8665343569832042533(4, 2) = 0
out_8665343569832042533(1, 3) = 0
out_8665343569832042533(2, 3) = 0
out_8665343569832042533(3, 3) = 0
out_8665343569832042533(4, 3) = 0
out_8665343569832042533(1, 4) = g*yml
out_8665343569832042533(2, 4) = 0
out_8665343569832042533(3, 4) = 0
out_8665343569832042533(4, 4) = 0

end subroutine

subroutine matA21(drdmu, dyml, g, m, mu, r, ymlp, &
      out_825899070853517470)
implicit none
REAL*8, intent(in) :: drdmu
REAL*8, intent(in) :: dyml
REAL*8, intent(in) :: g
REAL*8, intent(in) :: m
REAL*8, intent(in) :: mu
REAL*8, intent(in) :: r
REAL*8, intent(in) :: ymlp
REAL*8, intent(out), dimension(1:4, 1:3) :: out_825899070853517470

out_825899070853517470(1, 1) = -drdmu*dyml*g*mu**2/r + drdmu*dyml*g/r
out_825899070853517470(2, 1) = 0
out_825899070853517470(3, 1) = 0
out_825899070853517470(4, 1) = 0
out_825899070853517470(1, 2) = -drdmu*g*m*ymlp/r
out_825899070853517470(2, 2) = 0
out_825899070853517470(3, 2) = 0
out_825899070853517470(4, 2) = 0
out_825899070853517470(1, 3) = 0
out_825899070853517470(2, 3) = 0
out_825899070853517470(3, 3) = 0
out_825899070853517470(4, 3) = 0
end subroutine

问题解答

1. 指定生成双精度实数类型

Sympy的codegen可以通过自定义类型映射强制生成双精度代码,有两种常用实现方式:

方法一:单个表达式生成时指定类型

使用sympy.printing.fcode的type_aliases参数,将默认的real映射为real*8:

from sympy import symbols, fcode

Gamma1, g, p0, rho0, yml = symbols('Gamma1 g p0 rho0 yml')
expr = rho0*yml/(Gamma1*p0)

# 生成双精度代码
print(fcode(expr, type_aliases={'real': 'real*8'}))

方法二:批量生成子程序时配置

使用sympy.utilities.codegen.codegen函数,通过type_aliases参数统一设置类型:

from sympy import symbols, Matrix
from sympy.utilities.codegen import codegen

# 定义变量
Gamma1, g, p0, rho0, yml = symbols('Gamma1 g p0 rho0 yml')
matA11 = Matrix([
    [0, 0, 0, g*yml],
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [rho0*yml/(Gamma1*p0), 0, 0, 0]
])

# 生成双精度Fortran代码
codegen(
    ('matA11', matA11),
    language='fortran',
    filename='matrices',
    # 映射为REAL*8,也可替换为'double precision'适配F95标准
    type_aliases={'real': 'real*8'}
)

2. 让子程序接收所有变量作为参数

Sympy默认只将表达式中用到的变量设为参数,要强制传入所有变量,可通过添加哑变量引用实现:在矩阵表达式中加入未使用变量乘以0的项(不影响计算结果,但会被Sympy识别为必要参数)。

示例代码

from sympy import symbols, Matrix, ZeroMatrix
from sympy.utilities.codegen import codegen

# 定义所有需要传入的全局变量
all_vars = symbols('Gamma1 g p0 rho0 yml drdmu dyml m mu r ymlp')

# 构造matA11原始表达式
matA11_raw = Matrix([
    [0, 0, 0, g*yml],
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [rho0*yml/(Gamma1*p0), 0, 0, 0]
])
# 找出未用到的变量,添加哑引用
unused_vars_A11 = [var for var in all_vars if var not in matA11_raw.free_symbols]
dummy_A11 = ZeroMatrix(4,4)
for var in unused_vars_A11:
    dummy_A11 += var * ZeroMatrix(4,4)
matA11_full = matA11_raw + dummy_A11

# 同理处理matA21
matA21_raw = Matrix([
    [-drdmu*dyml*g*mu**2/r + drdmu*dyml*g/r, -drdmu*g*m*ymlp/r, 0],
    [0, 0, 0],
    [0, 0, 0],
    [0, 0, 0]
])
unused_vars_A21 = [var for var in all_vars if var not in matA21_raw.free_symbols]
dummy_A21 = ZeroMatrix(4,3)
for var in unused_vars_A21:
    dummy_A21 += var * ZeroMatrix(4,3)
matA21_full = matA21_raw + dummy_A21

# 批量生成统一参数格式的代码
codegen(
    [('matA11', matA11_full), ('matA21', matA21_full)],
    language='fortran',
    filename='matrices_unified',
    type_aliases={'real': 'real*8'}
)

效果说明

生成的两个子程序都会包含所有全局变量作为输入参数,调用时可统一传入全部变量,无需区分每个子程序的参数列表。


内容的提问来源于stack exchange,提问作者arkhose u

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 05:50:55