czwartek, 9 czerwca 2016

Instalacja FreeFem++ w systemie Ubuntu 16.04

FreeFem++

Zapewne nie ma programisty, który by nie znał języka C++. Ale czy ktokolwiek z was słyszał o języku FreeFem++?
Ostatnio miałem z nim do czynienia w związku z problemem, który wymagał rozwiązywania równań różniczkowych cząstkowych metodą elementów skończonych (ang. finite element method, w skrócie FEM); zob. np. [MES, Wikipedia].
Język ten powstał w laboratorium Jacques-Louis Lions należącego do Universit´e Pierre et Marie Curie w Paryżu. Zdołał nawet zgromadzić wokół siebie całkiem sporą grupę użytkowników, głównie matematyków i fizyków z Francji. Można znaleźć sporo dokumentacji, co ważne, nawet w języku w angielskim :-). Głównym powodem, dla którego warto używać FreeFem++ jest prostota i bardzo efektywna wydajność wielu metod numerycznych, które współpracują z metodą FEM. Język umożliwia stosowanie wielu zaawansowanych technik rozwiązywania układów równań z macierzami rzadkimi, jakie często pojawiają się w metodzie FEM.
Strona główna projektu FreeFem++ znajduje się tutaj
http://www.freefem.org/
Stamtąd można pobrać właściwie całe oprogramowanie zarówno pod system Windows, Linux, jak i MacOS.

Instalacja w systemie Ubuntu 16.04

FreeFem++ można bez problemu zainstalować w systemie Ubuntu wykorzystując odpowiednio przygotowane pakiety, dostępne bezpośrednio z polecenia
sudo apt-get install freefem++ libfreefem++
Po wykonaniu tego polecenia w systemie będziemy mieli cały zestaw bibliotek, umieszczonych domyślnie w katalogu
/usr/lib/freefem++
wraz z programem FreeFem++, katalogu /usr/bin/

Kompilacja

Ponieważ pakiety FreeFem++ dostępne w repozytoriach Ubuntu 16.04 są w wersji 3.38, a obecnie dostępna wersja stabilna na stronie projektu to 3.46, więc pomyślałem, że warto spróbować dokonać kompilacji całego oprogramowania na własną rękę.
I tutaj zaczyna się szereg problemów.

Teoretycznie wszystkie szczegóły można znaleźć na stronie
http://www.freefem.org/ff++/linux.php
Pomyślałem jednak, że pomogę niektórym, bo nie wszystko idzie tak gładko, jak to opisali autorzy projektu.

Krok 1.

Po pierwsze, należy pobrać archiwum dostępne na stronie
http://www.freefem.org/ff++/ftp
Gdy pisałem tę notatkę najnowsza wersja znajduje się tutaj
http://www.freefem.org/ff++/ftp/freefem++-3.46.tar.gz
http://www.freefem.org/ff++/ftp/freefem++-3.46.tar.gz
Po pobraniu i próbie rozpakowania pojawia się drobny problem. Być może jest to wina przeglądarki Google Chrome, której używam. Otóż, na stronie jest napisane, że wielkość pliku to 25MB, podczas gdy po kliknięciu na powyższy link pobiera się plik o rozmiarze 125MB.
Chodzi o to, że pobrany plik jest jakby automatycznie rozpakowywany (programem gzip).
W ten sposób otrzymany plik nie jest archiwum tar.gz, lecz tylko tar i należy rozpakować je poleceniem
tar xf freefem++-3.46.tar.gz
a nie
tar zxf freefem++-3.46.tar.gz

Krok 2.

Po rozpakowaniu otrzymujemy katalog freefem++-3.46, do którego wchodzimy poleceniem
tar zxf freefem++-3.46
Zanim przejdziemy do kompilacji, a następnie do instalacji, najlepiej jest upewnić się, że mamy zainstalowane wymagane pakiety. Ja zainstalowałem wszystkie podane przez autorów:
sudo apt-get install cpp freeglut3-dev g++ gcc gfortran ghostscript m4 make patch pkg-config wget python libopenblas-dev liblapack-dev libhdf5-dev libgsl0-dev libscotch-dev libfftw3-dev libarpack2-dev libsuitesparse-dev libmumps-seq-dev libnlopt-dev coinor-libipopt-dev libgmm++-dev libtet1.5-dev autoconf automake autotools-dev bison flex gdb valgrind mercurial gnuplot-qt mpich
Następnie wykonujemy polecenia, tak jak to opisano na stronie:
./configure --enable-download
download/getall -a
make
sudo make install
Jeśli ostatniego kroku nie chcemy wykonywać jako root, wystarczy uprzednio skonfigurować
./configure --enable-download --prefix=/path_to_usr_local
Jeśli tego nie zrobimy, to domyślnie FreeFem++ zainstaluje się w katalogu /usr/local/bin/
Natomiast wszystkie biblioteki zainstalują się w katalogu /usr/local/lib/ff++/3.46/lib, a nagłówki w /usr/local/lib/ff++/3.46/include.

Teoretycznie FreeFem++ powinien być już dostępny.
Okazuje się, że jeszcze nie.

Biblioteka libhdf5.so.10

Przy pierwszej próbie uruchomienia FreeFem++ otrzymujemy błąd iż system nie potrafi odnaleźć biblioteki (łączonej dynamicznie) libhdf5.so.10. Nie udało mi się znaleźć dokładnie takiej biblioteki dla systemu Ubuntu 16.04. Jedyne co znalazłem to pakiet libhdf5-dev
sudo apt-get install libhdf5-dev
który daje, m.in., plik /usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5.so
Wydaje mi się, że przyczyną problemu jest to, że w systemie Ubuntu mam zainstalowany python z dystrybucji anaconda3; zob. https://www.continuum.io/downloads
Wymaganą bibliotekę libhdf5.so.10 znalzłem właśnie tam, gdzie mam zainstalowaną anaconda3, czyli tutaj
anaconda3/lib/libhdf5.so.10
Aby jednak nie zmieniać LD_LIBRARY_PATH, czego nie lubię robić, dodałem do systemu takie łącze
cd /usr/lib/x86_64-linux-gnu/
sudo ln -s my_path/anaconda3/lib/libhdf5.so.10
Po wykonaniu
sudo ldconfig
wymagana biblioteka jest już dostępna i FreeFem++ uruchamia się bez problemów.

Biblioteki medit.so, tetgen.so, ...

Jeśli będziemy mieli dużo szczęścia, to próba uruchomienia skryptu *.edp (takie rozszerzenia mają programy napisane w języku FreeFem++) z poleceniem
load "medit"
load "msh3"
load "tetgen"
odnajdzie biblioteki
/usr/local/lib/ff++/3.46/lib/medit.so
/usr/local/lib/ff++/3.46/lib/msh3.so
/usr/local/lib/ff++/3.46/lib/tetgen.so
i wszystko przebiegnie bez problemów.
Swoją drogą warto uruchamiać FreeFem++ z polecenia
FreeFem++ -v 10
 a więc z większą liczbą verbosity (domyślnie jest 0). Możemy się wówczas przekonać, że nasz FreeFem++ szuka tych bibliotek w następującej kolejności (przykład dla medit.so)
addInitFunct : -10000 call : 1 (  ) 
addInitFunct : -20 call : 1 ( lg_fem  UMFPACK  ) lg_mesh  glumesh2D lg_mesh3 eigenvalue 
load "medit"
test dlopen(/usr/lib/freefem++/medit)= 0
load error was: /usr/lib/freefem++/medit: cannot open shared object file: No such file or directory
test dlopen(/usr/lib/freefem++/medit.so)= 0
load error was: /usr/lib/freefem++/medit.so: cannot open shared object file: No such file or directory
test dlopen(./medit)= 0
load error was: ./medit: cannot open shared object file: No such file or directory
test dlopen(./medit.so)= 0
load error was: ./medit.so: cannot open shared object file: No such file or directory
test dlopen(/usr/local/lib/ff++/3.46/lib/medit)= 0
load error was: /usr/local/lib/ff++/3.46/lib/medit: cannot open shared object file: No such file or directory
 ****  medit.cpp ****
 -- addInitFunct: 10000 1 medit.cpp
test dlopen(/usr/local/lib/ff++/3.46/lib/medit.so)= 0x227e1d0
(load: dlopen /usr/local/lib/ff++/3.46/lib/medit.so 0x227e1d0)  callInitsFunct : 1
 addInitFunct : 10000 call : 1 ( 
 loadfile medit.cpp
 load:popen.cpp  
 ) 
Widzimy więc, że program znalazł potrzebną bibliotekę dopiero przy szóstej próbie.

Uwaga

Co ważne, jeśli ktoś zdecyduje się posiadać dwie wersje FreeFem++ i zostawi zainstalowny pakiet libfreefem++ z repozytorium Ubuntu 16.04, to powyższy proces wyszukiwania np. biblioteki medit.so zakończy się już przy drugiej próbie, tj. znajdzie plik
/usr/lib/freefem++/medit.so
czyli biblioteki dla wersji 3.38 (taki jest obecny stan repozytorium Ubuntu 16.04).
Może zakończyć to się problemem, gdy będziemy uruchamiali skompilowany przez nas program FreeFem++ w wersji 3.46.

Testy

Jeszcze nie testowałem użycia takich bibliotek jak np. MPI, czy różnych metod rozwiązywania układów równań dla macierzy rzadkich. Na potwierdzenie sukcesu swojej kompilacji mogę powiedzieć tylko tyle, że udało mi się przejść wszystkie testy dostępne z polecenia
make check

Zakończenie

Życzę miłego używania najnowszej wersji FreeFem++ w systemie Ubuntu 16.04