Чтение и запись двоичных файлов (GrADS) в фортран
Я запускаю модель и записываю вывод модели в двоичный файл (файл GrADS *gra), например, так:
integer,parameter :: nvar =3 ,& !number of variables to be written to file
nx=10,ny=10,& !number of girdboxes in lat & long
nt = 5
integer :: it, & ! loop counter
irec ! Record number
real :: var1(nx,ny), var2(nx,ny),var3(nx,ny)
OPEN(30,file='Outfile.gra',action='write',form='unformatted',access='direct',&
recl=4*nVar*nx*ny,status='replace')
!loop over timesteps
it = 1, nt
irec = irec + 1
WRITE(1,rec=irec) Var1(:,:),Var2(:,:),Var3(:,:)
enddo
Файл можно прочитать в GrADS, и файл *ctl выглядит следующим образом
dset /mypath/Outfile.gra
title MyTitle
options little_endian
xdef 10 linear 1 1
ydef 10 linear 1 1
zdef 1 linear 1.0 1.0
tdef 5 linear 00:00Z01jan2012 1hr
vars 3
var1
var2
var3
endvars
То, что я хотел бы сделать из отдельной программы, это записать все переменные x&y of 1 с шагом 1 раз в текстовый файл. Я пробовал несколько способов, но ничего не помогло. Моя последняя попытка такая:
integer,parameter :: &
t = 3, & !Timestep I want to write to file
field = 2, & !Variable I want to write to file
nvar =3 , & !number of variables to be written to file
nx=10,ny=10, & !number of girdboxes in lat & long
nt = 5 !number of timesteps
inteǵer :: it,ix,iy,& ! loop counters
irec ! Record number
real :: val(nx,ny) ! Data to be written to file
open(1,file='NewFile.txt',status='replace')
open(2,file='Outfile.gra',action='read',form='unformatted',access='direct',&
recl=4*nVar*nx*ny,status='old')
irec = 0
do it = 1,nt
irec=irec + nvar*nx*ny
if(it == t) then
irec = irec + (field-1)*nx*ny
do ix = 1,nx
do iy = 1,ny
irec=irec+1
read(2,rec=irec) val(ix,iy)
enddo
enddo
write(1,*) val(:,:)
Этот конкретный пример дает мне следующую ошибку
Ошибка выполнения Fortran: номер несуществующей записи
но я пробовал другие варианты, которые не давали мне никаких ошибок, но просто не записывали то, что я пытался записать в файл. Может ли кто-нибудь сказать мне, что я делаю неправильно и как это решить? Спасибо.
2 ответа
High Performance Mark и Hristo Iliev определили проблему с номером записи. Для того, чтобы иметь возможность делать то, что я хочу, т.е. написать одну переменную за один шаг, правильный код
irec = 0
do it = 1, t
irec = irec + 1
read(2,rec=irec) val(:,:,:)
enddo
write(1,*) val(:,:,field)
где val(nx,ny,nVar)
ОК, позвольте мне попробовать еще раз. Когда ты пишешь outfile.gra
ты, кажется, пишешь nt
записи к нему в блоке
!loop over timesteps
it = 1, nt
irec = irec + 1
WRITE(1,rec=irec) Var1(:,:),Var2(:,:),Var3(:,:)
enddo
я думаю что irec
инициализируется 0
где-то в коде. nt
установлен в 5
так что, если мое предположение верно, ваш код записывает 5 записей в outfile.gra
,
Позже вы читаете тот же файл в этом блоке
irec = 0
do it = 1,nt
irec=irec + nvar*nx*ny
if(it == t) then
irec = irec + (field-1)*nx*ny
do ix = 1,nx
do iy = 1,ny
irec=irec+1
read(2,rec=irec) val(ix,iy)
enddo
enddo
Неясно, где if
заявление закрывается, но из вашего вопроса, я думаю, что оно закрывается после того, как циклы над nx
а также ny
, как это:
irec = 0
do it = 1,nt
irec=irec + nvar*nx*ny
if(it == t) then
irec = irec + (field-1)*nx*ny
do ix = 1,nx
do iy = 1,ny
irec=irec+1
read(2,rec=irec) val(ix,iy)
enddo
enddo
end if
Опять же, если мое предположение верно, то irec
имеет значение 401
когда read
Оператор сначала выполняется.
Кажется, вы написали 5 записей outfile.gra
и пытаемся прочитать 401-ую запись из него. Для среды выполнения вполне разумно сообщить, что вы пытаетесь прочитать несуществующую запись.