четверг, 26 января 2017 г.

Механические расчеты конструкций в свободном ПО. Часть 1

Введение

Классическая «технология» расчета конструкций МКЭ включает 4 этапа:

  1. Твердотельное моделирование с применением 3D-CAD’ов.

  2. Предпроцессинг: разбиение на конечные элементы.

  3. Расчет.

  4. Постпроцессинг: визуализация и анализ результатов.

В мире существует огромная «армия» коммерческого ПО класса CAD/CAE, решающая эти задачи как вместе – в одной системе-комбайне, так и по отдельности.

В нашей отрасли наиболее популярны для 3D-моделирования SolidWorks, КОМПАС 3D и Autodesk Inventor, а для пунктов 2–4 – либо соответствующие модули в составе этих систем (SolidWorks Simulation, APM-FEM в КОМПАС-3D или Stress Analysis в Inventor Professional), либо – более серьезный ANSYS.

Расчеты – дело ответственное. Для сложных систем лучше использовать профессиональные CAD/CAE-системы.

Однако, например, в нашей практике в 90% случаев приходится иметь дело либо с «очень», либо с «довольно» простыми конструкциями. Для их расчетов отлично зарекомендовал себя рассмотренный ниже свободный софт, справляющиеся с возложенными на него функциями не хуже коммерческих монстров. Применение свободных программ оправдано, когда подобные расчеты приходится делать «время от времени», а сами конструкции (повторюсь) – не слишком сложны. Завязываться на свободный софт по его текущему уровню развития в технологическом цикле машиностроительного проектирования CAD/CAE/CAМ по моему мнению пока преждевременно.

Мы многократно тестировали описанную ниже цепочку программ на предмет адекватности результатов:

  • сравнением с модельными задачами, для которых можно получить аналитическое решение (балки, стержневые системы);

  • сравнением с результатами, полученными в «серьезных» CAD/CAE;

  • испытаниями.

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

Пожалуй, единственный значимый недостаток – это определенное неудобство использования. «Порог входа» довольно высок. На разных этапах приходится применять программы с разными идеологиями и разными не вполне интуитивными интерфейсами. Как в любом свободном ПО, у этих программ немало недоработок. Но, если к их особенностям чуть-чуть попривыкнуть, «рука набивается». Расчеты получается делать достаточно быстро и качественно.

Важное условие – инженер должен понимать, что он делает и иметь определенный багаж теоретических знаний в строительной механике / сопромате и МКЭ. Но без этого – легко «натворить дел» и в коммерческих CAE. Их обманчивая простота «для домохозяек» продуцирует ситуацию, когда за расчеты берутся мало понимающие в них люди. При этом мотивации к изучению теории – не возникает. В итоге мы имеем настоящую эпидемию – море неграмотно сконструированных объектов. Иногда все заканчивается очень печально. В этом смысле, свободный софт, наоборот, мотивирует знать теорию. Без нее, скорее всего, просто ничего не получится. :)

Отметим, что вариантов использования различных программ на разных этапах «технологии» – множество. Перечислю в таблице лишь некоторые:

Этап Возможный свободный (бесплатный) софт
1. 3D-моделирование OpenSCAD, ImplicitCad, FreeCAD, CadQuery, SolveSpace, OnShape, Salome, Calculix cgx, GMSH, BRL-CAD
2. Пред-процессинг GMSH, Salome, NetGen, TetGen
3. Расчет CalculiX cсx, Code_Aster, GetDP, NGSolve
4. Пост-процессинг CalculiX cgx, Salome, GMSH, NetGen, ParaView

Ниже будут рассмотрены варианты программ, на которых мы пока «примерно остановились» с кратким обзором отдельных альтернатив.

Чтобы было не скучно, последовательность расчета будет проиллюстрирована не на классических балках или «пистонах». Поиздеваемся над символом этого блога – звездчатым многогранником «Соединение пяти тетраэдров». Поставим скромную задачу выполнить самый простой линейный расчет напряженно-деформированного состояния. Более интересные нелинейные расчеты, расчеты устойчивости и динамический анализ – также без проблем делаются. Надеюсь о них написать как-нибудь в будущем.

CAD’ы: подготовка 3D-геометрии

OpenSCAD: 3D-моделер для программистов

OpenSCAD – это легкая и простая, но совершенно крутейшая штука. 3D-модели здесь просто «пишутся» на удобном и очень простом языке программирования. Рядом – интерактивно строится результат.


Теоретически на нем можно делать весьма сильные вещи. Умельцы и делают. Когда нужно сформировать что-то «модельное» или «абстрактное» – я тоже с удовольствием его запускаю. Коллеги-конструкторы крутят у виска пальцем. :)

Вообще, идея описания конструкций на языке – на мой взгляд прекрасна. Она не получила развития в коммерческих CAD’ах скорее в силу традиций (не приучены конструкторы к текстам). А ведь достоинств у такого подхода немало:

  1. Текст – прозрачен и гибок. Модель параметризуется и «работает» в точности так, как вы задумали.

  2. Универсальность и выразительность языка – всегда выше GUI.

  3. Текст хорошо «накапливается» и обобщается в библиотеки, которые дальше повторно используются. Уровни абстракций – наращиваются.

  4. Текст не может «испортиться», как непонятный бинарный файл, в котором хранят модели обычные CAD’ы.

  5. С текстом можно использовать системы контроля версий, такие как Git. Одно это очень многого стоит.

  6. Языковая модель CAD наиболее легко интегрируется с узкоспециальными САПР вашей предметной области. Это особенно актуально, если части такой САПР приходится разрабатывать самостоятельно.

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

Не все пункты это перечня реализуются в OpenSCAD. :) Вообще, он – скорее концепт. В реальной работе, когда нужно быстро посчитать что-то не элементарно простое, в нем работать, конечно, не очень удобно. Приходится выбирать средства визуального проектирования, о которых речь пойдет ниже.

Но когда надо сделать что-то «модельное», «математически абстрактное», параметрическое, OpenSCAD – крут. Например, вот описание нашего многогранника:

module tetrahedron(edgeLength){ // Правильный тетраэдр 
    points =  [ [ 1, 1, 1],
                [ 1,-1,-1],
                [-1, 1,-1],
                [-1,-1, 1] ];
    faces  =  [ [ 0, 2, 1],  
                [ 3, 0, 1],  
                [ 0, 3, 2],  
                [ 1, 2, 3] ];    
    scale([1,1,1]*edgeLength/sqrt(8))    
    polyhedron(points, faces);    
}

module fiveTetrahedra(edgeLength){ // Соединение пяти тетраэдров 
    for(i=[0:4]){
        rotate([0,-atan(sqrt(5)/2-0.5), i*360/5])
        tetrahedron(edgeLength);
    } 
}

// ---------------- Модель -------------------
rotate($t*360/5)
fiveTetrahedra(100);    

Просто, лаконично, понятно без комментариев. Если они нужны, на сайте есть хорошая справка в виде «Шпаргалки».

Обратите внимание на простоту языка: операторов и конструкций там очень мало. Он изучается буквально за пару часов, и, кстати, здорово развивает пространственное мышление – намного лучше средств визуального проектирования.

Предпоследняя строчка нашего текста, где выполняется преобразование rotate с параметром $t, позволяет сделать в окне OpenSCAD анимацию. Нельзя удержаться, чтобы не перегнать ее в .gif: :)


Понятно, что анимацию можно сделать для любого параметрического поведения вашей системы, например смоделировать кинематический механизм.

OpenSCAD очень популярен среди любителей 3D-печати. Кстати, они наплодили буквально тонны готовых текстов для разных моделей, открытых для повторного применения. OpenSCAD позволяет сохранять модели в сеточном формате STL, стандартном для 3D-печати.

OpenSCAD – самый известный, но далеко не единственный проект «языкового» CAD. Автор OpenSCAD Мариус Кинтель намерено сохраняет язык простым. Это по-своему здорово, но возможностей языка хватает далеко не всегда. В частности, огорчает отсутствие многих средств, к которым мы привыкли в языках программирования общего пользования. Имеется несколько альтернативных проектов. Основные из них представляют похожие средства описания геометрии вместе с продвинутыми возможностями различных базовых языков программирования.

Альтернативный проект (ссылка) Базовый язык Особенности
1 OpenJSCAD JavaScript Веб-интерфейс
2 CoffeeCAD CoffeeScript Веб-интерфейс
3 RapCAD OpenSCAD с дополнениями Заточен для RepRap-принтеров. GUI, похожий на OpenSCAD.
4 ImplicitCAD OpenSCAD / Haskell Написан целиком на Haskell. Добавляет к языку OpenSCAD много интересных возможностей. В частности, можно легко выполнить сглаживание граней и плавные переходы между частями моделей. Веб-интерфейс + работа из командной строки.
5 OpenSCAD.net OpenSCAD / OpenJSCAD Веб-интерфейс для OpenSCAD / OpenJSCAD
6 CadQuery Python Надстройка к FreeCAD либо веб-интерфейс. Позволяет работать с BREP-геометрией. Предоставляет высокоуровневые абстракции, позволяющие определять модель подобно тому, как описал бы ее человек на родном языке

Я с особым интересом слежу на проектом ImplicitCad (пункт 4), т.к. Haskell – это безумно круто. :) И вообще: проект создает интересный канадский чувак Кристофер Олах, мыслящий очень продвинуто. Но особый интерес для нас представляет пункт 6 – CadCuery (я планирую рассказать о нем немного подробней). Помимо того, что он открывает нам мощь Python, он интересен вот почему.

Огромный недостаток OpenSCAD (а также альтернатив пп. 1-5) для нас заключается в том, что он «мыслит» полигональными сетками, описывающими кривые поверхности приближенно. OpenSCAD базируется на геометрическом ядре CGAL и реализует технологию конструкционной блочной геометрии (CSG) с помощью сеток. По этой причине у него нет возможности сохранять модель в «точном» формате, описывающем геометрию на основе граничных поверхностей (BREP) в форматах .STEP или .BREP. А для последующих расчетов нам крайне желательно иметь геометрию в «точном» формате. Точно также OpenSCAD не может и импортировать геометрию, скажем, из .STEP. Очень жаль: иначе можно было бы использовать части модели, сделанные где-то еще, видоизменяя их на языковом CAD. Всех этих недостатков лишен CadQuery, и о нем я еще напишу.

К счастью, геометрию, описанную в OpenSCAD, «понимает» FreeCAD, в который OpenSCAD входит как один из модулей. Таким образом, можно писать модель в OpenSCAD, а сохранять ее потом в «точном» формате через FreeCAD. На практике, в принципе, это добавляет лишь три клика мышкой.

Для того, чтобы почувствовать разницу в представлениях BREP и с полигональными сетками, а также, чтобы предпроцессору не казалось все слишком элементарным, :) давайте чуть-чуть усложним нашу модель: сделаем объединение пяти тетраэдров с шаром. Для этого изменим концовку программы:

// ---------------- Модель -------------------
rotate($t*360/5)
union() {
    fiveTetrahedra(100);    
    sphere(64*sqrt(6)/4, $fn=100);
}

Здесь радиус шара задан как \( 64\sqrt{6}/{4} \) т.к. для правильного тетраэдра радиус описанной сферы равен \( a \sqrt{6}/{4}\), где \(a\) – длина ребра. Можно проверить, что при \( 100\sqrt{6}/{4} \) сфера опишет наши тетраэдры.

Получаем:


Обратите внимание, что сферическая поверхность отрисована сеткой. $fn=100 – это ее «густота».


(Продолжение следует).

вторник, 24 января 2017 г.

GFortran: доступ к Windows API

Сам вызов функций WinAPI делается на Cи (на примере MessageBox):

// Файл: winapi.c
// *** Вызовы функций Windows API ***
#include <windows.h>

int c_messagebox_(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{ 
    return MessageBox(hWnd, lpText, lpCaption, uType); 
}

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

Для доступа к этим функциям из Фортран-программ целесообразно сделать модуль с обертками:

! Файл: windows.f08
! *** Модуль с интерфейсом к некоторым функциям Windows API ***
module Windows
    use iso_c_binding

    implicit none
    integer(kind=C_LONG), parameter, private :: HWND_DESKTOP       = '00000000'X
    integer(kind=C_LONG), parameter, private :: MB_OK              = '00000000'X
    integer(kind=C_LONG), parameter, private :: MB_ICONERROR       = '00000010'X
    integer(kind=C_LONG), parameter, private :: MB_ICONINFORMATION = '00000040'X

    interface
        function c_messagebox(hWnd, lpText, lpCaption, uType)
            use iso_c_binding
            integer(kind=C_LONG)          :: c_messagebox
            integer(kind=C_LONG), value   :: hWnd, uType
            character(kind=C_CHAR, len=*) :: lpText, lpCaption
        endfunction 
    endinterface

contains 

    subroutine MsgErr(str)   ! Выводит простой MessageBox с ошибкой
        character(*)    :: str
        integer         :: res
        res = c_messagebox(HWND_DESKTOP, str // C_NULL_CHAR, &
              "Ошибка" // C_NULL_CHAR, MB_ICONERROR + MB_OK)
    endsubroutine 

    subroutine MsgInf(str)   ! Выводит простой MessageBox c информацией
        character(*)    :: str
        integer         :: res
        res = c_messagebox(HWND_DESKTOP, str // C_NULL_CHAR, &
              "Информация" // C_NULL_CHAR, MB_ICONINFORMATION + MB_OK)
    endsubroutine

endmodule

Здесь вызов функций из модуля на Си осуществляется через interface с указанием специальных разновидностей типов (C_LONG, C_CHAR), определенных для совместимости с Си в модуле iso_c_binding, входящим в GCC.

NB! В процедурах-обертках к строкам приходится добавлять C_NULL_CHAR.

Для проверки:

! Файл: test.f08
program Test
    use Windows
    call MsgInf("Это информация.")
    call MsgErr("А это ошибка!")
endprogram

Компилируем и запускам:

gcc -c winapi.c
gfortran -c windows.f08
gfortran -c test.f08
gfortran *.o -o test.exe
test.exe

Если все хорошо, получаем:


понедельник, 23 января 2017 г.

Ламповый теплый Fortran

Introduction

Инженер на любом языке программирования программирует на Fortran.

Это шутка, но, как обычно, только отчасти. :)

Fortran – старейший язык высокого уровня, задуманный изначально как FORmula TRANslator для ученых и инженеров. Fortran создавался в IBM начиная с 1954 года суровым чуваком Джоном Бэкусом.


Формально первым языком высокого уровня считается Планкалкюль (1945), компилятор которого, правда, был создан только в 2000. Fortran в 1950-х был не просто изобретен (точнее – «интуитивно нащупан»), но сразу реализован. Он – первый «по-честноку».

Благодарные ученые и инженеры активно используют Fortran до сих пор, несмотря на очевидную его моральную устарелость. (Сейчас XXI век, четвертая пятилетка). Мы тоже не исключение. На Fortran меня подсадили в 2009 году седовласые профессора кафедры «Прикладная математика» петербургского Политеха, с которыми мы вместе создавали одну нетривиальную загогулину. С тех пор слезть с него не удается никак.

В рейтинге популярности языков программирования Fortran находится на 28 месте, между F# и Lua. Современные мейнстримные программисты заливаются хохотом, когда им говоришь про Fortran. (Боюсь, они представляют его весьма условно, в стандарте приблизительно 77). А зря. Среди куда более узкой аудитории – ученых и инженеров Fortran занимает если уже и не первое, то точно одно из ведущих мест.

Причин продолжения использования Fortran несколько:

  1. Огромная, накопленная за пол века база инженерно-научного кода.

  2. Скорость. Программы на Fortran – очень быстрые. Компиляторы Fortran чрезвычайно эффективны, а используемые математические библиотеки алгоритмически отточены как лезвия бритв. Кроме того, современный Fortran очень эффективно позволяет распараллеливать вычисления.

  3. Удобство работы с матрицами и вообще с математикой. В Си-подобных языках этого можно добиться только с помощью ряда библиотек, здесь – все «из коробки».

  4. Он простой как топор и императивный как танк. Инженеру/ученому не надо забивать голову программистскими премудростями (объектно-ориентированными или функциональными парадигмами, либо особенностями распределения памяти, указателями и т.д., и т.п.). Можно просто писать свои сладкие формулы.

  5. Он компилируемый. Программы очень просто кому-нибудь отдавать безо всяких ваших виртуальных машин.

  6. Как ни странно, он развивается и поддерживается. Стандарты регулярно обновляются (последний – 2015), компиляторы – совершенствуются.

На самом деле, Fortran действительно хорош для задач вычислительной математики, требующих очень высокой скорости исполнения кода с одной стороны, а с другой стороны – не слишком сложных в плане организации данных. Большинство околонаучных задач таковы. Однако, если данных все-таки много (не по объему, а по запутанности), а проект – сложен, то Fortran с удовольствием поспособствует его превращению в летающего макаронного монстра.

Если высокая скорость не требуется, лучше взять более современный язык «сверхвысокого» уровня: Python с библиотеками NumPy и SciPy или специализированный математический язык Mathematica или MatLAB (или свободные аналоги; для последнего – Octave или SciLAB). На них разработка «научного» проекта будет в разы быстрей и прозрачней, правда все будет работать чертовки по-черепашьи.

Часто проекты так и приходится создавать в два этапа:

  1. Прототипирование на «высоком и прозрачном» языке типа Python.

  2. Реализация на быстром Fortran (или С/С++).

В последние годы научным сообществом активно разрабатывается новый современный язык Julia, претендующий на замену Fortran. Он позволяет писать как «прозрачные» прототипы, так и быструю реализацию критичных участков. Julia, родившаяся в 2012, – многообещающий и очень интересный язык, который лично я изучать пока только начал. О нем еще будут посты.

Компиляторы Fortran

Живых компиляторов Fortran сегодня, как ни странно, не меньше десятка.

Лучший активно развивающийся коммерческий компилятор для Windows и Linux – вероятно, Intel Fortran. С ним «из коробки» идет мощнейшая математическая библиотека MKL, включающая известные пакеты линейной алгебры BLAS и LAPACK, а также супер-эффективный пакет для работы с разряженными матрицами PARDISO и прочие вкусности. (За дополнительные деньги можно приобрести дополнительные или альтернативные библиотеки, такие как знаменитая IMSL). С Intel Fortran поставляется очень мощный профайлер, позволяющий смотреть, на каких участках кода как тратится время (и другие параметры) и оптимизировать код. В Windows Intel Fortran ставится на MS Visual Studio и работает с линкером от Майкрософт.

Вторым лидером рынка вроде бы считается PGI Fortran (для Linux and Mac доступен во Free edition) – тоже монстр, на который, я правда особо и не смотрел. Еще есть Absoft Pro Fortran, IBM XL Fortran (для Linux и AIX), EKOPath (Linux), Lahey/Fujitsu Fortran, NAG Fortran, Oracle Solaris Studio (для Solaris и Linux, кажется недавно стала бесплатной) и другие.

Довольно интересный коммерческий компилятор – Silverfrost FTN95, бесплатный для персонального использования или «в целях оценки». Единственное неудобство – каждый раз при запуске скомпилированной программы появляется баннер. С FTN95 поставляется приятная легкая Plato IDE. Вообще, вся система производит впечатление очень легкой и быстрой.

Лучший свободный компилятор – GFortran из набора компиляторов GCC, разрабатываемых в рамках проекта GNU. GFortran активно совершенствуется «свободным сообществом».

Еще неплохой свободный компилятор был G95, но похоже загнулся в 2013.

Итого, наш выбор – GFortran, поэтому о нем – поподробнее.

Установка GFortran в Windows

На январь 2017 последняя стабильная версия GCC с GFortran – 6.3, заканчивается работа над седьмой версией.

GFortran – разумеется, кроссплатформенный. Для Windows его можно получить и установить разными способами:

  1. Из родного «набора свободных средств разработки под Windows для настоящих минималистов» :) – проекта MinGW или отпочковавшегося от него проекта MinGW-w64, реализующего преимущества 64-битной архитектуры. Или из проекта CygWin. Все три варианта – не самые простые пути. Что надо скачать и как это настроить – все довольно запутанно.

  2. Поставить GFortran вместе с хорошей свободной кроссплатформенной IDE Code::Blocs. Скачиваем с их сайта и устанавливаем файл codeblocks-16.01mingw_fortran-setup.exe (версия 16.01 на сегодня последняя). Возможно, это наиболее простой путь. Недостаток – GFortran будет несколько устаревшей (текущая версия в сборке 4.9.2) и только в разрядности 32. Зато поставил – и можно сразу переходить к сладким формулам в интуитивно понятном окружении IDE.

  3. От ребят, именующих себя Equation Solution, в лице китайца Джен-Чинга Ляо (www.equation.com). Это бывший профессор колумбийского университета, еженедельно собирающий самую актуальную версию дистрибутива GCC для разрядности как 32, так и 64. Сборка дополнена отладчиком и собственными библиотеками профессора Ляо, из которых особый интерес для нас представляют LAIPE2 (решение СЛАУ с распараллеливанием) и JCL (перенумерация строк и столбцов разряженных матриц для приведения их к ленточной форме). Это хорошие библиотеки, оказавшиеся для меня очень кстати. Из дистрибутива профессора Ляо GCC устанавливается очень легко через инсталлятор. Необходимые пути автоматом прописываются в PATH. У Ляо в принципе, все хорошо. С его дистрибутивами я жил какой-то время, единственное, там немножко все «собрано на коленке». Например, в комплекте нет dll (предполагается только статическая линковка библиотек gcc), получаемые exe в последних версиях стали странным образом разбухать, его собственные библиотеки – иногда глючат и т.п. :) Как обычно, Open Source – такой Open Source. :)

  4. Из специальной сборки компиляторов GCC для Windows с сайта TDM-GCC. Это очень хорошие и продуманные сборки, включающие полный набор нужных средств. К сожалению, здесь GCC тоже несколько устаревший (текущая версия 5.1), но сейчас этот вариант – мой фаворит. Скачиваем с их странички файл tdm64-gcc-5.1.0-2.exe для архитектуры 64 или tdm-gcc-5.1.0-3.exe для 32. На версии 64 можно (в том числе) компилировать свои программы и для 32-разрядных машин, т.е. две версии ставить не нужно. Устанавливается все элементарно через инсталлятор. Единственное, ему надо указать «Устанавливать все пакеты», т.к. по умолчанию компилятор фортран как «экзотика» пропускается. Инсталлятор прописывает путь к компиляторам в PATH.

Последний вариант, TDM-GCC, – очень хороший, за одним «но». В версиях 5.3 (и 4.9) допущен досадный баг, из-за которого не работает оператор фортрана Open. :) (Open Source – такой Open Source). Об этом не написал в баг-листе только ленивый. Надо скачать с их сайта старую версию 4.8 (там надо найти gcc-4.8.1-tdm64-2-fortran.zip) и заменить из нее файлы libgfortran_64-3.dll и libgfortran-3.dll, а также libgfortran.a, libgfortran.dll.a, libgfortran.spec, libgfortranbegin.a. Причем последние файлы имеются в 64 и 32-разрядных версиях, их надо аккуратно разложить по соответствующим папкам lib или lib32.

То же относится и к текущей версии 4.9 GFortran в CodeBlocs (он по сути там тот же самый из TDM-GCC).

Надеюсь, это исправят. В остальном все работает как часы.

В дистрибутивах от Ляо этой проблемы нет.

Компиляция в GFortran

Из IDE

IDE для того и нужны, чтобы не думать, а нажимать кнопочки. :) Все интуитивно понятно без дополнительных пояснений.

Из командной строки

Допустим, мы хотим запустить «чистый компилятор», не пользуясь IDE. Пишем программу в текстовом файле, например Hello.f08:

program Hello
    print *, "Здавствуй, мир! Hello, Space Boy!"
    call execute_command_line("Pause")
endprogram

Компилируем из командной строки:

gfortran Hello.f08 -o Hello.exe

Если пути в PATH «подхватились», после этого получается файл Hello.exe, запуск которого приведет к выводу приветствия на консоль (или «кракозябров» из-за несовпадения кодировки). Если пути в PATH не прописаны, перед gfortran надо указать к нему путь – все точно также будет работать.

Опция -o задает выходной файл.

Чтобы статически сгенерировать exe, не завязанный ни на какие внешние .dll-библиотеки, нужно добавить опцию -static:

gfortran Hello.f08 -static -o Hello.exe

О других опциях – см. ниже.

Далее. Допустим, проект состоит из нескольких модулей. Пусть, например, это три файла: Module1.f08, Module2.f08 и MainProgram.f08 с соответствующими текстами:

module Module1 
    contains 
    function Square(x)  ! Вычисление квадрата x
        real :: x, Square
        Square = x**2
    endfunction
endmodule
module Module2
    use Module1 
    contains 
    subroutine PrintSquare(y)  ! Печать квадрата y 
        real :: y
        print *, "Квадрат числа:", Square(y)
    endsubroutine
endmodule
program MainProgram ! Супер-программа «Нахождение квадрата числа»
    use Module1 ; use Module2
    real :: z = 3.   ! Наше число
    call PrintSquare(z)
    print *, "Проверка:", Square(z)
    call execute_command_line("Pause")
endprogram

Пример составлен так, чтобы смоделировать зависимости модулей друг от друга, показанные на схеме:




Компилируется такой проект, чтобы не нарушался порядок зависимостей, следующим образом:

gfortran -c Module1.f08
gfortran -c Module2.f08
gfortran -c MainProgram.f08
gfortran Module1.o Module2.o MainProgram.o -static -o MyProgram.exe

Сначала исходные файлы компилируются в объектные .o (опция -c), а затем они линкуются в результирующий .exe.

Компиляция с GNU Make

Работать с командной строкой, когда фалов проекта много, не слишком удобно (даже если все прописывать в *.bat или *.cmd). Задачу автоматизации сборки берет на себя IDE и/или олдскульная технология составления Make-файлов, которые можно легко вызывать на исполнение, например, из любимого текстового редактора. Преимущество Make, в частности, в том, что каждый раз будут перекомпилироваться не все файлы проекта, а только те, которые изменились.

Если фортран был поставлен из дистрибутива TDM-GCC или CodeBlocs, утилита Make находится в папке bin под именем mingw32-make.exe. Для простоты скопируем (продублируем) ее под именем просто make.exe. В дистрибутиве от Ляо она сразу называется make.exe.

Если на машине инсталлировано несколько сред программирования, могут стоять и различные мэйки, которые также могут вызываться по команде make не совсем к месту. Убедимся, что так вызывается именно GNU Make, набрав make -v. Это должно выдавать приблизительно следующее:

GNU Make 3.82.90
Built for i686-pc-mingw32
Copyright (C) 1988-2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

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

Make-файл состоит из правил и переменных. Правила имеют следующий синтаксис:

цель1 цель2 ...: реквизит1 реквизит2 ...
    команда1
    команда2
    ...

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

NB! Строки, в которых записаны команды, должны начинаться с символа табуляции. Пробелы здесь ставить нельзя!!!

Простейший Makefile для программы из одного модуля Hello.f08 (наш первый пример) может выглядеть так:

PRG_NAME = Hello

all: 
    gfortran $(PRG_NAME).f08 -o $(PRG_NAME).exe
    $(PRG_NAME).exe

clean:
    rm -rf *.o *.mod $(PRG_NAME).exe

Здесь вначале определена переменная PRG_NAME, значение которой затем «дословно» подставляется в команды – везде, где написано $(PRG_NAME).

Далее определены две цели: all и clean, без реквизитов, но зато с командами.

Если из рабочего каталога вызвать

make all

то мейк отработает первую цель, а именно – скомпилирует и запустит нашу программу. При этом файл Makefile подхватится по умолчанию. Первую цель, определенную в файле, можно вызывать еще проще, написав просто

make

Можно также указать требуемый мейк-файл явно, тогда он может называться как нам угодно:

make -f MyMakeFile all

Запуск Make с другой целью, clean, сотрет все промежуточные файлы проекта:

make clean

Теперь составим чуть более сложный Makefile для нашего второго примера с тремя модулями. При этом предусмотрим возможность управления вариантами компиляции с разными опциями, путем их комментирования/раскомментирования. Пусть также exe помещается в отдельную папку bin, которая должна лежать рядом с папкой для исходного кода.

# 1. Флаги компилятора, меняемые оперативно (отладка, оптимизация):

# Быстрая компиляция без лишних вопросов:
# MY_FLAGS = -w -O0 

# Компиляция для отладки с проверками времени выполнения и предупреждениями:
MY_FLAGS = -Og -Wall -Wno-tabs -fcheck=all

# Компиляция для релиза с оптимизацией:
# MY_FLAGS = -w -Ofast -mfpmath=sse -ftree-vectorize -funroll-all-loops

# 2. Флаги компилятора - общие для всех модулей и вариантов компиляции:
FLAGS = -ffree-line-length-512 -freal-4-real-8 

# 3. Название программы и исходных файлов (без расш.) в порядке компиляции:
PRG_NAME = ..\\bin\\MyProgram
F1 = Module1
F2 = Module2
F3 = MainProgram

# 4. Компилятор фортран (здесь можно прописать путь):
CF = gfortran

# 5. Главная цель - сформировать программу и потом ее запустить:
all: $(PRG_NAME)
    $(PRG_NAME).exe

# 6. Для этого нужно достичь другой цели - слинковать объектные файлы в exe:
$(PRG_NAME): $(F1).o $(F2).o $(F3).o 
    $(CF) $^ $(FLAGS) $(MY_FLAGS) -o $@.exe 

# 7. А для этого нужно скомпилировать каждый файл из исходников:
$(F1).o: $(F1).f08 
    $(CF) -c $(FLAGS) $(MY_FLAGS) $^ 

$(F2).o: $(F2).f08 
    $(CF) -c $(FLAGS) $(MY_FLAGS) $^ 

$(F3).o: $(F3).f08 
    $(CF) -c $(FLAGS) $(MY_FLAGS) $^ 

# 8. Альтернативная цель - очистка проекта от промежуточных файлов:
clean:
    rm -rf *.o *.mod $(PRG_NAME).exe

Возможно, это не лучший стиль написания Make, но для меня он «родной» и наглядный.

В главной цели all перед командой запуска файла мы указали реквизит, одноименный с названием программы:

all: $(PRG_NAME)
    $(PRG_NAME).exe

Make – как хороший солдат, любой ценой (но желательно наименьшей), должен выполнить поставленную перед ним цель. А заключается она в исполнении команд, при этом обязательным условием перед их исполнением является наличие реквизита. В качестве реквизита основной цели мы указали необходимость достижения «дочерней» цели, правило для которой описали так:

$(PRG_NAME): $(F1).o $(F2).o $(F3).o 
    $(CF) $^ $(FLAGS) $(MY_FLAGS) -o $@.exe 

Оно требует наличия еще трех реквизитов – готовых объектных файлов $(F1).o $(F2).o $(F3).o. Если они имеются, должна быть выполнена команда по их линковке в exe.

Выражение $@ означает «подставить сюда текущую цель», а $^ – «подставить сюда текущий реквизит».

Цели, связанные с данными реквизитами, мы описали так:

$(F1).o: $(F1).f08 
    $(CF) -c $(FLAGS) $(MY_FLAGS) $^ 

Это значит, что для достижения очередной цели надо, чтобы присутствовал файл $(F1).f08, после чего его надо скомпилировать в объектный файл.

Make, как любой нормальный боец, чрезвычайно ленив. Если какая-то цель была уже выполнена, он не будет рваться достигать ее еще раз. Если у него уже есть скомпилированный объектный файл, он его компилировать повторно не будет. Но он – все же очень исполнительный и прилежный боец. Если файл исходника был изменен позже объектного файла, Make старательно это исправит, перекомпилировав объектный файл снова.

Здесь находится перевод официальной справки по GNU Make.

Здесь – хороший материал «Эффективное использование GNU Make» от Владимира Игнатова.

Некоторые опции компилятора

При компиляции и линковке GFortran’у можно указать огромную кучу опций – все они описаны в справках по GFortran и GСС. Перечислю здесь некоторые «типовые» (используемые мной в практике):

Опция Пояснение
-static Указывается при линковке. Собирает весь код зависимых библиотек в один exe-файл. Его можно будет отдавать и переносить без дополнительных dll.
-shared-libgcc Наоборот, dll от GCC – отлинковать динамически. exe-файл будет маленький, но без установленных в доступности PATH нескольких «родных» dll ничего работать не будет.
-m32 Если установлен 64-разрядный GFortran, по умолчанию проект компилируется как 64-разрядное приложение, этой опцией можно попросить сделать версию для 32-разрядных машин.
-O0, -O1, -O2 или -O3 или -Ofast Уровни оптимизации, кода. С -O0 сама компиляция будет быстрой (удобно при разработке), но код – медленный. -O3 или -Ofast – для релиза. -Og – оптимизация для отладки.
-mfpmath=sse -ftree-vectorize -funroll-all-loops Дополнительные оптимизации для релиза (но без фанатизма, для современных процессоров можно навернуть больше).
-fdollar-ok -llaipe2 -lneuloop4 -ljcl Опции для подключения библиотек от Ляо. Первая разрешает доллар в именах функций как у него принято, остальные просто подключают библиотеки laipe2, neuloop4, jcl.
-fopenmp Подключает библиотеку OpenMP для параллельных вычислений.
-fimplicit-none Запрещает неявное определение типов по первой букве у переменных (i – integer и т.д.). Эквивалентно указанию в каждой процедуре implicit none, где их можно забыть и поиметь проблемы с переменными, которые забыли определить явно.
-ffree-line-length-512 Позволяет писать длинные строки в коде (с современными мониторами трудно умещать код в 72 символа, считающиеся ранее максимальной шириной кода).
-freal-4-real-8 Считать все вещественные числа типа real(4), которые в фортране по-умолчанию можно задавать как «просто» real, числами с двойной точностью real(8) (8 байт). На мой взгляд, для большинства задач сейчас лучше использовать 8 байт, а с этой опцией будет меньше визуального мусора типа real(8) :: r = 1.0_8, будет просто real :: r = 1.0.
-w Подавлять все синтактические предупреждения
-Wall -Wno-tabs -fcheck=all Наоборот, выводить все предупреждения (кроме абсурдных), а также выполнять все проверки времени выполнения (выходы за пределы индексов в массивах и т.д., и т.п.)
-ggdb Генерировать информацию для отладчика gdb
-pg Генерировать информацию для профайлера gprof

О расширениях исходных файлов

Расширение файлов по традиции отражает стандарт языка: в наших примерах оно f08 – стандарт 2008. Это дань традиции: компилятор без доп. опций понимает f08, f03, f95, f90 одинаково, как файлы в свободном формате. Для старого фиксированного формата используются расширения f, for и др.

Если расширение начинается с большой буквы (F08, F95 и т.п.), а также если оно fpp, то файл будет сначала пропускаться через предпроцессор – в нем можно будет писать директивы компилятору с синтаксисом gcc-Си, например:

#define Compile_R16
! ...

#if defined Compile_R16
    real*16 :: MyReal
#else
    real*8  :: MyReal
#endif 

Подключение математических библиотек к GFortran

BLAS и LAPACK

BLAS и LAPACK – классические библиотеки линейной алгебры, которые не совсем очевидно подключаются к GFortran в Windows. Здесь описан процесс подключения, если вы работаете c Visual Studio с линкером от Майкрософт, который подключает библиотеки *.dll, используя *.lib. Родной линкер GFortran использует библиотеки в архивированном формате *.a.

Как подключить BLAS и LAPACK к GFortran в Windows:

  1. Скачиваем с официального сайта архив lapack-3.7.0.tgz. (На сегодня последняя версия 3.7.0). Распаковываем архив в папку lapack-3.7.0.

  2. В подпапке INSTALL находим файл make.inc.gfortran, копируем его в корневую папку (lapack-3.7.0) и переименовываем его в просто make.inc.

  3. Идем в каталог \BLAS\SRC (например, в файловом менеджере FAR) и набираем в нем команду make (GNU make должен быть подключен, см. выше). После компиляции ряда файлов в корневой папке (lapack-3.7.0) должен появиться файл librefblas.a.

  4. Аналогично, идем в каталог \SRC и набираем в нем команду make all. После компиляции ряда файлов (довольно долгой) в корне должен появиться файл liblapack.a.

  5. Переписываем файлы librefblas.a и liblapack.a туда, где GCC хранит свои библиотеки. В зависимости от установленного дистрибутива это папки вроде \i686-pc-mingw32\lib, \x86_64-w64-mingw32\lib или \MinGW\lib (в CodeBlocks).

  6. Если мы работаем с дистрибутивом разрядности 64 (например от TDM-GCC) и хотим по опции -m32 уметь компилировать наши программы для 32-разрядных машин, весь процесс придется повторить, скомпилировав librefblas.a и liblapack.a с опцией -m32 (придется дописать ее в make-файл), а потом положить 32-разрядные версии библиотек в соответствующую папку (у TDM-GCC это \x86_64-w64-mingw32\lib32).

  7. Все!

Протестируем. Решим систему линейных алгебраических уравнений (СЛАУ)

\[ \mathbf{A}\cdot\mathbf{X}=\mathbf{B}, \]

где \(\mathbf{A}\) – матрица коэффициентов, \(\mathbf{X}\) – вектор неизвестных и \(\mathbf{B}\) – вектор правых частей.

Пусть матрица \(\mathbf{A}\) – плотная, общего вида. Для СЛАУ с такими матрицами в подойдет LAPACK-процедура dgesv. Первая буква «d» означает вариант для вещественных чисел двойной точности, real(8). Пусть \(\mathbf{A}\) имеет размер \(10 \times 10\) с заполнением случайными числами от \(0\) до \(100\), а вектор \(\mathbf{B}\) заполнен числами \(100 \dots 1000\).

Наберем в файле test.f08:

program LAPACK_test
    implicit none 
    integer, parameter      ::  n = 10    ! Размерность матриц
    real(8), dimension(n,n) ::  A         ! Матрица коэффициентов
    real(8), dimension(n,1) ::  B, X      ! Векторы правых частей / результатов
    integer                 ::  i         ! Вспомог. индекс
    integer, dimension(n)   ::  ipiv      ! Вспомог. матрица для процедуры LAPACK
    integer                 ::  info      ! Инфо об успешности решения
    character(100)          ::  FRM       ! Формат для вывода матриц
    !----------------------------------------------------------------------------
    print *, "Проверка LAPACK. Решение СЛАУ А*X=B с плотной матрицей общего вида"
    call random_number(A);  A = 100*A     ! Заполняем матрицу А 
    forall(i = 1:n) B(i,1) = 100*i        ! Заполняем вектор B
    write(FRM, "(a,i10,a)") "(",n,"f8.2)" ! Формируем формат для вывода матриц
    print *, "Матрица коэффициентов A:"
    print FRM, A
    print *, "Вектор правых частей B:"
    print FRM, B
    X = B
    call dgesv(n, 1, A, n, ipiv, X, n, info)  ! Вызов LAPACK для решения СЛАУ
    print *, "Решение:"
    print FRM, X
    print *, "Успешность решения (флаг «info»):", info
endprogram

Компилируем, подключая библиотеки lapack / refblas:

gfortran test.f08 -llapack -lrefblas -static -o test.exe

Получаем:

Проверка LAPACK. Решение СЛАУ А*X=B с плотной матрицей общего вида
Матрица коэффициентов A:
  99.76   56.68   96.59   74.79   36.74   48.06    7.38    0.54   34.71   34.22
  21.80   13.32   90.05   38.68   44.55   66.19    1.61   65.09   64.64   32.30
  85.57   40.13   20.69   96.85   59.84   67.30   45.69   33.00   10.04   75.55
  60.57   71.90   89.73   65.82   15.07   61.23   97.87   99.91   25.68   55.09
  65.90   55.40   97.78   90.19   65.79   72.89   40.25   92.86   14.78   67.45
  76.96   33.93   11.58   61.44   82.06   94.71   73.11   49.76   37.48   42.15
  55.29   99.79   99.04   74.63   95.38    9.33   73.40   75.18   94.68   70.62
  81.38   55.86    6.17   48.04   59.77   13.75   58.74   52.00   88.59   30.38
  66.97   66.49   50.37   26.16    7.66   10.12   54.93   37.56    1.51   79.29
  62.09   77.36   95.36   11.42   31.85   59.68    4.82   11.42   21.60   10.06
Вектор правых частей B:
 100.00  200.00  300.00  400.00  500.00  600.00  700.00  800.00  900.00 1000.00
Решение:
  -8.79   16.14   12.52    3.00  -14.42   -0.18    4.31   -2.40    5.41   -1.10

Библиотеки дядюшки Ляо

В дистрибутиве GCC профессора Ляо (с сайта www.equation.com) имеются очень неплохие библиотеки:

  • NEOLOOP – для параллельных вычислений;

  • LAIPE2 – решение СЛАУ с матрицами коэффициентов различного вида, включая симметричные положительно определенные ленточные или просто разряженные, представляющие для нас особый интерес (почему – об этом потом). Решение выполняется с распараллеливанием процессов.

  • JCL – перенумерация строк и столбцов разряженных матриц для приведения их к ленточной форме.

Если нужно установить эти библиотеки в другие дистрибутивы, делаем следующее:

  1. Находим в дистрибутиве от Ляо файлы библиотек: libneuloop4.a, libneuloop6.a, liblaipe2.a, libjcl.a.

  2. Переписываем их в место, где хранит основные библиотеки ваш фортран.

Как обычно, если мы работаем с 64-битной версией GCC с желанием сохранить возможность компиляции программ под 32, это надо сделать для обеих версий библиотек, положив их в lib и lib32.

Компиляция программ с этими библиотеками выполняется с опциями:

-fdollar-ok -llaipe2 -lneuloop4 -ljcl

(Первая разрешает доллар в именах функций как у него принято, остальные просто подключают библиотеки laipe2, neuloop4, jcl).

Чтобы подпрограммы LAIPE2 заработали, надо предварительно вызвать процедуру laipe$use с указанием числа ядер процессора, которые вы хотите использовать (иначе не «заведется» – об этом Ляо забыл написать в справке).

Библиотеки NEOLOOP и LAIPE2 работают только на Windows 7 и более старших.

IDE и редакторы для GFortran

Для серьезной работы с языком хорошо иметь как IDE, со всем богатством возможностей, так и текстовый редактор (может быть, не один), позволяющий «что-нибудь сварганить» по-быстрому или подправить. Честно говоря, я IDE почему-то запускаю реже текстового редактора, с которым намного лучше постигается Дзен.

Какие есть варианты для GFortran в Windows?

IDE Code::Blocks

Это самый простой вариант начать работать в Fortran, пользуясь свободным ПО. Все ставится из коробки и заводится с пол-оборота. По сравнению с альтернативными IDE – относительно легкая. Тут есть все что нужно: автодополнение кода, подсказки, навигация по объектам программы, отладчик, профайлер, минимальные средства рефакторинга.


Когда-то я «щупал» ifort + Visual Studio, там таких удобных подсказок и умного автодополнения и близко не было (это не претензия к студии – в других языках все очень круто, но не в Intel Fortan). Т.е. в определенном смысле CodeBlocks – даже лучше. (Может конечно я отстал от жизни, последних версий ifort + VS не видел).

На 64-разрядных машинах желательно поставить 64-разрядный компилятор GFortran (см. выше) и подключить его в качестве основного (все делается мышкой в настройках элементарно).

Вывод сообщений ваших программ не в консоль, в окно редактора (чтобы не было проблем с кодировками) можно сделать через меню Tools, создав новый инструмент, указав для него:

Executable: ${TARGET_OUTPUT_BASENAME}
Working directory: ${TARGET_OUTPUT_DIR}
Launch tool hidden with standart output redirect

IDE Eclipse с расширением Photran

Eclipse – знаменитая мощнейшая IDE для множества языков программирования. Для Fortran есть расширение Photran, работающее в том числе c GCC. Доступно здесь.

Eclipse – очень тяжелая штука. Я побаловался, но дальше она как-то не прижилась.

Прочие IDE

Еще можно посмотреть в сторону легонькой Geany.

Не уверен, что своими силами можно толком настроить GFortran c Visual Studio. Есть коммерческий пакет, где это сделано – Lahey/Fujitsu Fortran. Это не наш путь.

Текстовые редакторы

Не могу отделаться от ассоциации программистских текстовых редакторов с людьми разных возрастных групп. :)

Emacs и Vim

Седовласые старики. Очень опытные, мудрые и крутые, но найти с ними общий язык – очень сложно. Я пока не сумел, хотя пару десятков попыток делал. :)

Sublime Text, Atom, VS Code

Энергичные мужики. Моложавые, хипстерской внешности. На этих редакторах получается сделать «почти IDE».

Atom – открытый, мощный, но жирный и неторопливый. Использую его для некоторых других языков, Фортран как-то на нем не прижился.

Sublime Text – мой выбор. Мощный, быстрый, правда не открытый и не бесплатный (70 долларов, хотя незарегистрированной версией можно пользоваться сколько угодно).


VS Code – удачная попытка Microsoft написать бесплатный Sublime. Очень приятный. Все намереваюсь на него перейти, но руки пока не доходят.

SciTE, NotePad++, AkelPad

Эдакие продвинутые юнцы. Меленькие, легкие, дерзкие, но далеко не такие мощные, как товарищи из первых двух групп. Не «почти IDE».

Раньше я очень любил SciTE, последнее время перешел в AkelPad. Он крошечный, работает со сверхзвуковой скоростью. Очень просто настраивается подсветка. Все, чего только только можно желать, реализуется на скриптах на простом человеческом JavaScript.


С GFortran нетрудно настроить любой редактор. Привожу некоторые скриншоты работы приведенной выше программы по тестированию правильности установки LAPACK.

Литература по Fortran

Лучшая книга на русском языке – О. В. Бартеньев «Современный Фортран». Она настолько полная и и исчерпывающая, что книги остальных авторов – не нужны. Хорош также его же трехтомник по библиотеке IMSL. Даже если вы не применяете IMSL, там много полезной теории. (На самом деле книги Бартеньева – по сути качественный перевод полной документации по Фортрану и IMSL и от минимума «отсебятины» они только лучше). Жаль только, что его книги несколько устарели, но это совсем не критично – Фортран развивается не так быстро.

Здесь – GFortran Wiki.

Здесь – PDF-справка по GFortran. Очень неплоха. Коротко и по делу. Для работы нужен второй PDF по GCC в целом.

Здесь – очень хорошее краткое описание языка в стандарте 95 в википедии. Если вы пишете на других языках, прочитав это, станете гуру в Фортране за каких-нибудь пару часов. :)

Здесь, в открытом доступе, – прекрасная справка по Intel Fortran, в основной части (в части самого языка) подходящая и для GFortran.

Здесь, аналогично, – прекрасная документация по Intel MKL, в основной части подходящая для BLAS и LAPACK.

Что прекрасно в Fortran

  1. Работа с матрицами.

С матрицами (например, A, B, C) можно работать как с переменными:

A = 2*B + sin(C)

К матрицам (поэлементно) могут быть применены любые чистые функции (как синус в примере).

Вырезки и сечения матриц:

B[1:5,1:5] = A[1:10:2,1:10:2]

В отличие от MatLAB-подобных языков, шаг - третий, а не второй элемент триплета.

Конструкция forall. Например, заполним матрицу \(n \times n\) единицами по диагонали (сделаем ее единичной):

A = 0 
forall(i = 1:n) A(i,i) = 1

Конструкция where. Например, так можно обнулить все отрицательные компоненты матрицы B:

where(B < 0) B = 0

С матрицами, вообще, множество удобных встроенных функций – практически на все случаи жизни.

Матрицы могут быть многомерными.

  1. Вызов процедур: поддерживается перегрузка параметров, необязательные и именованные параметры.

  2. Типы, включая комплексные числа. Удобные древовидные пользовательские типы (структуры данных).

  3. Как ни странно, форматный ввод-вывод, к которому привыкаешь, но который я также отмечу как одно из самых ужасных свойств языка. :)

Что ужасно в Fortran

Современный Fortran позволяет писать более-менее сносный код, если не пользоваться устаревшими конструкциями языка, поддерживаемыми ради совместимости, например:

  • типизацией переменных по умолчанию на основе первых букв их имен;

  • разными точками входа в процедуры;

  • переходами goto с метками;

  • указателями и прочими средствами работы с памятью «напрямую» и т.д.

Иногда чешутся руки, наоборот, это все использовать и писать программы аутентично «индийские». В идеале можно выйти на абсолютный Brainfuck. :)

Не только эти, но и в принципе многие конструкции языка, конечно же, устарели. Что особенно бесит:

  • Работа со строками.

В Fortran нет строк переменной длины, размер строк нужно задавать явно.

Специфичны преобразования других типов данных в строку и обратно. Чтобы преобразовать, например, вещественное число r в строку str или наоборот, приходится делать это через операторы ввода-вывода:

write(str, "(f8.3)") r  ! str <- r в формате f8.3
read(str,*) r           ! str -> r

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

str = trim(str1) // trim(str2)  ! Если строки выровнены влево
str = trim(AdjustL(str1)) // trim(AdjustL(str2)) ! Если не выровнены :)

Разумеется, в Fortran нет никаких регулярных выражений и других «вкусностей», к которым в современных языках мы успели уже «прикипеть».

  • Форматный ввод-вывод – очень мясной. Он был удобен для терминалов, но сейчас это – кошмарный анахронизм:
print "(a,i4,a,10f8.3)", "Шаг:", i, "Вектор:", V

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

  • Нет списков и вообще структур данных с изменяемой длиной «на лету». (Динамически размещаемые массивы, конечно же, есть).

  • Переусложненная система типов. Вещественные числа разной длины пишутся с указанием разновидности (KIND) весьма специфично:

real     :: r1 = 1.     ! По умолчанию real – это real(4)
real(8)  :: r2 = 1._8
real(16) :: r3 = 1._16

С другой стороны, KIND можно определить на уровне директивы компилятора и везде использовать просто real и числа без этих «_8»

  • Мало средств «декомпозиции и абстракции» для поддержания структуры больших проектов.

  • Избыточность языка, связанная с историей и совместимостью снизу вверх.

  • Наследуемый код, написанный за пол века «учеными и инженерами» – в подавляющей массе просто чудовищен. Чуть менее, чем весь созданный код. :) Почему так – загадка. Прямой вины языка в этом нет. Потемки – душа ученого.

Вместо Conclusions

В этой импровизированной статье пока не был раскрыт ключевой вопрос абстракта «как заставить себя в XXI веке писать на Fortran?». :)

Мейнстримовый C++ предлагает аналогичную скорость.

Лаконичный Python предоставляет неслыханную мощь и ясность/читаемость кода. Одна строчка идет за 5-10 Фортрана.

Julia совсем наступает на пятки, предлагая почти ту же мощь и прозрачность, что и Python, и вполне сравнимую с Fortran скорость.

На самом деле, у меня нет разумного ответа на сакраментальный вопрос, кроме лишь одного: Fortran надо любить. :) Как дедушку и стареющего отца.

Каждый раз, открывая текстовый редактор с Фортраном, чувствуешь, что «подключаешься» к чему-то ретрофутуристично-прекрасному. :) Будущее, как видели его в 60-х годах, космические полеты, покорение звезд. Элементарные частицы, атомные реакторы. Шуршащие пленкой вычислительные машины. Папиросы профессоров «Прикладной математики». Все это преломляется в вашем редакторе, хочется открывать его еще и еще. :) А на современных машинах все эти отблески проносятся с бешенной скоростью… Ну и конечно, по совокупности качеств, с чего «статья» начиналась…

Пускай в этом блоге Fortran будет отправной точкой в мир более современных решений.

воскресенье, 22 января 2017 г.

О блоге

Я работаю в отделе НИОКР одной инжиниринговой компании. В ходе профессиональной и «околонаучной» деятельности мы вынуждены решать довольно разнообразные задачи из области инженерной механики, электродинамики, теплофизики и аэродинамики. Специфика такова, что для многих задач либо не существует ПО, подходящего для нас напрямую, либо оно очень тяжелое и дорогое.

Мы выбрали стратегию решать наши проблемы преимущественно на базе свободного (бесплатного, некоммерческого) ПО. Иногда приходится разрабатывать собственные программы на открытых (опять-таки) языках, иногда – пользоваться сторонними пакетами и системами. Зачастую – в причудливой связке.

Процесс изучения языков и ПО стал для меня не только работой, но и «заменителем хобби» – я с удовольствием трачу на это свободное время. Изучать «технологии» – захватывающее занятие. А сделать что-то новое и полезное, не используя при этом почти ни единого коммерческого продукта, – становится интересно просто в спортивном плане. :) Кроме того, я – романтик, и поэтому искренне верю, что знания («достижения науки и техники») принадлежат всему человечеству и очень важно, чтобы они становились открытыми и свободными. Как Википедия или Open-Sourсe код.

Разбирательству с «открытыми достижениями» и будет посвящен данный блог. Во многих случаях «человечество» как будто намерено преподносит свои «открытые достижения» в таком виде, что через них приходится «продираться» настойчиво и упорно. Зачастую рядом стоит какой-нибудь Дядюшка Сэм и предлагает то же на блюдечке – в понятной и простой форме, красиво обернутое и за хорошие деньги. Но мы не ищем легких путей. :)

Здесь почти не будут описываться предметные задачи (оставим рабочее для работы), будут обсуждаться именно «технологии».

Блог задумывается прежде всего как конспект аспектов применения «открытых технологий в области инжиниринга» (как звучит, а? :). Конспект – вещь полезная, прежде всего, для себя:

  • когда пишешь конспект, любое изучение спорится в разы эффективней;

  • в будущем многое можно быстро восстановить в памяти (надоело разбираться с одними и теми же «тонкостями» по нескольку раз с периодичностью в несколько лет);

  • ссылку на соответствующий раздел такого блога-конспекта можно отдать коллегам или аспирантам/студентам и не тратить время на разъяснения. :)

Если отсюда что-то пригодится кому-то еще – я буду счастлив. С благодарностью приму конструктивную критику и комментарии.

Примерный круг интересов в части «софта» будет следующий:

  1. Языки программирования, ориентированные на инженерное и научное применение: Fortran, Python, Julia, Lisp, Modelica и др. Специализированные библиотеки для этих языков.

  2. Системы компьютерной алгебры / вычислительной математики: Maxima, Sage, Yacas, SymPy / Octave, SciLAB и др.

  3. CAD’ы и CAE для конечноэлементного моделирования механических, электрических, тепловых и гидроаэродинамических процессов (и не только конечноэлементного). CAD’ы для построения геометрии: FreeCAD, OpenSCAD, Solvespace. Генераторы сеток: GMSH, NetGen, Salome. Решатели (и не только): Calculix, Elmer, Code_Aster, Code_Saturne, GetDP, Impact, OpenFoam, FEniCS, MBDyn, OpenModelica и др.

  4. Подготовка документации: языки разметки Markdown, LaTeX и ПО для работы с ними.

Может, будет также что-то еще, но даже так – на не одну длинную жизнь точно хватит. :)

Так сложилось, что ОС мы используем, в основном, Windows. На «идеологически верную» Linux перебираться пытаемся, но пока робко. Из-за привязки к некоторому корпоративному ПО – это не просто. С другой стороны, некоторый специфической софт хорошо работает только в Linux, поэтому приходится жить в двух системах.

Поскольку я не программист и не компьютерный гуру, а лишь инженер, многие вещи будут конспектироваться «тугодумно» с разжевыванием элементарных деталей.

Вроде бы все. Для приличия осталось представиться.

Меня зовут Евгений, родился в 1976.

Образование: 2000 – СПбГТУ (ЛПИ), инженер-радиофизик; 2003 – IMISP, менеджмент; 2010 – ПГУПС (ЛИИЖТ), кандидатская по специальности «Подвижной состав железных дорог, тяга поездов и электрификация».

Живу и работаю в Санкт-Петербурге.