2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Fortranからnumpy配列を読み書きしたい!: forpyの利用その3

Last updated at Posted at 2021-05-21

この記事はFortranからPythonを扱う方法であるforpyを解説する記事の第三弾です。
FortranからPythonを使いたい!:forpy
Fortranで機械学習がしたい:FortranからのPyTorchの利用
が以前の記事です。

今回は、Fortranで作った配列をnumpyの配列にして、その配列をnpy形式で読み書きする方法です。
npy形式とは、Pythonでnumpyの配列をそのまま保存する場合のフォーマットです。

バージョン

  1. gcc version 11.1.0 (Homebrew GCC 11.1.0)
  2. mac OS 10.14.6

で試しました。
forpyの使い方は以前の記事をみてください。

ファイル書き込み

まず、ファイルの書き込みです。こんな感じになります。

subroutine test()
    use forpy_mod
    use,intrinsic::iso_fortran_env
    implicit none
    integer(int32)::ierror
    real(real64),allocatable::x(:)
    integer(int32)::N
    type(ndarray)::x_numpy,x2_numpy

    type(module_py) :: np
    type(tuple) :: args

    N = 10
    allocate(x(1:N))
    call random_number(x)
    write(*,*) "x = ",x

    
    ierror = import_py(np, "numpy")

    ierror = ndarray_create(x_numpy,x)
    ierror = print_py(x_numpy)

    ierror = ndarray_create_nocopy(x2_numpy,x)
    x(1) = 100d0
    ierror = print_py(x2_numpy)

    ierror = tuple_create(args, 2)
    ierror = args%setitem(0, "test")
    ierror = args%setitem(1, x_numpy)

    ierror = call_py_noret(np,"save",args)

    call x_numpy%destroy
    call x2_numpy%destroy

end subroutine

ここで、ndarray_createは新しいnumpy配列を作り、ndarray_create_nocopyはコピーなしでFortranの配列とnumpy配列を紐つけるものです。紐ついているために、Fortranの配列をいじるとnumpyの配列も変わっていることがわかります。このコードではtest.npyというファイルが書き出されます。

ファイル読み込み

ファイル読み込みは

subroutine test2()
    use forpy_mod
    use,intrinsic::iso_fortran_env
    implicit none
    integer(int32)::ierror
    type(module_py) :: np
    type(tuple) :: args
    type(object) :: arr
    real(real64),dimension(:), pointer ::x
    type(ndarray)::x_numpy
    integer(int32)::N

    N = 10

    ierror = import_py(np, "numpy")
    ierror = tuple_create(args, 1)
    ierror = args%setitem(0, "test.npy")

    ierror = call_py(arr,np,"load",args)

    ierror = ndarray_create_empty(x_numpy, [N], dtype="float64")
    !ierror = cast(arr,x_numpy)
    ierror = cast(x_numpy,arr) !arrの内容をx_numpyにcast
    ierror = x_numpy%get_data(x)

    write(*,*) "load"
    write(*,*) x

end subroutine

です。numpy配列をFortran配列にする場合には、call_pyで返ってきたPythonオブジェクトを一旦castでnumpy配列にしてから、get_dataをしなければならないことに注意してください。また、Fortranの配列にはpointer属性をつけてください。これで、Fortranの配列が手に入りました。

全体

全体のコードは

subroutine test()
    use forpy_mod
    use,intrinsic::iso_fortran_env
    implicit none
    integer(int32)::ierror
    real(real64),allocatable::x(:)
    integer(int32)::N
    type(ndarray)::x_numpy,x2_numpy

    type(module_py) :: np
    type(tuple) :: args

    N = 10
    allocate(x(1:N))
    call random_number(x)
    write(*,*) "x = ",x

    
    ierror = import_py(np, "numpy")

    ierror = ndarray_create(x_numpy,x)
    ierror = print_py(x_numpy)

    ierror = ndarray_create_nocopy(x2_numpy,x)
    x(1) = 100d0
    ierror = print_py(x2_numpy)

    ierror = tuple_create(args, 2)
    ierror = args%setitem(0, "test")
    ierror = args%setitem(1, x_numpy)

    ierror = call_py_noret(np,"save",args)

    call x_numpy%destroy
    call x2_numpy%destroy

end subroutine

subroutine test2()
    use forpy_mod
    use,intrinsic::iso_fortran_env
    implicit none
    integer(int32)::ierror
    type(module_py) :: np
    type(tuple) :: args
    type(object) :: arr
    real(real64),dimension(:), pointer ::x
    type(ndarray)::x_numpy
    integer(int32)::N

    N = 10

    ierror = import_py(np, "numpy")

    ierror = tuple_create(args, 1)
    ierror = args%setitem(0, "test.npy")

    ierror = call_py(arr,np,"load",args)

    ierror = ndarray_create_empty(x_numpy, [N], dtype="float64")
    !ierror = cast(arr,x_numpy)
    ierror = cast(x_numpy,arr) !arrの内容をx_numpyにcast
    ierror = x_numpy%get_data(x)

    write(*,*) "load"
    write(*,*) x
end subroutine


program main
    use forpy_mod
    use,intrinsic::iso_fortran_env
    implicit none
    integer(int32)::ierror

    ierror = forpy_initialize()
    call test()
    call test2()
end program

こんな感じになります。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?