четверг, 14 апреля 2011 г.

Создание списка имён файлов в виде текстового файла

Задача: Нужно получить список названий файлов, содержащихся в некотором каталоге, и записать его в текстовый файл
Методы решения: использование командной строки или cmd


Пусть есть несколько файлов, где записаны некоторые данные. Для обработки в одной программе на фортране ВСЕХ файлов удобно создать список имён этих файлов. Это делается, чтобы вычитывать имена из этого списка и, подставляя названия в оператор OPEN, открывать/закрывать эти файлы в цикле. Но как получить список имён файлов в виде текстового файла?

Одним из вариантов решения этой проблемы является использование командной строки.

Командная строка вызывается обычно по пути:

ПУСК - Все программы - Стандартные - Командная строка

Можно запустить её по-другому:

Пуск - Выполнить - cmd

Полезно знать некоторые команды для ориентирования в командной строке:

ls  - вывод списка файлов и подкаталогов в указанном каталоге
dir - отображает полный путь текущего каталога
cd - вывод имени, либо смена текущего каталога

Пусть все файлы лежат в папке-каталоге, куда вызывается командная строка (C:\Users\Pavel\). Если файлы лежат в другом каталоге, к нему нужно прийти с помощью команды cd, задав либо полный путь (1), либо отображая текущие папки в каталоге командой dir и переходя к ним последовательно при помощи команды cd (2):

(1) cd C:\Users\Pavel\Downloads\Exp_data\

(2) dir
<список файлов и папок. Среди них есть папка Downloads>
cd Downloads
dir
<список файлов и папок. Среди них есть папка Exp_data>
cd Exp_data


* Если после набора хотя бы одного символа в командной строке нажать TAB, то она дополнит этот символ до имени файла или папки, которые есть в текущем каталоге. Повторное нажатие TAB поможет выбрать среди схожих названий (если они есть) нужное.

Собственно теперь само решение. Набираем команду:

dir /b > list.txt

В текущем каталоге будет создан файл с именем "list.txt", в котором будут содержаться имена всех файлов данного каталога + имя нового файла list.txt. Достаточно открыть файл, убрать новое имя и - вуаля - список файлов готов!

воскресенье, 10 апреля 2011 г.

Gfortran reading until EOF. EOF чтение до конца файла

Свободно распространяемый компилятор gfortran (http://ru.wikipedia.org/wiki/GFortran или http://www.gfortran.org/) имеет ряд "проблем" с функциями, которые спокойно работают в других компиляторах фортрана.
Одной из таких проблем является отсутствие возможности чтения до конца файла (EOF) в цикле условия (do while) в таком виде:

integer :: unit
real :: stud4

unit = 10

do while(.not. eof(unit)) ! Обработка данных файла
read(unit) stud4
***
end do

Как же заменить эту функцию в gfortran? Как один из вариантов - написать небольшую подпрограмму чтения файла до конца (до EOF), которая вычислит число строк в файле, и затем вернёт это целое значение n пользователю. Тогда вместо цикла "do while - enddo" ставим цикл "do i =1,n - enddo". Примером реализации такого алгоритма может служить такой вариант:

SUBROUTINE READ_EOF(n,nstrok)

INTEGER, INTENT(in) ::n ! Даётся явное описание входящих в подпрограмму параметров
INTEGER, INTENT(out) :: nstrok ! "-" исходящих из подпрограммы параметров

INTEGER :: nstrok_counter
CHARACTER(1) :: a

ioer=0
nstrok_counter=0
DO WHILE (ioer.eq. 0)
READ(n,*,iostat=ioer) a
nstrok_counter=nstrok_counter + 1
ENDDO
REWIND(n)
nstrok=nstrok_counter-1

RETURN

END

В подпрограмму передаётся номер канала n файла, который надо прочесть до конца (до EOF), и подпрограмма возвращает число строк, содержащихся в файле.

четверг, 7 апреля 2011 г.

Время работы программы

Задача: узнать сколько точно требуется времени для выполнения программы

Решение: подпрограмма CPU_TIME

Иногда полезно знать сколько времени занимает выполнение всех операторов в программе. Для этого (и не только, конечно) в фортране есть встроенная подпрограмма CPU_TIME.

"Подпрограмма CPU_TIME(time) возвращает процессорное время time, тип которого - REAL(4). Единицы измерения времени - секунды; после десятичной точки time содержит две значащих цифры."  
О. В. Бартеньев, Современный ФОРТРАН, стр.202
Размещаем вызов подпрограммы в начале программы после блока неисполняемых операторов (блока объявления переменных) и в конце, перед end. Печатаем на экран (или в файл) разницу результатов вызовов подпрограмм, используя разные переменны. В коде выглядит примерно так:

real(4) :: start_time, finish_time
call cpu_time(start_time)
<Вычисления>
call cpu_time(finish_time)
print *, 'Время вычислений = ', finish_time - start_time

end
О. В. Бартеньев, Современный ФОРТРАН, стр.202

среда, 6 апреля 2011 г.

Integer to character - Character to integer fortran

Задача: превратить переменную типа integer (целое число) в переменную типа character (символьного типа) и наоборот
Решение: символьные переменные как внутренние файлы

Допустим, мы подсчитали число случаев попадания наших данных в некий диапазон значений. Мы хотим отразить эту информацию в названии выходного (пост-обработки) файла. Значит необходимо преобразовать тип целых в символьный тип, ведь в названии файлов могут присутствовать только символьные переменные.
Чтобы решить такую задачу нужно воспользоваться символьными переменными как внутренними файлами, т.е. произвести запись не по канала файла (unit), а напрямую в символьную переменную по формату целого типа. В коде это выглядит примерно так:

INTEGER :: data ! Исходное значение - оно нам известно
CHARACTER(3) :: string ! Символьная переменная - то, что хотим получить
WRITE (string, '(I3)' ) data ! Операция записи целого по формату в символьную переменную

Чтобы произвести обратное преобразование (из character в integer), нужно воспользоваться другой схемой:

CHARACTER(3) :: string !
Исходный символ - он нам известен
INTEGER :: data ! Переменная целого типа - то, что хотим получить
READ (string, '(I3)' ) data ! Операция чтения символьной переменной по формату в целое

"Используя оператор WRITE, в строку можно передать данные любых типов. И наоборот, оператором READ из строки можно считать, например, числовые данные (если в строке есть числовые поля данных). Часто при помощи оператора WRITE числовые данные преобразовываются в символьные, например число 123 в строку '123', а также формируются
строки, состоящие из смеси числовых и символьных данных.

О. В. Бартеньев, Современный ФОРТРАН, стр.72

вторник, 5 апреля 2011 г.

ПРАКТИКУМ. Элементарные статистики

В этом практикуме мы рассмотрим код стандарта fortran77 на примере программы вычисления элементарных статистик. Программа взята из Библиотеки численного анализа НИВЦ МГУ

Подпрограмма: BS01R
Назначение: вычисление среднего, среднего отклонения, среднеквадратического отклонения и дисперсии заданной выборки

      SUBROUTINE BS01R(DATA,N,AVE,ADEV,VAR,SDEV)
      DIMENSION DATA(N)
      INTEGER N,J
      REAL DATA,AVE,ADEV,VAR,SDEV,S,P,ABS,SQRT
C      IF(N.LE.1)PAUSE 'N must be at least 2'
      S=0.
      DO 11 J=1,N
        S=S+DATA(J)
11    CONTINUE
      AVE=S/N
      ADEV=0.
      VAR=0.
      DO 12 J=1,N
        S=DATA(J)-AVE
        ADEV=ADEV+ABS(S)
        P=S*S
        VAR=VAR+P
12    CONTINUE
      ADEV=ADEV/N
      VAR=VAR/(N-1)
      SDEV=SQRT(VAR)
      RETURN
      END
---------------------------------------------------------------

Рассмотрим особенности синтаксиса программы:

1) В блоке объявления переменных после указания типа переменной сразу идёт именование переменной ( INTEGER N,J ).

2) Пятая строчка начинается с символа "С" - это значит, что данная строка за комментирована, т.е. компилятор будет игнорировать эту строчку.

3) Циклы оформлены в виде меток, т.е. тело цикла для переменной J заканчивается меткой "11". Рядом с меткой 11 (которая может занимать с 2 по 5 включительно позиции от начала строки ) стоит оператор CONTINUE. Он ничего не выполняет, но необходим для объявления самой метки. Саму по себе метку (без других операторов, таких как CONTINUE) ставить нельзя.

4) При присваивании действительным переменным типа real ставится точка после целой части (S=0.) . Это не требование синтаксиса, но страхует от некоторых ошибок.

5) SQRT и ABS - не переменные, а встроенные функции фортрана извлечения квадратного корня и взятия модуля. Хотя по синтаксису они мало отличаются от массивов, обычно эти функции "подкрашиваются" IDE, т.е. той программной оболочкой, где Вы пишете программу.

FORTRAN77

Фортран бывает разный. Точнее, его компиляторы. Ну и версии-стандарты, конечно.
На русской Википедии (http://ru.wikipedia.org/wiki/Fortran) дается вполне исчерпывающая информация о том, что такое Фортран, и краткая история его развития.
В этом посте я бегло рассмотрю 77-ую версию (в широком смысле) фортрана.

FORTRAN77

Самым старым из "доживших" до сегодняшнего дня является стандарт FORTRAN77. "Семьдесят седьмой фортран" - довольно архаичный, но тем не менее до сих пор активно использующийся учёными-метеорологами стандарт. Это объясняется как привычкой, так и тем, что многие старые, но не устаревшие подпрограммы и программы, написаны именно на fortran77. Файлы стандарта 77-го фортрана легко узнать по расширениям *.f или *.for, например: test.for или test.f
Какие же у него плюсы и минусы? 

(-) Минусы:

1) Несмотря на то, что этот стандарт к сегодняшнему дню значительно расширен дополнительными функциями, в нём сохранилось ограничение на 72 знака в строке, необходимость в 6 позициях для меток (именно в шестой позиции любой символ превращается в знак объединения предыдущей и текущей строки). Для объявления символьных констант и больших формул иногда это бывает неудобно.Кстати, именно по этой причине в старых программах отсутствуют пробелы между символами - сказывается привычка экономить место в коде.

2) Отсутствие таких функций и операторов, как SELECT CASE, ALLOCATE, MODULE, PRIVATE, PUBLIC, CONTAINS, INTERFACE, USE, INTENT.

3) Этот стандарт использует отличный от последующих версий синтаксис. Так, например для комментирования строки используется символ "с" в первой позиции (в fortran90 и далее используется символ "!"). Синтаксис циклов также другой - используются метки вместо enddo (это уже fortran90):

      do 88 i=1,100
      pro(i)=dat1(i*num)
 88 continue

Отличия также есть в объявлении переменных и других операторах.

4) Как и любой старый стандарт со временем он будет полностью заменён на новый. Рано или поздно придётся переходить на новый стандарт.

(+) Плюсы:

1) Наличие огромного количества разнообразных подпрограмм в стандарте fortran77. Это ОЧЕНЬ серьёзный аргумент для использования данного стандарта.

2) Многие современные компиляторы успешно поддерживают этот стандарт с возможностями новых стандартов (90, 95 и 2003). Например, компиляторы из Fortran Developer Studio ("df" и "f77") позволяют использовать динамические массивы в 77-ом стандарте файлов.

Резюме:

Будучи старейшим из использующихся стандартов фортрана, при поддержке современных компиляторов, fortran77 остаётся мощным средством обработки научных данных и решения вычислительных задач.

Расширения фортрана-77: "*.for", "*.f", "*.f77"

INTRO

Здравствуй, дорогой читатель!

Вдохновленный блогом Николая Колдунова (http://koldunov.net/), я решил создать родственный блог, который был бы посвящён использованию Fortran, Grads, Surfer, Grapher и другого программного обеспечения на различных ОС (Windows/Linux) в метеорологических и смежных науках. 
Здесь будут публиковаться как различные заметки и обзоры, так и коды программ и подпрограмм. Надеюсь, что данный блог когда-нибудь перерастёт в небольшое пособие по фортрану для начинающих.

Как перевести UV в направление и скорость ветра? How to convert wind UV-components to direction and velocity?

 Всё просто.  def uv2dir(u, v):     '''     Источник:     https://github.com/blaylockbk/Ute_WRF/blob/master/functions/wind_calc...