当前位置: 首页 > 面试题库 >

f2py:在与python交互时在fortran中指定实际精度吗?

子车芷阳
2023-03-14
问题内容

我在玩f2py。我对numpy固有类型和fortran 90类型感到困惑。与python交互时,似乎只能在fortran
90中使用单精度实数。让我用一个例子来说明:

说我有这个fortran 90模块test.f90,可以用f2py编译并导入python中:

module test
implicit none

integer, parameter :: sp = selected_real_kind(6,37) ! single precision
integer, parameter :: dp = selected_real_kind(15,307) ! double precision

real(sp) :: r_sp = 1.0
real(dp) :: r_dp = 1.0_dp
end module

我这样编译:

f2py -c -m测试test.f90

然后,在python中:

>>> import test
>>> test.test.r_sp
array(1.0, dtype=float32)
>>> test.test.r_dp
array(1.0)

IOW,看来f2py不接受双精度。当将输入从python传递到fortran 90子例程时,这甚至变得更加成问题。说我将模块扩展到:

module test

implicit none
integer, parameter :: sp = selected_real_kind(6,37) ! single precision
integer, parameter :: dp = selected_real_kind(15,307) ! double precision

real(sp) :: r_sp = 1.0
real(dp) :: r_dp = 1.0_dp

contains

subroutine input_sp(val)
  real(sp), intent(in) :: val
  real(sp) :: x
  x = val
  write(*,*) x
end subroutine

subroutine input_dp(val)
  real(dp), intent(in) :: val
  real(dp) :: x
  x = val
  write(*,*) x
end subroutine
end module

f2py -c -m测试test.f90

蟒蛇

>>> import test
>>> test.test.input_sp(array(1.0,dtype=float32))
1.0000000    
>>> test.test.input_sp(array(1.0,dtype=float64))
1.0000000    
>>> test.test.input_dp(array(1.0,dtype=float32))
-1.15948430791165406E+155
>>> test.test.input_dp(array(1.0,dtype=float64))

-1.15948430791165406E + 155

因此,似乎要从python发送的任何输入变量都必须声明为单精度。这是f2py的已知问题吗?

此外,作为后续问题:从sp转换为dp的工作原理如下:

subroutine input_sp_to_dp(val)
  real(sp), intent(in) :: val(2)
  real(dp) :: x(2)
  x = val
  write(*,*) x
end subroutine

但是我想知道这是否完全是编译器特定的吗?我可以期望上述子例程对任何体系结构上的任何编译器执行正确的操作吗?在测试时,我使用了以上所有示例的gfortran。


问题答案:

在您的第一个示例中,我不知道您为什么说f2py似乎不接受双精度,test.test.r_dp
双精度却如此。一个显示带有小数点的值且没有显式dtype的numpy数组是一个双精度数组。

第二个示例显示了F2PY用处理类型定义的局限性kind=<kind>。请参阅常见问题解答:http :
//cens.ioc.ee/projects/f2py2e/FAQ.html#q-what-if-fortran-90-code-uses-type-
spec-kind-kind

要查看发生了什么,请运行f2py test.f90 -m test。我得到这个:

Reading fortran codes...
    Reading file 'test.f90' (format:free)
Post-processing...
    Block: test
            Block: test
                Block: input_sp
                Block: input_dp
Post-processing (stage 2)...
    Block: test
        Block: unknown_interface
            Block: test
                Block: input_sp
                Block: input_dp
Building modules...
    Building module "test"...
        Constructing F90 module support for "test"...
          Variables: r_dp sp r_sp dp
            Constructing wrapper function "test.input_sp"...
getctype: "real(kind=sp)" is mapped to C "float" (to override define dict(real = dict(sp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file).
getctype: "real(kind=sp)" is mapped to C "float" (to override define dict(real = dict(sp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file).
getctype: "real(kind=sp)" is mapped to C "float" (to override define dict(real = dict(sp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file).
              input_sp(val)
            Constructing wrapper function "test.input_dp"...
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file).
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file).
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file).
              input_dp(val)
    Wrote C/API module "test" to file "./testmodule.c"
    Fortran 90 wrappers are saved to "./test-f2pywrappers2.f90"

请注意,它会将“ real(kind = sp)”和“ real(kind = dp)”都映射到C“ float”,这是单精度的。

有几种方法可以解决此问题。

方法1

将类型声明分别更改为“ real(kind = 4)”和“ real(kind = 8)”(或“ real * 4”和“ real * 8”)。

当然,这违背了使用的目的selected_real_kind,对于某些编译器,对于单精度和双精度而言,4和8不是正确的KIND值。在这种情况下,使用gfortransp为4和dp8,因此可以正常工作。

方法二

告诉f2py如何处理这些声明。在f2py常见问题解答中对此进行了说明,这是上面显示的f2py输出中的“ getctype:…”消息中建议的方法。

在这种情况下,您将创建一个名为.f2py_f2cmap(在运行f2py的目录中)的文件,其中包含以下行

dict(real=dict(sp='float', dp='double'))

然后f2py将对那些real(sp)real(dp)声明做正确的事情。

方法3

它还可以重新排列代码:

module types

implicit none
integer, parameter :: sp = selected_real_kind(6,37) ! single precision
integer, parameter :: dp = selected_real_kind(15,307) ! double precision

real(sp) :: r_sp = 1.0
real(dp) :: r_dp = 1.0_dp

end module


module input

contains

subroutine input_sp(val)
  use types
  real(sp), intent(in) :: val
  real(sp) :: x
  x = val
  write(*,*) x
end subroutine

subroutine input_dp(val)
  use types
  real(dp), intent(in) :: val
  real(dp) :: x
  x = val
  write(*,*) dp, val, x
end subroutine

end module


 类似资料:
  • 问题内容: 我试图弄清楚如何从一些FORTRAN代码中重定向输出,我已经使用F2PY为它们生成了Python接口。我试过了: 这是在Python中重定向输出的事实上的方法,但是在这种情况下似乎不起作用(即,无论如何都会显示输出)。 我确实找到了2002年的邮件列表帖子,内容是“可以从pts设备读取消息,例如ttysnoop可以做到这一点”。关于ttysnoop的信息似乎很难在网上找到(我认为它已经

  • 本文向大家介绍Fortran 浮点数精度,包括了Fortran 浮点数精度的使用技巧和注意事项,需要的朋友参考一下 示例 类型的浮点数real不能有任何实数值。它们可以表示实数,最多可以包含一定数量的十进制数字。 FORTRAN 77保证了两种浮点类型,而最新的标准则至少保证了两种实数类型。实变量可以声明为 x这是默认类型的实数,并且y是比更大的十进制精度的实数x。在Fortran 2008中,十

  • 本文向大家介绍Python实现定时精度可调节的定时器,包括了Python实现定时精度可调节的定时器的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Python实现定时精度可调节的定时器,供大家参考,具体内容如下 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

  • 问题内容: 我一直在研究Python的模块,我想使用python的bash进行“交互式会话”。我希望能够像在终端模拟器上一样从Python读取bash输出/写入命令。我猜一个代码示例可以更好地解释它: (显然,这种方式行不通。)是否可能出现这种情况,怎么办? 非常感谢 问题答案: 请尝试以下示例: 您必须阅读有关stdin,stdout和stderr的更多信息。看起来不错的演讲:http://ww

  • 问题内容: 我知道可以做到,但是我不记得怎么做。 如何在python中重新导入模块?场景如下:我以交互方式导入模块并对其进行修改,但随后遇到错误。我修复了.py文件中的错误,然后想重新导入固定模块而不退出python。我该怎么做 ? 问题答案: 这应该工作: 来自Python文档 重新加载先前导入的模块。该参数必须是模块对象,因此它必须已经成功导入。如果您已使用外部编辑器编辑了模块源文件,并且想在

  • 编辑:我知道命令的选项。我明确地要求在docker文件中实现这一点。 Edit2:这不是Dockerfile中交互命令的重复,因为我的问题涉及如何避免为指定的参数,以便在Dockerfile中指定它们,而假设的重复解决了docker自身构建图像期间交互输入的问题。