Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Fortran > [General] Файл Fortran binary -> в ASCII?


Автор: Mormishka 25.8.2010, 17:29
Существуют какие-либо макросы?

Автор: Фантом 25.8.2010, 18:52
А что такое "файл Fortran binary"?

Автор: FCM 26.8.2010, 20:59
Может файл данных записанный из Фортран-программы c FORM = UNFORMATED или BINARY переписать в текстовый?

Автор: Mormishka 27.8.2010, 02:53
Цитата(FCM @ 26.8.2010,  20:59)
Может файл данных записанный из Фортран-программы c FORM = UNFORMATED или BINARY переписать в текстовый?

Да. Какая программа для этого нужна?

Автор: Фантом 27.8.2010, 17:32
Цитата(Mormishka @  27.8.2010,  02:53 Найти цитируемый пост)

Да. Какая программа для этого нужна? 

Формат известен? Если да - проще всего написать еще одну программу на Фортране (это 7-8 строк, не больше), которая этот файл считает и в нужном текстовом виде запишет.

Автор: ertttttt 31.8.2010, 11:29
Фантом, 

Программу написали. При чтении методом open не читает неформатированный файл. Не понятно как сконвертировать файл Fortran binary в ASCII текст. Как это можно сделать? 


Код

program Convert
    character a(100)

    integer i


    OPEN(UNIT = 12, FILE = 'C:\Program Files\Microsoft Visual Studio\MyProjects\Convert_ivanov\x.s', FORM='UNFORMATTED',CONVERT='BIG_ENDIAN',ACTION='READ',IOSTAT=i)

    OPEN(UNIT = 17, FILE = 'C:\Program Files\Microsoft Visual Studio\MyProjects\Convert_ivanov\x_ERROR.s', FORM='FORMATTED',ACTION='WRITE')
    
    do i=1,50
    
        read(12,*) a(i)

        print *, a

    enddo

end program Convert


Автор: kemiisto 31.8.2010, 11:34
ertttttt,  а можно примерчик файла. Расширение у него до боли знакомое... 

А с чего вообще взяли, что это 
Цитата(FCM @  26.8.2010,  21:59 Найти цитируемый пост)
файл данных записанный из Фортран-программы c FORM = UNFORMATED или BINARY

?

Автор: Фантом 31.8.2010, 13:03
Цитата(ertttttt @  31.8.2010,  11:29 Найти цитируемый пост)

Программу написали. При чтении методом open не читает неформатированный файл.

Так ведь какой-то формат для чтения нужен, обойтись чтением под управлением списка в данном случае нельзя.
Вам нужно знать формат, в котором эти данные записаны, в противном случае их можно интерпретировать как угодно (и в самом файле эта информация не содержится).

Автор: Mormishka 31.8.2010, 15:35
Цитата(kemiisto @ 31.8.2010,  11:34)
ertttttt,  а можно примерчик файла. Расширение у него до боли знакомое... 

А с чего вообще взяли, что это 
Цитата(FCM @  26.8.2010,  21:59 Найти цитируемый пост)
файл данных записанный из Фортран-программы c FORM = UNFORMATED или BINARY

?

Файл прикрепил. Это файл линий тока в программе Schlumberger Eclipse. В мануале про него написано, что его можно перевести в ASCII text в Compact Visual Fortran методом open:

Programmers using Compaq Visual Fortran, who wish to read 98A and later PC binary
files will need to use CONVERT=’BIG_ENDIAN’ when they open an unformatted file,
for example.:
OPEN(UNIT=IUNIT,FILE=ZFILE,FORM=’UNFORMATTED’,CONVERT=’BIG_ENDIAN’)
...
Output files may be formatted (ASCII text) or unformatted (Fortran binary).

Автор: kemiisto 31.8.2010, 16:19
Когда читаем из/пишем в unformatted файл, то, естественно, ни о каких форматах чтения/записи речи идти не может. А у Вас READ(12, *). А * эта, между прочим, специфицирует формат ввода/вывода. Фантом писал об этом.

Код

PROGRAM main

  IMPLICIT NONE
  
  INTEGER :: i
  
  OPEN (unit=777, file="ECL_SAMPLE01.SLN0006", form="unformatted",              &
&   convert="big_endian", action="read")

  READ (777) i
  PRINT *, i

END PROGRAM main


Ну и (опять таки Фантом писал об этом), нужно знать что и в какой последовательности писалось в файл, чтобы считать.

Автор: FCM 1.9.2010, 15:52
Цитата(Mormishka @  31.8.2010,  15:35 Найти цитируемый пост)
Файл прикрепил. Это файл линий тока в программе Schlumberger Eclipse. В мануале про него написано, что его можно перевести в ASCII text в Compact Visual Fortran методом open:


Наверное в мануале написано, в каком виде они там записывались - в виде массива конкретной формы (и типа) или в цикле отдельными записями, состоящими из строк массива и/или отдельных чисел определенных типов?

Скорее всего второе, но, как уже отмечалось, нужно знать чего (т.е. какого типа и параметра разновидности ) и сколько чисел в записи - ведь один и тот же набор двоичой информации по-разному интерпретируется для разных типов.


Автор: Mormishka 1.9.2010, 16:57
FCM, 

Наверное вы это имеете ввиду?

Output files are written in a general format which consists of data arrays, each headed
by a data descriptor record. The header record consists of:
• An 8-character keyword which identifies the data in the block. Valid keywords are
described in the following chapters. Where appropriate, the keyword may be a
property, region or solution name. Use of names containing embedded blanks is
not recommended.
• A 4-byte integer defining the number of elements in the block.
• A 4-character keyword defining the type of data in the block.
Possible types are:
INTE standard (4 byte) integers
REAL single precision (4 byte) floating point reals
LOGI standard (4 byte) logicals
DOUB double precision (8 byte) floating point reals
CHAR characters (handled as 8-character words)
C0nn CHARACTER*nn strings (e.g. C065 for 65-character strings)
If the file is unformatted, the three header items are read as a single physical record. If
the file is formatted, the following Fortran format is used:
(1X, 1X, A8, 1X, 1X, I11, 1X, 1X, A4)
In ECLIPSE formatted output files, the character strings are surrounded by single
quotes for readability.
The data contents follow the descriptor (starting on a new record). Numerical arrays
are divided into blocks of up to 1000 items each. Character data are divided blocks of
up to 105 8-character words each. For unformatted files, the physical record size is the
same as the block size. Formatted files consist of 80-character physical records, read
using the following Fortran formats:
Integer 6(1X, I11)
Real 4(1X, E16.8)
Logical 25(1X, L2)
Double Precision 3(1X, D22.14)
Character 7(1X, 1X, A8, 1X)
Character*nn (1X, 1X, Ann, 1X), repeated if possible
within 80 characters
In ECLIPSE formatted output files, the 8-character words are surrounded by single
quotes for readability.
Note that multidimensional arrays are ordered according to the Fortran convention,
with the left-hand index increasing fastest. For example, in a full array of cell values for
a grid with dimensions NX*NY*NZ, the position of cell (IX,IY,IZ) would be given
by:
ICELL = (IZ-1)*NX*NY + (IY-1)*NX + IX

Автор: FCM 1.9.2010, 20:21
Навскидку, сделаем черновой прогон

Код

character(8) :: chname
integer(4)    :: num
character(4) :: chtype 

open(11,...)

do
    read(11)  chname, num, chtype
    write(*,*) chname, num, chtype
endo



В результате получим вывод (проверьте!)

INTEHEAD         10    INTE
...
GEOMETRY   26460   DOUB
....
GEOMINDX       238  INTE
...
ID_BEG            237  INTE
...
ID_END            237  INTE
...
ID_CELL         8583  INTE
...
TIME_BEG       8820  DOUB
...
SWAT              8583  DOUB
...

Т.е. в чистовом прогоне нужно последовательно  считывать  chname,num,chtype (как единую запись) и следующие за ними массивы из  num -чисел  chtype-типа (скорее всего как единую запись).


Автор: Mormishka 2.9.2010, 02:01
Попробую. Вот образец другого файла в мануале в ASCII text

INTEHEAD 10 INTE
2 1 3 1 20 10 1997 23 50 41
GEOMETRY 42 DOUB
25. 24. 2000. 20. 23. 2000. 13. 20. 2000. 10. 17. 2000. 8. 14. 2000. 6. 10. 2000.
5. 5. 2000. 25. 24. 2000. 22. 20. 2000. 20. 15. 2000. 15. 10. 2000. 14. 9. 2000.
10. 7. 2000. 5. 5. 2000.
GEOMINDX 3 INTE
1 22 43
ID_BEG 2 INTE
2 2
ID_END 2 INTE
1 1
ID_CELL 12 INTE
9 8 5 4 4 1 9 6 5 2 2 1
TIME_BEG 14 DOUB
4.2333 7.33 18.84 24.7 29.13 34.25 41. 4. 7. 17.84 20.7 23.3300 31.05 40.
SWAT 12 DOUB
0.75 0.575 0.5 0.4 0.225 0.05 0.5 0.575 0.4 0.3 0.225 0.35
GEOMETRY 15 DOUB
30. 5. 2000. 20. 4. 2000. 26. 3. 2000. 10. 2. 2000. 5. 5. 2000.
GEOMINDX 2 INTE
1 16
ID_BEG 1 INTE
3
ID_END 1 INTE
1
ID_CELL 4 INTE
3 2 2 1
TIME_BEG 5 DOUB
4.2333 7.3300 18.8400 24.7000 29.1300
SWAT 4 DOUB
0.7500 0.5750 0.5000 0.4000

Автор: ertttttt 2.9.2010, 07:40
Первые три числа прочитал. Дальше не хочет читать. Здесь другой файл этого же типа. Я поменял название на «x.s». Для меня пока важно вывести на экран, что идет после ключевого слова GEOMETRY. В данном файле после GEOMETRY идет число 162, т.е. всего 162 числа должно быть.

    program Convert

    implicit none

    integer i

    real(8) ::r1
    real(8) ::r2
    real(8) ::r3

    
    character(8) :: chname
    integer(4) :: num
    character(4) :: chtype

    open(unit=777, file='x.s', form='unformatted',convert='big_endian', action='read')

    do

        read (777) chname, num, chtype

        write(*,*) chname, num, chtype

        if (chname=='GEOMETRY') then
            do i=1,num
                read (777) r1,r2,r3
                write(*,*) r1,' ',r2,' ' ,r3,' ',i, ' ' ,num
            enddo
        end if

    enddo

    end program Convert

На экране:

INTEHEAD          10 INTE
    ☻   ☺           3    ♥
 GEOMETRY         162 DOUB
   450.000000000000          450.000000000000          2025.00000000000
           1           162
forrtl: severe (67): input statement requires too much data, unit 777, file C:\P
rogram Files\Microsoft Visual Studio\MyProjects\Proect\Debug\x.s

Автор: FCM 2.9.2010, 07:41
Я тут прикинул одну програмку (в gfortran) -  первый массив считывается корректно, а потом некорректно.
По-видимому неверно считывается число элементов в массиве. Надо еще подумать. Может "местные жители" что подскажут.

Код

PROGRAM MAIN
  IMPLICIT NONE
  CHARACTER(8) :: CHNAME
  INTEGER(4) :: NUM, IFLAG
  CHARACTER(4) :: CHTYPE
  INTEGER(4), ALLOCATABLE  :: I_DATA(:)
  REAL(4),    ALLOCATABLE  :: R4_DATA(:)
  REAL(8),    ALLOCATABLE  :: R8_DATA(:)
  WRITE(*,*) 'ENTER IFLAG (0 - prikidka, 1 - final)'
  READ(*,*) IFLAG
  OPEN( 11, FILE="ECL_SAMPLE01.SLN0006", FORM="UNFORMATTED" ,  &
   CONVERT = "BIG_ENDIAN", ACTION = "READ")
  OPEN( 12, FILE="ECL_SAMPLE01.TXT", FORM="FORMATTED" )
  DO
     READ (11,ERR = 901)   CHNAME, NUM, CHTYPE
     WRITE(*,*)  CHNAME, NUM, CHTYPE
     WRITE(12,*) CHNAME, NUM, CHTYPE

     IF(IFLAG == 0)     CYCLE

     SELECT CASE (CHTYPE(1:1))
        CASE('I')
            ALLOCATE (I_DATA(NUM))
           READ(11, ERR = 901)   I_DATA
           WRITE(*,*) I_DATA
           WRITE(12,*) I_DATA
           DEALLOCATE(I_DATA)
        CASE('R')
            ALLOCATE (R4_DATA(NUM))
           READ(11,ERR = 901)   R4_DATA
           WRITE(*,*) R4_DATA
           WRITE(12,*) R4_DATA
           DEALLOCATE(R4_DATA)
        CASE('D')
           ALLOCATE (R8_DATA(NUM))
           READ(11,ERR = 901)   R8_DATA
           WRITE(*,*) R8_DATA
           WRITE(12,*) R8_DATA
           DEALLOCATE(R8_DATA)
     END SELECT

  ENDDO

901 CLOSE(11); CLOSE(12); WRITE(*,*) 'FILES HAVE BEEN CLOSED!'

END PROGRAM MAIN

 
В Visual Fortran цикл можно записать как  DO WHILE(  EOF(11)  )  

при iflag не равном нулю, получаем
 INTEHEAD          10 INTE
           2           1           3           6          30          12        2005           0           0           0
 GEOMETRY       26460 DOUB 
- далее некорректно (fortran run time error - end of record    )
Видимо число 26460 не соответствует реальности (хотя размер файла достаточен для такого массива) или, скорее всего, программа пока не соответствует  smile /

PS/
при iflag = 0

 INTEHEAD          10 INTE

   ...
 GEOMETRY       26460 DOUB
   ...
 GEOMINDX         238 INTE
   ...   
 ID_BEG           237 INTE
   ...
 ID_END           237 INTE
   ...
 ID_CELL         8583 INTE
   ...
 TIME_BEG        8820 DOUB
   ...
 SWAT            8583 DOUB
   ... 
 далее fortran run time error - end of file    

Автор: FCM 2.9.2010, 09:25
Кажется нашел - в доках написано, что массивы разбиваются на блоки (записи?) по 1000 элементов (Numerical arrays are divided into blocks of up to 1000 items each.).
Подправил - проверьте (no warranty - до конца не уверен, надо ли неполную тысячу рассматривать как неполную (что реализовано ниже) или, все-таки, надо как полную)
Код

PROGRAM MAIN           ! mingw-gfortran
  IMPLICIT NONE

  CHARACTER(8) :: CHNAME
  INTEGER(4) :: NUM, IFLAG, I
  CHARACTER(4) :: CHTYPE
  INTEGER(4), ALLOCATABLE  :: I_DATA(:)
  REAL(4),    ALLOCATABLE  :: R4_DATA(:)
  REAL(8),    ALLOCATABLE  :: R8_DATA(:)

  WRITE(*,*) 'ENTER IFLAG (0 - FIRST, 1 - FINAL)'
  READ(*,*) IFLAG
  OPEN( 11, FILE="ECL_SAMPLE01.SLN0006", FORM="UNFORMATTED" ,  &
                   CONVERT = "BIG_ENDIAN", ACTION = "READ")
  OPEN( 12, FILE="ECL_SAMPLE01.TXT", FORM="FORMATTED" )

  DO

     READ (11,ERR = 901)   CHNAME, NUM, CHTYPE
     WRITE(*,*)  CHNAME, NUM, CHTYPE
     WRITE(12,*) CHNAME, NUM, CHTYPE

     IF( IFLAG == 0 )     CYCLE

     IF( CHTYPE == 'INTE' )  THEN  !----------------------------------------
           ALLOCATE(  I_DATA(NUM)  )
           DO I = 1, NUM/1000 + 1
                IF ( I < NUM/1000 + 1 ) THEN
                    READ(11,ERR = 901)   I_DATA(1000*(I-1)+1 : 1000*I)
                    WRITE(*,*)  I_DATA(1000*(I-1)+1:1000*I)
                    WRITE(12,*) I_DATA(1000*(I-1)+1:1000*I)
                ELSE
                    READ(11,ERR = 901)   I_DATA(1000*(I-1)+1 : NUM)
                    WRITE(*,*)  I_DATA(1000*(I-1)+1 : NUM)
                    WRITE(12,*) I_DATA(1000*(I-1)+1 : NUM)
                ENDIF
           ENDDO
           DEALLOCATE( I_DATA )
     ELSE IF ( CHTYPE == 'REAL' )   THEN  !----------------------------------------
           ALLOCATE ( R4_DATA(NUM) )
           DO I = 1, NUM/1000 + 1
                IF ( I < NUM/1000 + 1) THEN
                    READ(11,ERR = 901)   R4_DATA(1000*(I-1)+1 : 1000*I)
                    WRITE(*,*)  R4_DATA(1000*(I-1)+1 : 1000*I)
                    WRITE(12,*) R4_DATA(1000*(I-1)+1 : 1000*I)
                ELSE
                    READ(11,ERR = 901)   R4_DATA(1000*(I-1)+1 : NUM)
                    WRITE(*,*)  R4_DATA(1000*(I-1)+1 : NUM)
                    WRITE(12,*) R4_DATA(1000*(I-1)+1 : NUM)
                ENDIF
           ENDDO
           DEALLOCATE( R4_DATA )
      ELSE IF ( CHTYPE == 'DOUB' )  THEN  !----------------------------------------
           ALLOCATE ( R8_DATA(NUM) )
           DO I = 1, NUM/1000 + 1
                IF ( I < NUM/1000 + 1 )  THEN
                    READ(11,ERR = 901)   R8_DATA(1000*(I-1)+1 : 1000*I)
                    WRITE(*,*)  R8_DATA(1000*(I-1)+1:1000*I)
                    WRITE(12,*) R8_DATA(1000*(I-1)+1:1000*I)
                ELSE
                    READ(11,ERR = 901)   R8_DATA(1000*(I-1)+1 : NUM)
                    WRITE(*,*)  R8_DATA(1000*(I-1)+1 : NUM)
                    WRITE(12,*) R8_DATA(1000*(I-1)+1 : NUM)
                ENDIF
           ENDDO
           DEALLOCATE (R8_DATA)
    ENDIF !----------------------------------------

  ENDDO

  901 CLOSE(11); CLOSE(12); WRITE(*,*) 'FILES HAVE BEEN CLOSED!'

END PROGRAM MAIN


Автор: ertttttt 2.9.2010, 11:21
FCM, 
Огромная благодарность! С кодом буду разбираться.
Работает. Только в конце оборвался. Пишет 
severe (24): end-of-file during read, unit 11,

Автор: FCM 2.9.2010, 11:25
Так и должно быть - это недостаток приведенной программы.
Если пользуешься Visual Fortran, попробуй в самом внешнем цикле вместо 
DO
записать 
DO WHILE (.NOT.EOF(11))

Автор: ertttttt 2.9.2010, 12:38
Какой тип данных использовать для имени файла? Как сделать, чтоб можно вводить имя файла?

WRITE(*,*) 'ENTER FILENAME'
 READ(*,*) FNAME

Автор: FCM 2.9.2010, 12:51
Код

    CHARACTER(100) :: FNAME
    WRITE(*,*) 'ENTER FILENAME'
    READ(*,*) FNAME
    OPEN(11, FILE = TRIM(FNAME), ...)


Удобно вводить только изменяющуюся часть имени - см
http://forum.vingrad.ru/forum/topic-278045/kw-%D0%B3%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D1%8F-%D0%BD%D0%B0%D0%B7%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0.html

Автор: Mormishka 4.9.2010, 13:56
Разобрался с этим.
Не получается работать с динамическим массивом GEOMETRY. Пишет:
X=  0.000000000000000E+000
 Y=  0.000000000000000E+000
 Z=  0.000000000000000E+000
forrtl: severe (161): Program Exception - array bounds exceeded
Image              PC        Routine            Line        Source
Convert_plus_spec  00402590  MAIN                       62  Convert_plus_spec.f9
0

Код

PROGRAM MAIN
  IMPLICIT NONE
  CHARACTER(8) :: CHNAME
  INTEGER(4) :: NUM, I,J,K,NX,NY,NZ,N,TEMP
  CHARACTER(4) :: CHTYPE
  REAL(8),    ALLOCATABLE  :: GEOMETRY(:)
  CHARACTER(50) :: FNAME
  
  REAL(8) :: DX,DY,DZ,X,Y,Z
  INTEGER(4) :: cube(1:10,1:10,1)
  NX=10
  NY=10
  NZ=1
  DX=100
  DY=100
  DZ=50
  
  DO I=1,NX
    DO J=1,NY
        DO K=1,NZ
            CUBE(I,J,K)=0
        ENDDO
    ENDDO
  ENDDO

  WRITE(*,*) 'ENTER FILENAME'
  READ(*,*) FNAME

  OPEN( 11, FILE=FNAME, FORM="UNFORMATTED" ,  &
                   CONVERT = "BIG_ENDIAN", ACTION = "READ")
  FNAME='CONVERTTED_'//FNAME
  OPEN( 12, FILE=FNAME, FORM="FORMATTED" )

DO WHILE (not (EOF(11)))
    READ (11,ERR = 901)   CHNAME, NUM, CHTYPE
    WRITE(*,*)  CHNAME, NUM, CHTYPE
    IF (CHNAME=='GEOMETRY') THEN 
        ALLOCATE ( GEOMETRY(NUM) )
        DO I = 1, NUM/1000 + 1
            IF ( I < NUM/1000 + 1 )  THEN
                READ(11,ERR = 901)   GEOMETRY(1000*(I-1)+1 : 1000*I)
                WRITE(*,*)  GEOMETRY(1000*(I-1)+1:1000*I)
                WRITE(12,*) GEOMETRY(1000*(I-1)+1:1000*I)
            ELSE
                READ(11,ERR = 901)   GEOMETRY(1000*(I-1)+1 : NUM)
                WRITE(*,*)  GEOMETRY(1000*(I-1)+1 : NUM)
                WRITE(12,*) GEOMETRY(1000*(I-1)+1 : NUM)
            ENDIF
        ENDDO
        PRINT *,'NUM=',NUM
        N=1
        DO 
            PRINT *,'X=',X
            PRINT *,'Y=',Y
            PRINT *,'Z=',Z
            X=GEOMETRY(N)
            Y=GEOMETRY(N+1)
            Z=GEOMETRY(N+2)
            I=X/DX+1
            J=Y/DY+1
            K=Z/DZ+1
            CUBE(I,J,K)=1
            N=N+3
            IF (N>=NUM) EXIT
        ENDDO
        DO I=1,NX
            DO J=1,NY
                DO K=1,NZ
                    PRINT *,CUBE(I,J,K)
                ENDDO
            ENDDO
            PRINT *,'\'
       ENDDO
       DEALLOCATE (GEOMETRY)
    ENDIF   
     

ENDDO

  901 CLOSE(11); CLOSE(12); WRITE(*,*) 'FILES HAVE BEEN CLOSED!'

END PROGRAM MAIN


Автор: FCM 4.9.2010, 15:34
В приведенной диагностике указано на line 62 твоего листинга 
CUBE(I,J,K)=1
По видимому в программе заложена ошибка с определеним I,J, K 

В чем вообще идея с этим CUBE. Зачем он вводится?
В связи с CUBE там еще вводятя NX, DX и т.п. - они должны быть одинаковыми для любого считываемого файла или привязаны к конкретному файлу?

Можно чуть улучшить начало программы:
В данном конкретном случае вместо 
Код

INTEGER(4) :: NUM, I,J,K,NX,NY,NZ,N,TEMP
 
  REAL(8) :: DX,DY,DZ,X,Y,Z
  INTEGER(4) :: cube(1:10,1:10,1)
  NX=10
  NY=10
  NZ=1
  DX=100
  DY=100
  DZ=50

  DO I=1,NX
    DO J=1,NY
        DO K=1,NZ
            CUBE(I,J,K)=0
        ENDDO
    ENDDO
  ENDDO


можно написать

Код

  INTEGER(4), PARAMETER :: NX = 10, NY = 10, NZ =1
  REAL(8) :: DX = 100.d0, DY = 100.d0, DZ = 50.d0, X, Y, Z
  INTEGER(4) :: CUBE(NX,NY,NZ) = 0


Автор: Mormishka 4.9.2010, 16:17
FCM, 
NX, DX и т.п должны считываться с другого файла. Но это думаю сделать можно потом.
Есть прямоугольная область с ортогональными координатами. Последовательность чисел после ключевого слова GEOMETRY это координаты линий тока записанные в последовательности x1,y1,z1,x2,y2,z2...xn,yn,zn. Есть сетка, т.е. вся облать разбита на ячейки размером dx,dy,dz кол-вом Nx,Ny,Nz. Мне надо сделать куб, т.е. трехмерный массив в котором содержится информация о том есть ли в заданной ячейки с координатами i,j,k cube(i,j,k) (0 - нет, 1 -есть) линия тока или нет.(пока я хочу сделать так, потом мне нужно будет разделять линии тока идущие от одной скважины к другой).
В файл куб(массив) нужно записать построчно в обычный текстовый файл, т.е.
a(1,1,1) a(2,1,1) ... a(nx,1,1) 
a(1,2,1) a(2,2,1) ... a(nx,2,1)
... 
a(1,ny,1) a(2,ny,1) ... a(nx,ny,1)
...
a(1,ny,1) a(2,ny,1) ... a(nx,ny,1)
...
al(nx,ny,1) a(nx,ny,2) ... a(nx,ny,nz)
Так написано в мануале: Grid blocks are ordered with the X axis index cycling fastest, followed by the Y and Z axis
indices.
Я не понимаю только как переходить на новую строку.

Автор: FCM 4.9.2010, 16:37
Цитата(Mormishka @  4.9.2010,  16:17 Найти цитируемый пост)
на ячейки размером dx,dy,dz кол-вом Nx,Ny,Nz.

что то я пока  не понимаю  насчет размеров 100 100 50 и как они соотносятся с количеством элеиентов в CUBE.

Как ты проверяешь принадлежность ячейке?

Автор: Mormishka 4.9.2010, 16:57
FCM, 
всего ячеек Nx*Ny*Nx.  Т.е. cube(Nx,Ny,Nz). dx,dy,dz это размер каждой ячейки. Т.е. есть как бы две системы координат:
1) ортогональная (x,y,z), где x,y,z вещественные
2) сетка, ячейки размером dx,dy,dz, координы (i,j,k), i,j,k-натуральные числа

Проверить можно так, GEOMETRY это массив который содержит координаты линий тока, который считали с файла 
Код

DO 
    X=GEOMETRY(N)
    Y=GEOMETRY(N+1)
    Z=GEOMETRY(N+2)
    I=X/DX+1
    J=Y/DY+1
    K=Z/DZ+1
    CUBE(I,J,K)=1
    N=N+3
    IF (N>=NUM) EXIT
ENDDO


Автор: FCM 4.9.2010, 18:00
Добавь отладочную печать - посмотри согласуются ли значения I,J,K и заявленные размеры CUBE

Код

        N=1
        DO  WHILE( N <= NUM-2 )
            X=GEOMETRY(N);    Y=GEOMETRY(N+1);  Z=GEOMETRY(N+2)
            I=X/DX+1;         J=Y/DY+1;         K=Z/DZ+1
            CUBE(I,J,K) = 1
         ! --------------------------------------------------------------------------
            WRITE(*,*) 'IJK = ',I,J,K, '  cube = ', CUBE(I,J,K)   ! отладочная печать
         ! --------------------------------------------------------------------------
            N=N+3
        ENDDO


Цитата

Так написано в мануале: Grid blocks are ordered with the X axis index cycling fastest, followed by the Y and Z axis indices.
Я не понимаю только как переходить на новую строку.


Из английской цитаты следует ли делать вывод, что в записи (строке) по NX чисел?
Есть какие-нибудь дополнительные сведения? В Grid blocks - под blocks что понимается?
Если предположить, что надо записывать по NX  чисел в строке (записи), то попробуй (после того, как разберешься с третьим измерением в CUBE) так
Код

        DO K=1,NZ
            DO J=1,NY
                    WRITE(UNIT,*)   ( CUBE(I,J,K), I=1,NX )
            ENDDO
        ENDDO

где UNIT номер "устройства"  вывода
 

Автор: ertttttt 6.9.2010, 07:20
Код

        DO K=1,NZ
            DO J=1,NY
                    WRITE(UNIT,*)   ( CUBE(I,J,K), I=1,NX )
            ENDDO
        ENDDO

Выдало такой результат:
           1           1           0           0           0           0
           1           1           1           1
           1           1           1           0           0           1
           0           1           1           0
           1           0           1           1           0           1
           1           0           0           0
           1           1           1           1           1           1
           1           1           1           1
           1           0           0           1           1           1
           1           1           1           1
           1           0           0           1           1           1
           1           0           1           1
           1           0           0           1           1           0
           1           0           1           1
           1           0           1           1           0           0
           1           0           1           1
           1           1           1           0           0           1
           0           0           1           1
           1           1           1           1           1           1
           0           0           0           1
Почему он оставляет пробелы? Как сделать, чтоб был только один пробел между цифрами?
 

Автор: FCM 6.9.2010, 08:59
Пробелы оставляет потому, что используются правила форматировани по умолчанию. Можно задать явно для каждого элемента I2, где 2 - кол-во позиций (одна под однозначное число, другая под пробел)
или
I0,1X - где I0 автоматически подстроится под кол-во знаков в целом числе, а 1X - не что иное как 1 пробел.
Код

       DO K=1,NZ
            DO J=1,NY
                    WRITE( UNIT, '(100I2)' )   ( CUBE(I,J,K), I=1,NX )
                  ! или  WRITE( UNIT, '(100(I0,1X))' )   ( CUBE(I,J,K), I=1,NX )
            ENDDO
        ENDDO


(100 - задано с запасом (главное, чтобы было  >=  NX).
В принципе можно и точно указать по кол-ву элементов:
(в Visual Fortran вместо него можно попробовать вставить <NX>, т.е.
Код

    WRITE( UNIT, '(<NX>I2)' )   ( CUBE(I,J,K), I=1,NX )

в других Фортранах сформировав соответствующую строку с впечатыванием в нее NX),
но результативно это ничего не изменит.)

Автор: ertttttt 6.9.2010, 11:35
FCM, 
Помогло.
Теперь немного улучшаю алгоритм создания массива cube. 
Код

IF ((MOD (X,DX)<>0) .AND. (MOD (Y,DY)<>0)) CUBE(I+1,J+1,K)=9
IF ((MOD (X,DX)==0).AND.(MOD (Y,DY)<>0)) THEN
CUBE(I+1,J,K)=9
CUBE(I,J,K)=9
ENDIF
IF ((MOD (X,DX)<>0).AND.(MOD (Y,DY)==0)) THEN
    CUBE(I,J+1,K)=9
    CUBE(I,J,K)=9
ENDIF
IF ((MOD (X,DX)==0).AND.(MOD (Y,DY)==0)) THEN
    CUBE(I,J+1,K)=9
    CUBE(I+1,J,K)=9
    CUBE(I,J,K)=9
    CUBE(I+1,J+1,K)=9
ENDIF


Жалуется на "<>". Как будет "не равно"?

Код

--------------------Configuration: Convert_plus_spec - Win32 Debug--------------------
Compiling Fortran...
C:\Program Files\Microsoft Visual Studio\MyProjects\Convert_plus_spec\Convert_plus_spec.f90
C:\Program Files\Microsoft Visual Studio\MyProjects\Convert_plus_spec\Convert_plus_spec.f90(63) : Error: Syntax error, found '>' when expecting one of: ( <IDENTIFIER> <CHAR_CON_KIND_PARAM> <CHAR_NAM_KIND_PARAM> <CHARACTER_CONSTANT> <INTEGER_CONSTANT
> ...
   IF ((MOD (X,DX)<>0) .AND. (MOD (Y,DY)<>0)) CUBE(I+1,J+1,K)=9
----------------------------------------^
C:\Program Files\Microsoft Visual Studio\MyProjects\Convert_plus_spec\Convert_plus_spec.f90(63) : Error: Syntax error, found '>' when expecting one of: ( <IDENTIFIER> <CHAR_CON_KIND_PARAM> <CHAR_NAM_KIND_PARAM> <CHARACTER_CONSTANT> <INTEGER_CONSTANT
> ...
   IF ((MOD (X,DX)<>0) .AND. (MOD (Y,DY)<>0)) CUBE(I+1,J+1,K)=9
--------------------------------------------------------------^
C:\Program Files\Microsoft Visual Studio\MyProjects\Convert_plus_spec\Convert_plus_spec.f90(64) : Error: Syntax error, found '>' when expecting one of: ( <IDENTIFIER> <CHAR_CON_KIND_PARAM> <CHAR_NAM_KIND_PARAM> <CHARACTER_CONSTANT> <INTEGER_CONSTANT
> ...
   IF ((MOD (X,DX)==0).AND.(MOD (Y,DY)<>0)) THEN
------------------------------------------------------------^
C:\Program Files\Microsoft Visual Studio\MyProjects\Convert_plus_spec\Convert_plus_spec.f90(68) : Error: Syntax error, found '>' when expecting one of: ( <IDENTIFIER> <CHAR_CON_KIND_PARAM> <CHAR_NAM_KIND_PARAM> <CHARACTER_CONSTANT> <INTEGER_CONSTANT
> ...
   IF ((MOD (X,DX)<>0).AND.(MOD (Y,DY)==0)) THEN
----------------------------------------^
Error executing df.exe.

Convert_plus_spec.exe - 4 error(s), 0 warning(s)


Автор: kemiisto 6.9.2010, 11:41
Цитата(ertttttt @  6.9.2010,  12:35 Найти цитируемый пост)
Жалуется на "<>". Как будет "не равно"?

/=

Автор: ertttttt 10.9.2010, 08:34
Не пойму на что жалуется. Если убрать ERR = 901 работает. Раньше и так работало.

Разобрался, строки не хватало
901 CLOSE(11); CLOSE(12); WRITE(*,*) 'FILES HAVE BEEN CLOSED!'

Код

    program Flow

    implicit none

    INTEGER(4) :: NUM,NUMG,I
    CHARACTER(4) :: CHTYPE
    REAL(4),    ALLOCATABLE  :: FLOOILI_P(:)
    REAL(4),    ALLOCATABLE  :: FLOOILJ_P(:)
    REAL(4),    ALLOCATABLE  :: FLOWATI_P(:)
    REAL(4),    ALLOCATABLE  :: FLOWATJ_P(:)
    CHARACTER(8) :: CHNAME
    CHARACTER(50) :: FNAME

    WRITE(*,*) 'ENTER FILENAME';READ(*,*) FNAME

    OPEN( 11, FILE=FNAME, FORM="UNFORMATTED" ,  &
                   CONVERT = "BIG_ENDIAN", ACTION = "READ")

    FNAME='TEXT_'//FNAME
    OPEN( 12, FILE=FNAME, FORM="FORMATTED" )

    READ (11) CHNAME, NUM, CHTYPE
    
    DO WHILE (not (EOF(11)))

        READ (11,ERR = 901) CHNAME, NUM, CHTYPE

    ENDDO

    end program Flow



Код

--------------------Configuration: Flow - Win32 Debug--------------------
Compiling Fortran...
C:\Program Files\Microsoft Visual Studio\MyProjects\Flow\Flow.f90
C:\Program Files\Microsoft Visual Studio\MyProjects\Flow\Flow.f90(26) : Error: This label is undefined.   [901]
  READ (11,ERR = 901) CHNAME, NUM, CHTYPE
-------------------------------^
Error executing df.exe.

Flow.exe - 1 error(s), 0 warning(s)

Автор: Mormishka 1.11.2011, 22:06
Опять поднимаю тему, т.к. сейчас возникла необходимость написать программу на си. Не очень понимаю как устроена запись в определенном формате в Фортране. Что значит например запись integer в формате 6(1X,I11) ?

Автор: Фантом 1.11.2011, 22:43
Цитата(Mormishka @  1.11.2011,  23:06 Найти цитируемый пост)
Что значит например запись integer в формате 6(1X,I11) ? 

Такого не бывает. Формат, который Вы указали - это шестикратное повторение одного пробела и целого с 11 позициями.

Автор: Mormishka 2.11.2011, 10:47
Фантом, 
Я вот начал на СИ считывать и в hex редакторе смотреть файл который в топике. Я понял, что фортрана свой какой формат записи в бинарном виде? Как можно на си прочитать что было записано на фортране?

Автор: Фантом 2.11.2011, 15:00
Цитата(Mormishka @  2.11.2011,  11:47 Найти цитируемый пост)
Я вот начал на СИ считывать и в hex редакторе смотреть файл который в топике. Я понял, что фортрана свой какой формат записи в бинарном виде? Как можно на си прочитать что было записано на фортране? 

Э... Вы сами поняли то, что написали? Я - не очень.

"Своего какого формата" нет, и мы это уже обсуждали. 

Автор: Mormishka 2.11.2011, 15:27
В общем проблему почти решил.  Оказывается при записи блока памяти на фортране записывается 4 байта в начале и в конце еще 4 байта.
Кому интересны подробности можете прочитать http://paulbourke.net/dataformats/fortran/

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)