inputdeck_fortran
Case 3.1. Inputdeck case study 1
다음과 같이 정수형 변수 1개, 실수형 변수 1개, 리스트형 변수 1개, 3차원 벡터 1개를 받는 Inputdeck를 생성하였다.
Inputdeck에서 필요한 정보들만 담기 위해 Inputdeck 설정 값을 다음과 같이 정하였다.
INPUTDECK key | value |
---|---|
value delimiter | SPACE |
line delimiter | NULL |
Vector vracket | SQUARE_SPACE |
Vector delimiter | SPACE |
이렇게 설정되어 생성된 인풋 파일은 다음과 같다.
INT1 42
REAL1 42.112
LIST1 a
VECTOR1 [ 1 0 0 ]
FORTRAN code example : Case3.f
program sample
CHARACTER(len=16) :: cmd_option_name , value_name
CHARACTER(len=512) :: inputdeck
INTEGER :: num_of_args, i, io_status
LOGICAL :: args_error_flag = .false.
INTEGER INT1
DOUBLE PRECISION REAL1
CHARACTER LIST1, tempchar
INTEGER :: VECTOR1(3)
num_of_args = iargc()
do i=1, num_of_args, 2
call getarg(i,cmd_option_name)
if( cmd_option_name .eq. "-inp") then
call getarg(i+1,inputdeck)
WRITE (*,*) trim(inputdeck)
else
args_error_flag = .true.
WRITE (*,*) "ERROR: INVALID COMAND OPTION: " ,
+ cmd_option_name
endif
enddo
if ( args_error_flag .eqv. .true. ) then
WRITE(*,*) "CHECK YOUR COMAND OPTION"
stop
endif
open(1,file=trim(inputdeck),iostat=io_status, status='old')
if (io_status /= 0) then
write(*,*) 'File open error'
stop
end if
do
READ(1,*, IOSTAT=io) value_name
if ( io < 0) then
WRITE(*,*) "Inputdeck file read end"
EXIT
end if
BACKSPACE (1)
if ( value_name .eq. "INT1") then
READ(1,*) value_name, INT1
WRITE(*,*) "INT1 = ", INT1
else if ( value_name .eq. "REAL1") then
READ(1,*) value_name, REAL1
WRITE(*,*) "REAL1 = ", REAL1
else if ( value_name .eq. "LIST1") then
read(1,*) value_name, LIST1
write(*,*) "list = ", LIST1
else if ( value_name .eq. "VECTOR1") then
read(1,*) value_name, tempchar, VECTOR1(1),
+ VECTOR1(2), VECTOR1(3)
write(*,*) "Vector = ", VECTOR1(1), VECTOR1(2),
+ VECTOR1(3)
else
WRITE(*,*) "Inputdeck value read error"
stop
endif
end do
CLOSE(1)
end program
입력 파일이 1개인 경우의 Fortran 예제 코드에서 Inputdeck 파일을 읽는 부분을 추가한 예제이다.
주요 변수 설명
INT1
,REAL1
,LIST1
,VECTOR1(3)
: Inputdeck 파일에서 각각의 변수 값를 저장하는 변수io_status
: 입력 파일 오픈 시 에러 발생 여부를 저장하는 변수
주요 코드 설명
...
[1] open(1,file=trim(inputdeck),iostat=io_status, status='old')
[2] if (io_status /= 0) then
write(*,*) 'File open error'
stop
end if
...
- open() 함수를 이용해 장치번호(UNIT)을 1로 설정하여
inputdeck
배열에 저장된 PATH의 인풋 파일 읽는다. 이때 trim() 함수를 이용해 앞에서 받은 inputdeck 경로 뒤에 붙은 공백을 제거한다. iostat=io_status
은 파일 오픈 시 에러 발생 여부를 확인하는 옵션으로, 정상적으로 파일 오픈시 0 값을 저장status='old'
는 기존의 있는 파일을 오픈하는 경우old
값을 입력한다.- 예를들어
trim("Hello ")
실항하면, "Hello"를 리턴하게 된다. - 입력된 path에 파일이 없거나 정상적으로 파일이 오픈이 안되는 경우
io_status
값이 0이 아닌 값을 리턴한다. 에러 메시지를 표시하고 프로그램을 종료한다.
...
do
[1] READ(1,*, IOSTAT=io) value_name
if ( io < 0) then
WRITE(*,*) "Inputdeck file read end"
EXIT
end if
[2] BACKSPACE (1)
[3] if ( value_name .eq. "INT1") then
READ(1,*) value_name, INT1
WRITE(*,*) "INT1 = ", INT1
else if ( value_name .eq. "REAL1") then
READ(1,*) value_name, REAL1
WRITE(*,*) "REAL1 = ", REAL1
else if ( value_name .eq. "LIST1") then
read(1,*) value_name, LIST1
write(*,*) "list = ", LIST1
else if ( value_name .eq. "VECTOR1") then
read(1,*) value_name, tempchar, VECTOR1(1),
+ VECTOR1(2), VECTOR1(3)
write(*,*) "Vector = ", VECTOR1(1), VECTOR1(2),
+ VECTOR1(3)
[4] else
WRITE(*,*) "Inputdeck value read error"
stop
endif
end do
CLOSE(1)
...
- 장치 번호 1번을 사용해 앞서 open한 입력 파일의 한 줄을 read()를 사용해 읽는다. 이때 입력 파일의 첫 번째 문자열인 변수 이름을
value_name
에 저장한다.- 여기서 파일을 끝까지 다 읽은 경우 파일 read를 하게 되면
io
값이 0보다 작게 된다. 이를 통해 파일을 끝까지 다 읽었는지 여부를 판단하고 파일을 끝까지 다 읽은 경우 loop문을 빠저나온다.
- 여기서 파일을 끝까지 다 읽은 경우 파일 read를 하게 되면
- read()함수를 이용해 이미 앞에서 읽었던 파일 라인의 변수의 값을 다시 읽기 위해서, backspace()를 이용 방금 읽었던 파일 라인을 다시 읽을 수 있도록 파일 포인터를 이동한다.
- 입력 파일에서 읽은 변수 이름을 확인하여 저장 함. 벡터 변수의 경우 변수 이름과 값 사이에 있는
[
문자를tempchar
변수에 저장하고,VECTOR1(1~3)
에 각각의 벡터 원소들을 저장한다. - 원하지 않은 변수 값이 입력되는 경우 이에 대한 에러 메시지를 표시하고 프로그램을 종료
Case 3.2. Inputdeck case study 2
다음과 같이 정수형 변수 1개, 실수형 변수 1개, 리스트형 변수 1개, 3차원 벡터 1개를 받는 Inputdeck를 생성하였다.
Inputdeck에서 필요한 정보들만 담기 위해 Inputdeck 설정 값을 다음과 같이 정하였다.
INPUTDECK key | value |
---|---|
value delimiter | EQUAL |
line delimiter | SEMICOLON |
Vector vracket | SQUARE_SPACE |
Vector delimiter | SPACE |
이렇게 설정되어 생성된 인풋 파일은 다음과 같다.
INT1 = 42 ;
REAL1 = 42.112 ;
LIST1 = a ;
VECTOR1 = [ 1 0 0 ] ;
FORTRAN code example : Case4.f
위 케이스에서 생성된 입력 파일을 읽어와 같은 이름의 변수를 생성해 저장하는 코드이다. case 1의 코드와 크게 다르지 않으며, tempchar
변수를 이용해 변수 이름과 변수 값 사이에 있는 =
을 처리하는 부분을 추가하였다.
program sample
CHARACTER(len=8) :: cmd_option_name , value_name
CHARACTER(len=256) :: inputdeck
INTEGER :: num_of_args, i, io_status
LOGICAL :: args_error_flag = .false.
INTEGER INT1
DOUBLE PRECISION REAL1
CHARACTER LIST1, tempchar
INTEGER :: VECTOR1(3)
num_of_args = iargc()
do i=1, num_of_args, 2
call getarg(i,cmd_option_name)
if( cmd_option_name .eq. "-inp") then
call getarg(i+1,inputdeck)
WRITE (*,*) trim(inputdeck)
else
args_error_flag = .true.
WRITE (*,*) "ERROR: INVALID COMAND OPTION: " ,
+ cmd_option_name
endif
enddo
if ( args_error_flag .eqv. .true. ) then
WRITE(*,*) "CHECK YOUR COMAND OPTION"
stop
endif
open(1,file=trim(inputdeck),iostat=io_status, status='old')
if (io_status /= 0) then
write(*,*) 'File open error'
stop
end if
do
READ(1,*, IOSTAT=io) value_name
if ( io < 0) then
WRITE(*,*) "Inputdeck file read end"
EXIT
end if
BACKSPACE (1)
if ( value_name .eq. "INT1") then
READ(1,*) value_name, tempchar, INT1
WRITE(*,*) "INT1 = ", INT1
else if ( value_name .eq. "REAL1") then
READ(1,*) value_name, tempchar, REAL1
WRITE(*,*) "REAL1 = ", REAL1
else if ( value_name .eq. "LIST1") then
read(1,*) value_name, tempchar, LIST1
write(*,*) "list = ", LIST1
else if ( value_name .eq. "VECTOR1") then
read(1,*) value_name, tempchar, tempchar, VECTOR1(1),
+ VECTOR1(2), VECTOR1(3)
write(*,*) "Vector = ", VECTOR1(1), VECTOR1(2),
+ VECTOR1(3)
else
WRITE(*,*) "Inputdeck value read error"
stop
endif
end do
CLOSE(1)
end program