<i id='gYYzu'><tr id='gYYzu'><dt id='gYYzu'><q id='gYYzu'><span id='gYYzu'><b id='gYYzu'><form id='gYYzu'><ins id='gYYzu'></ins><ul id='gYYzu'></ul><sub id='gYYzu'></sub></form><legend id='gYYzu'></legend><bdo id='gYYzu'><pre id='gYYzu'><center id='gYYzu'></center></pre></bdo></b><th id='gYYzu'></th></span></q></dt></tr></i><div id='gYYzu'><tfoot id='gYYzu'></tfoot><dl id='gYYzu'><fieldset id='gYYzu'></fieldset></dl></div>
<legend id='gYYzu'><style id='gYYzu'><dir id='gYYzu'><q id='gYYzu'></q></dir></style></legend>
    1. <tfoot id='gYYzu'></tfoot>

          <bdo id='gYYzu'></bdo><ul id='gYYzu'></ul>

        <small id='gYYzu'></small><noframes id='gYYzu'>

        Fortran - Cython 工作流程

        时间:2023-09-12
        <tfoot id='2jawj'></tfoot>

            <i id='2jawj'><tr id='2jawj'><dt id='2jawj'><q id='2jawj'><span id='2jawj'><b id='2jawj'><form id='2jawj'><ins id='2jawj'></ins><ul id='2jawj'></ul><sub id='2jawj'></sub></form><legend id='2jawj'></legend><bdo id='2jawj'><pre id='2jawj'><center id='2jawj'></center></pre></bdo></b><th id='2jawj'></th></span></q></dt></tr></i><div id='2jawj'><tfoot id='2jawj'></tfoot><dl id='2jawj'><fieldset id='2jawj'></fieldset></dl></div>

            <small id='2jawj'></small><noframes id='2jawj'>

              <tbody id='2jawj'></tbody>
              <bdo id='2jawj'></bdo><ul id='2jawj'></ul>

                  <legend id='2jawj'><style id='2jawj'><dir id='2jawj'><q id='2jawj'></q></dir></style></legend>
                  本文介绍了Fortran - Cython 工作流程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                  问题描述

                  我想设置一个工作流,以便在 Windows 机器上使用 Cython 从 Python 访问 fortran 例程

                  I would like to set up a workflow to reach fortran routines from Python using Cython on a Windows Machine

                  经过一番搜索,我发现:http://www.fortran90.org/src/best-practices.html#interfacing-with-c 和 https://stackoverflow.com/tags/fortran-iso-c-binding/信息

                  after some searching I found : http://www.fortran90.org/src/best-practices.html#interfacing-with-c and https://stackoverflow.com/tags/fortran-iso-c-binding/info

                  还有一些代码图片:

                  Fortran 端:

                  pygfunc.h:

                  void c_gfunc(double x, int n, int m, double *a, double *b, double *c);
                  

                  pygfunc.f90

                  pygfunc.f90

                  module gfunc1_interface
                      use iso_c_binding
                      use gfunc_module
                  
                      implicit none
                  
                  contains
                      subroutine c_gfunc(x, n, m, a, b, c) bind(c)
                          real(C_FLOAT), intent(in), value :: x
                          integer(C_INT), intent(in), value ::  n, m
                          type(C_PTR),    intent(in), value :: a, b
                          type(C_PTR),                value :: c
                  
                          real(C_FLOAT), dimension(:), pointer :: fa, fb
                          real(C_FLOAT), dimension(:,:), pointer :: fc
                  
                          call c_f_pointer(a, fa, (/ n /))
                          call c_f_pointer(b, fb, (/ m /))
                          call c_f_pointer(c, fc, (/ n, m /))
                          call gfunc(x, fa, fb, fc)
                       end subroutine
                  
                  end module
                  

                  gfunc.f90

                  module gfunc_module
                  
                  use iso_c_binding
                  
                      implicit none
                      contains
                          subroutine gfunc(x, a, b, c)
                              real,                 intent(in) :: x
                              real, dimension(:),   intent(in) :: a, b
                              real, dimension(:,:), intent(out) :: c
                  
                              integer :: i, j, n, m
                              n = size(a)
                              m = size(b)
                              do j=1,m
                                  do i=1,n
                                       c(i,j) = exp(-x * (a(i)**2 + b(j)**2))
                                  end do
                              end do
                          end subroutine
                  end module
                  

                  Cython 方面:

                  pygfunc.pyx

                  pygfunc.pyx

                  cimport numpy as cnp
                  import numpy as np
                  
                  cdef extern from "./pygfunc.h":
                      void c_gfunc(double, int, int, double *, double *, double *)
                  
                  cdef extern from "./pygfunc.h":
                      pass
                  
                  def f(float x, a=-10.0, b=10.0, n=100):
                      cdef cnp.ndarray ax, c
                      ax = np.arange(a, b, (b-a)/float(n))
                      n = ax.shape[0]
                      c = np.ndarray((n,n), dtype=np.float64, order='F')
                      c_gfunc(x, n, n, <double *> ax.data, <double *> ax.data, <double *> c.data)
                      return c
                  

                  和设置文件:

                  from distutils.core import setup
                  from distutils.extension import Extension
                  from Cython.Distutils import build_ext
                  import numpy as np
                  
                  ext_modules = [Extension('pygfunc', ['pygfunc.pyx'])]
                  
                  setup(
                      name = 'pygfunc',
                      include_dirs = [np.get_include()],
                      cmdclass = {'build_ext': build_ext},
                      ext_modules = ext_modules )
                  

                  所有文件都在一个目录中

                  all the files ar in one directory

                  fortran 文件编译(使用 NAG Fortran Builder)pygfunc 编译

                  the fortran files compile ( using NAG Fortran Builder ) pygfunc compiles

                  但链接它们会引发:

                  错误 LNK2019:引用了未解析的外部符号 _c_gfunc在函数___pyx_pf_7pygfunc_f

                  error LNK2019: unresolved external symbol _c_gfunc referenced in function ___pyx_pf_7pygfunc_f

                  当然还有:

                  致命错误 LNK1120:1 个未解决的外部问题

                  fatal error LNK1120: 1 unresolved externals

                  我错过了什么?还是这种在 Python 和 Fortran 之间建立工作流的方式从一开始就该死?

                  What am I missing ? or is this way to set up a workflow between Python and Fortran damned from the beginning ?

                  THX马丁

                  推荐答案

                  这是一个最小的工作示例.我使用 gfortran 并将编译命令直接写入安装文件.

                  Here's a minimum working example. I used gfortran and wrote the compile commands directly into the setup file.

                  gfunc.f90

                  module gfunc_module
                  implicit none
                  contains
                  subroutine gfunc(x, n, m, a, b, c)
                      double precision, intent(in) :: x
                      integer, intent(in) :: n, m
                      double precision, dimension(n), intent(in) :: a
                      double precision, dimension(m), intent(in) :: b
                      double precision, dimension(n, m), intent(out) :: c
                      integer :: i, j
                      do j=1,m
                          do i=1,n
                               c(i,j) = exp(-x * (a(i)**2 + b(j)**2))
                          end do
                      end do
                  end subroutine
                  end module
                  

                  pygfunc.f90

                  module gfunc1_interface
                  use iso_c_binding, only: c_double, c_int
                  use gfunc_module, only: gfunc
                  implicit none
                  contains
                  subroutine c_gfunc(x, n, m, a, b, c) bind(c)
                      real(c_double), intent(in) :: x
                      integer(c_int), intent(in) ::  n, m
                      real(c_double), dimension(n), intent(in) :: a
                      real(c_double), dimension(m), intent(in) :: b
                      real(c_double), dimension(n, m), intent(out) :: c
                      call gfunc(x, n, m, a, b, c)
                  end subroutine
                  end module
                  

                  pygfunc.h

                  extern void c_gfunc(double* x, int* n, int* m, double* a, double* b, double* c);
                  

                  pygfunc.pyx

                  from numpy import linspace, empty
                  from numpy cimport ndarray as ar
                  
                  cdef extern from "pygfunc.h":
                      void c_gfunc(double* a, int* n, int* m, double* a, double* b, double* c)
                  
                  def f(double x, double a=-10.0, double b=10.0, int n=100):
                      cdef:
                          ar[double] ax = linspace(a, b, n)
                          ar[double,ndim=2] c = empty((n, n), order='F')
                      c_gfunc(&x, &n, &n, <double*> ax.data, <double*> ax.data, <double*> c.data)
                      return c
                  

                  setup.py

                  from distutils.core import setup
                  from distutils.extension import Extension
                  from Cython.Distutils import build_ext
                  # This line only needed if building with NumPy in Cython file.
                  from numpy import get_include
                  from os import system
                  
                  # compile the fortran modules without linking
                  fortran_mod_comp = 'gfortran gfunc.f90 -c -o gfunc.o -O3 -fPIC'
                  print fortran_mod_comp
                  system(fortran_mod_comp)
                  shared_obj_comp = 'gfortran pygfunc.f90 -c -o pygfunc.o -O3 -fPIC'
                  print shared_obj_comp
                  system(shared_obj_comp)
                  
                  ext_modules = [Extension(# module name:
                                           'pygfunc',
                                           # source file:
                                           ['pygfunc.pyx'],
                                           # other compile args for gcc
                                           extra_compile_args=['-fPIC', '-O3'],
                                           # other files to link to
                                           extra_link_args=['gfunc.o', 'pygfunc.o'])]
                  
                  setup(name = 'pygfunc',
                        cmdclass = {'build_ext': build_ext},
                        # Needed if building with NumPy.
                        # This includes the NumPy headers when compiling.
                        include_dirs = [get_include()],
                        ext_modules = ext_modules)
                  

                  test.py

                  # A script to verify correctness
                  from pygfunc import f
                  print f(1., a=-1., b=1., n=4)
                  
                  import numpy as np
                  a = np.linspace(-1, 1, 4)**2
                  A, B = np.meshgrid(a, a, copy=False)
                  print np.exp(-(A + B))
                  

                  我所做的大部分更改都不是非常根本.以下是重要的.

                  Most of the changes I made aren't terribly fundamental. Here are the important ones.

                  • 您混合了双精度和单精度浮点数.不要那样做. 同时使用 real (Fortran)、float (Cython) 和 float32 (NumPy),同时使用双精度 (Fortran)、double (Cyton) 和 float64 (NumPy).尽量不要无意中混合它们.我假设你在我的例子中想要双打.

                  • You were mixing double precision and single precision floating point numbers. Don't do that. Use real (Fortran), float (Cython), and float32 (NumPy) together and use double precision (Fortran), double (Cyton), and float64 (NumPy) together. Try not to mix them unintentionally. I assumed you wanted doubles in my example.

                  您应该将所有变量作为指针传递给 Fortran.在这方面,它与 C 调用约定不匹配.Fortran 中的 iso_c_binding 模块仅匹配 C 命名约定.将数组作为指针传递,其大小作为单独的值.可能还有其他方法可以做到这一点,但我不知道.

                  You should pass all variables to Fortran as pointers. It does not match the C calling convention in that regard. The iso_c_binding module in Fortran only matches the C naming convention. Pass arrays as pointers with their size as a separate value. There may be other ways of doing this, but I don't know any.

                  我还在设置文件中添加了一些内容,以显示在构建时可以在哪里添加一些更有用的额外参数.

                  I also added some stuff in the setup file to show where you can add some of the more useful extra arguments when building.

                  要编译,请运行 python setup.py build_ext --inplace.要验证它是否有效,请运行测试脚本.

                  To compile, run python setup.py build_ext --inplace. To verify that it works, run the test script.

                  这是 fortran90.org 上显示的示例:mesh_exp

                  Here is the example shown on fortran90.org: mesh_exp

                  这是我前段时间整理的另外两个:ftridiag,fssor我当然不是这方面的专家,但这些示例可能是一个很好的起点.

                  Here are two more that I put together some time ago: ftridiag, fssor I'm certainly not an expert at this, but these examples may be a good place to start.

                  这篇关于Fortran - Cython 工作流程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                  上一篇:如何在 Fortran 中获取先前未知的数组作为函数的 下一篇:如何强制numpy数组顺序为fortran风格?

                  相关文章

                  最新文章

                    • <bdo id='SflWC'></bdo><ul id='SflWC'></ul>

                    <tfoot id='SflWC'></tfoot>

                  1. <i id='SflWC'><tr id='SflWC'><dt id='SflWC'><q id='SflWC'><span id='SflWC'><b id='SflWC'><form id='SflWC'><ins id='SflWC'></ins><ul id='SflWC'></ul><sub id='SflWC'></sub></form><legend id='SflWC'></legend><bdo id='SflWC'><pre id='SflWC'><center id='SflWC'></center></pre></bdo></b><th id='SflWC'></th></span></q></dt></tr></i><div id='SflWC'><tfoot id='SflWC'></tfoot><dl id='SflWC'><fieldset id='SflWC'></fieldset></dl></div>
                    1. <small id='SflWC'></small><noframes id='SflWC'>

                    2. <legend id='SflWC'><style id='SflWC'><dir id='SflWC'><q id='SflWC'></q></dir></style></legend>