2017-01-26 139 views
2

온라인 파기 및 시행 착오를 거친 후, 나는 여전히 파이썬에서 f2py에 의해 Fortran 배열 배열을 전달하는 방법에 대해 궁금해합니다. f2py를 사용하여 Fortran 서브 루틴에 문자열 배열을 전달하는 방법

SUBROUTINE FOO(A) 
    CHARACTER*5,dimension(10),intent(inout):: A 
    PRINT*, "A=",A 
    END 

가 그럼 난 f2py -m mystring -c string.f90을 실행

은 나뿐만 string.f90에서 포트란 서브 루틴이있다. 컴파일에 성공했습니다.

파이썬 세션이 test.py에 있습니다

import mystring 
import numpy as np 
nobstot=10 
xstring=np.empty(nobstot,dtype='S5') 
xstring[0]="ABCDE" 
mystring.foo(xstring) 

실행 python test.py, 나는 오류 메시지가 :

1-th dimension must be 5 but got 0 (not defined). 
Traceback (most recent call last) : 
File "test.py", line 6, in <module> 
mystring.foo(xstring) 
mystring.error: failed in converting 1st argument `a' of mystring.foo to C/Fortran array 

f2py 컴파일 단계를의 gfortran와 GCC 컴파일러가 호출되었다.

>>> print mystring.foo.__doc__ 후이 있었다 :

foo(a) 
Wrapper for ``foo``. 
Parameters 
--------- 
a : in/output rank-2 array('S') with bounds (10,5) 

그래서, 나뿐만 test.py 시도 : 다음 python test.py을 실행

import mystring 
import numpy as np 
nobstot=10 
xstring=np.empty((nobstot,5),dtype='S1') 
print xstring.shape 
xstring[0]="ABCDE" 
mystring.foo(xstring) 

을, 오류 메시지가 있었다 :

Traceback (most recent call last): 
File "test.py", line 7, in <module> 
mystring.foo(xstring) 
ValueError: failed to initialize intent(inout) array -- input 'S' not compatible to 'c' 
+0

가 인사를 추가하지 마십시오 당신의 게시하다. 이름 옆에 귀하의 이름이 이미 아이콘 근처에 자동으로 표시됩니다. –

+0

@Vladimire F. 알겠습니다. 도와 주셔서 정말로 고맙습니다. –

답변

2

먼저 문자열 배열을 Fortran에 전달하려면 Python에서 (<number of strings>, <string length>) 모양의 문자 배열을 만들고 내용을 채운 다음 char 배열을 f2py 생성 함수에 전달해야합니다. 귀하의 예제를 사용 :

xstring = np.empty((nobstot, 5), dtype='c') 
xstring[0] = "ABCDE" 
xstring[1] = "FGHIJ" 
mystring.foo(xstring) 

순서에서이 작업을, 당신도 당신의 포트란 코드를 변경해야합니다 : intent(inout)intent(in)로 대체

subroutine foo(A) 
character*5, dimension(10), intent(in) :: A 
print*, "A(1)=",A(1) 
print*, "A(2)=",A(2) 
end 

공지있다. 이것은 파이썬의 문자열과 numpy 배열의 문자열은 불변이지만 Fortran에서는 그렇지 않을 수 있기 때문입니다. 결과적으로, 파이썬 문자열의 메모리 레이아웃은 단순히 Fortran 함수로 전달 될 수 없으며 사용자는 위에서 설명한대로 문자열 데이터를 재구성해야합니다.

둘째, Fortran 코드가 문자열을 변경하면 intent(inout)의 사용법에서 알 수 있듯이 f2py 지시문을 사용하여 intent(in, out)과 같은 문자열 인수를 선언해야합니다.여기에 완벽한 예를 들어 다음과 같습니다

subroutine foo(A) 
character*5, dimension(10), intent(inout) :: A 
!f2py intent(in, out) A 
print*, "A(1)=",A(1) 
print*, "A(2)=",A(2) 
A(1)="QWERT" 
end 

F2py 전화 :

f2py -m mystring -c string.f90 

파이썬 테스트 스크립트 :

import mystring 
import numpy as np 
nobstot = 10 
xstring = np.empty((nobstot, 5), dtype='c') 
xstring[0] = "ABCDE" 
xstring[1] = "FGHIJ" 
xstring = mystring.foo(xstring) 
print("xstring[0]=",string[0].tostring()) 
print("xstring[1]=",string[1].tostring()) 

콘솔 출력 :

A(1)=ABCDE 
A(2)=FGHIJ 
xstring[0]= QWERT 
xstring[1]= FGHIJ 
+0

포트란 코드를 왜 표시 방식으로 변경해야하는지 이해할 수 없습니다. –

+0

일반적으로'! f2py intent (in, out) A'는 필요하지 않습니다. Fortran'intent (inout)'이 대신 자동으로 사용되기 때문입니다. 여기에 필요한 이유는 무엇입니까? –

+0

'! f2py intent (in, out)'이 필요한 진정한 이유는 문자열 배열에 대한 f2py 지원이 불완전하다는 것입니다. numpy 배열은 f2py가 활발하게 개발 된 후에 도입되었습니다. 문자열 배열 지원을 완료하면 numpy 문자열 배열을 사용하면이 문제가 해결됩니다. 그 때까지 여전히 f2py를 사용할 수 있지만 위에 언급 된 제한 사항 (numpy 문자열 배열 대신 numpy char 배열 사용)이 있습니다. – Pearu

0

가 문자열을 통신 그리고 fortran에서 조금 까다 롭습니다. 이 라인으로

당신은 10 개 문자의 1 차원 배열을 만드는

CHARACTER*10,intent(inout):: A 

로 변경하려고 실제 두 차원 문자 배열을 * 5

CHARACTER*5,dimension(10),intent(inout):: A 

10 establisted. 작동하지만 출력이 가비지 인 경우 두 문자가 같은 문자 형식 (ASCII/멀티 바이트 또는 유니 코드)인지 확인하십시오.

+0

고마워. 예, 문자열의 스칼라로 선언되면 파이썬 스크립트가 정상적으로 종료됩니다. 다행히도 예상대로 결과물이 정상적으로 보입니다. 지금 당장 나는 내 목적을 위해 당신의 제안에 충실 할 것입니다. 실제 정보에 새로운 정보 나보다 간단한 솔루션을 더 쉽게 사용하려면 여기에서 업데이트 할 것입니다. 지금 당장, 나는 당신의 대답을 선택하기 전에 다른 제안이 있는지 잠시 동안 기다릴 것입니다. –

+0

업데이트 : Fortran 서브 루틴에서 찾을 수 있습니다. CHARACTER (*), intent (inout) :: A. 이렇게하면이 스키마가 생각보다 강력 해집니다. –

+0

10 배 5 = 50, 왜 CHARACTER * 10이 아닌 CHARACTER * 50입니까? –