gpt4 book ai didi

fortran - 在 fortran 程序中调用 METIS API(用 C 语言编写)

转载 作者:行者123 更新时间:2023-12-04 05:12:28 26 4
gpt4 key购买 nike

两个多星期以来,我一直在努力调用 METIS 之一。从我的 fortran 代码用 C 语言编写的库。而且,不幸的是,没有你的帮助,这似乎不是一个快乐的结局。我发现了一些关于 direct calling 的帖子和 using interface .我更喜欢后者,因为我可以监视变量以进行调试。我附上了三个代码。
1.我想使用的c函数2.fortran接口(interface)模块3.fortran程序

(1)c函数

int METIS_PartMeshNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind, 
idx_t *vwgt, idx_t *vsize, idx_t *nparts, real_t *tpwgts,
idx_t *options, idx_t *objval, idx_t *epart, idx_t *npart)

我删除了 c 函数体。没有必要了解我的问题

在这里, idx_t 是整数和 real_t 是单精度还是 double 。来自 没有选项 是输入,最后三个参数是输出。和 大众 , 尺寸 , tpwgts 选项 可以接收 null 作为默认设置的输入 我编写了使用这样的 c 函数的接口(interface)模块

(2) Fortran接口(interface)模块

固定的!
  • 插入 使用 iso_c_bind 下使用常量
  • 使用整数(c_int) 而不是 整数 对于 没有 , nn 和其他变量。
  • 移除未使用的模块 常数

  • .
    module Calling_METIS

    !use constants, only : p2 !this is for double precision
    use iso_c_bind !inserted later

    implicit none

    !integer :: ne, nn !modified
    integer(c_int) :: ne, nn
    !integer, dimension(:), allocatable :: eptr, eind !modified
    integer(c_int), dimension(:), allocatable :: eptr, eind
    !integer, dimension(:), allocatable :: vwgt, vsize !modified
    type(c_ptr) :: vwgt, vsize
    !integer :: nparts !modified
    integer(c_int) :: nparts
    !real(p2), dimension(:), allocatable :: tpwgts !modified
    type(c_ptr) :: tpwgts
    !integer, dimension(0:39) :: opts !modified
    integer(c_int), dimension(0:39) :: opts
    !integer :: objval !modified
    integer(c_int) :: objval
    !integer, dimension(:), allocatable :: epart, npart !modified
    integer(c_int), dimension(:), allocatable :: epart, npart

    interface
    subroutine METIS_PartMeshNodal( ne, nn, eptr, eind, vwgt, vsize, nparts, tpwgt, &
    opts, objval, epart, npart) bind(c)
    use intrinsic :: iso_c_binding
    !use constants, only : p2

    implicit none

    integer (c_int), intent(in) :: ne, nn
    integer (c_int), dimension(*), intent(in) :: eptr, eind
    !integer (c_int), dimension(*), intent(in) :: vwgt, vsize !modified
    type(c_ptr), value :: vwgt, vsize
    integer (c_int), intent(in) :: nparts
    !real(c_double), dimension(*), intent(in) :: tpwgt !modified
    type(c_ptr), value :: tpwgt
    integer (c_int), dimension(0:39), intent(in) :: opts
    integer (c_int), intent(out) :: objval
    integer (c_int), dimension(*), intent(out) :: epart
    integer (c_int), dimension(*), intent(out) :: npart

    end subroutine METIS_PartMeshNodal
    end interface
    end module

    这是我调用该函数的程序代码

    (3) Fortran程序

    固定的!
  • 的分配大小npart 是固定的。不是 没有但是 nn
  • 添加 opts(7)=1 以获取 epart、npart 的 Fortran 样式数组(到现在为止无效)

  • .
    program METIS_call_test

    !some 'use' statments
    use Calling_METIS
    use iso_c_binging !added

    implicit none

    ! Local variable
    integer :: iC
    character(80) :: grid_file !grid_file

    grid_file = 'test.grid'

    ! (1) Read grid files
    call read_grid(grid_file)

    ! (2) Construction Input Data for calling METIS Function
    ! # of cells, vertices
    ne = ncells
    nn = nvtxs

    ! eptr, eind allocation
    allocate(eptr(0:ne), eind(0:3*ntria + 4*nquad - 1))

    ! eptr and eind building
    eptr(0) = 0
    do iC=1, ncells
    eptr(iC) = eptr(iC-1) + cell(iC)%nvtxs
    eind(eptr(iC-1):eptr(iC)-1) = cell(iC)%vtx
    end do

    ! epart, npart building
    !allocate(epart(ne), npart(ne))
    allocate(epart(ne), npart(nn)) ! modified

    ! # of partition setting
    nparts = 2
    vwgt = c_null_ptr !added
    vsize = c_null_ptr !added
    tpwgt = c_null_ptr !added

    ! (3) Call METIS_PartMeshNodal
    call METIS_SetDefaultOptions(opts)

    opts(7) = 1 !Added. For fortran style output array epart, npart.

    call METIS_PartMeshNodal(ne, nn, eptr, eind, vwgt, vsize, nparts, tpwgt, &
    opts, objval, epart, npart)
    !call METIS_PartMeshNodal(ne, nn, eptr, eind, null(), null(), nparts, null(), &
    ! opts, objval, epart, npart) !wrong...

    end program

    但问题是我收到如下错误消息,尽管我为 tpwgt 设置了 null。

    输入错误:约束 0 的 tpwgts 的 0.000000 和不正确。

    这条消息在下面的代码中处理。
    for (i=0; i<ctrl->ncon; i++) {
    sum = rsum(ctrl->nparts, ctrl->tpwgts+i, ctrl->ncon);
    if (sum < 0.99 || sum > 1.01) {
    IFSET(dbglvl, METIS_DBG_INFO,
    printf("Input Error: Incorrect sum of %"PRREAL" for
    tpwgts for constraint %"PRIDX".\n", sum, i));
    return 0;
    }
    }

    无论如何,为了看看如果我为 tpwgts 放置一个数组而不是 null 会得到什么, tpwgts(:) = 1.0/nparts ,这使得 tpwgts 的总和等于 1.0。但我收到了与 相同的消息1.75 总和。

    这些是我的问题
    1. 我是否使用 null() 正确传递参数?
    2. 我必须将所有参数的指针传递给 c 函数吗?那怎么办?
    3. 将整数放入 opts(0:39) 是否足够使用?例如,在 post如果没有“接口(interface)模块”,则使用像 options(3)=1 这样的简单代码。但在 c 代码中,options 有 16 个命名变量,如 options[METIS_OPTION_NUMBERING]、options[METIS_OPTION_UFACTOR]。我认为设置选项是必要的,但我不知道。
    4. 有没有 METIS fortran 的例子?

    任何形式的提示/建议都会对我有很大帮助。谢谢你。

    结论

    我遇到的问题是 c 函数无法识别 null 来自 fortran 代码的指针。

    接口(interface)模块中有一些变量的错误声明(请参阅“已修复”和评论)

    看起来代码工作正常。但是 选项(7) = 1 fortran 风格的输出不起作用,现在我正在研究它。

    最佳答案

  • 不,你不能通过 null() ,这是一个 Fortran 指针常量。您必须通过 C_NULL_PTR来自模块ISO_C_BINDING并且界面必须反射(reflect)这一点。虚拟参数必须是 type(c_ptr) ,很可能是 VALUE属性。由于相同的内部表示,它实际上可能有效,但我不会指望它。
  • 不,如果你传递一些普通的变量,你可以直接通过引用传递它。就像通常在 Fortran 中一样。如果接口(interface)是BIND(C) ,编译器知道它必须发送一个指针。
    有一个更新 Fortran 2008 的新 TS,您可以在其中将可互操作过程中的虚拟参数定义为 OPTIONAL .然后你可以通过省略它们来传递空指针。 Gfortran 应该已经支持这一点。

  • 注:在这里,我可以看到你的函数有一个非常不同的 C 签名,你确定你的函数没问题吗? http://charm.cs.uiuc.edu/doxygen/charm/meshpart_8c.shtml

    关于fortran - 在 fortran 程序中调用 METIS API(用 C 语言编写),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14730349/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com