MacでPETScをMPI無しで使う(M1チップ対応)

C/C++やFortrunで使える行列用のライブラリであるPETScを初心者がMacにインストールして、使えるようになるまでの軌跡です。

どのくらい初心者かというと、この手のライブラリを初めてインストールするくらいの初心者です。
（ほぼ、自分用のメモです。）

MPIなしで使うための公式の回答は[こちらのページ](https://petsc.org/release/install/install/)と[こちらのページ](https://www.mcs.anl.gov/petsc/documentation/installation.html#mpi)にあるので、こちらの記事は参考程度に見ていただけると幸いです。

ちなみに何でMPIなしで使おうかと思ったのかというと、MPI関連のデバッグが割と難しいので、最初は無しで使用するのが好ましいという助言をいただいたからです。

MPI無しだと制限される機能が多々あるらしいので、特に理由がなければインストールするようにしましょう。

##~~ダウンロード~~(以下の説明では、`git clone`を使用します。)
[PETScのダウンロードページ](https://www.mcs.anl.gov/petsc/download/index.html)に行きます。

Gitでクローンするか、zipファイルをダウンロードしましょう。
(Macなら、`brew install petsc` でもインストールできます。こちらの場合、例の如く`/usr/local/Cellar/`以下にpetscがインストールされます。ただ、`./configure`の実行ファイルが見当たらず、以下のオプションが指定できるかが謎なのであまり推奨しません。)

[ 追記 2021/12/28 ] 
M1チップ搭載のMacBook Proで`brew install petsc`を試しましたが、`open-mpi`のインストールでエラーが出てしまい、できませんでした。

## インストール ( 2021/12/28に改訂 )

[このページ](https://petsc.org/release/install/install/)の中の、`Installation in Root Location`を参考に、今回はHOMEディレクトリ内の`lib`内にインストールしていきます。
ここの章についてはM1チップ搭載のMacbook pro(Big Sur)を使用しました。
手順は(Webページにある通り)

```sh
mkdir $HOME/lib/petsc
cd $HOME/lib/petsc
git clone -b release https://gitlab.com/petsc/petsc.git .    
# ソースコードからコンパイルする場合は以下
# tar -xzf /*petsc-3.13.0.tar.gzへのパス*/petsc-3.13.0.tar.gz
```
次に,`configure`をしていきます。それ以降については、各コマンドを実行した際に表示される最後のメッセージに従って順番に`make all`と`make check`を行います。

```terminal   
./configure --with-cc=gcc --with-cxx=g++ --download-fblaslapack --with-mpi=0
make PETSC_DIR=/Users/keno/lib/petsc PETSC_ARCH=arch-darwin-c-debug all
make PETSC_DIR=/Users/keno/lib/petsc PETSC_ARCH=arch-darwin-c-debug check
```

自分はBLAS/LAPACKがなかったので、`./configure`のコマンドには、後ろに`--download-fblaslapack `のオプションを付けました。
また、Fortranの使用予定はなかったので`--with-fc`のオプションは明記しませんでした。

MPIなしで使用するには`--with-mpi=0`のオプションが必要です。

[ 追記 (2021/12/29) ]
`make all`でいくつかのライブラリが最新のMacOS用にコンパイルされているというWarningが出ていました。
その後、`make check`でいくつかErrorが出ましたが、私の使用しているプログラムのコンパイルには何も影響はありませんでした。何を使用するかによってこの辺りは変わってくると思われるので、注意してください。


## 環境変数の指定

いくつか環境変数を指定する必要があるっぽいです。
以下の二つを`~/.zshrc`に書き込み、`$ source .zshrc`で環境変数を更新しましょう。

#### 1. PETSC_DIR

```
export PETSC_DIR=$HOME/lib/petsc
```

これは、`make`したりだとか、`configure`した時にも(多分PETScのmakeファイル限定で？)同様のものが定義されているので、公式に環境変数として定義する必要があります。

これは名前の通り、PETScのファイルがあるディレクトリへのパスです。

####2. PETSC_ARCH
>this variable gives a name to a configuration/build.

と公式ドキュメントには書いております。ビルド名？ってこと？

```
export PETSC_ARCH=arch-darwin-c-debug
```

## examples 

PDFのドキュメントの32ページに習って実際に動かしてみましょう。

```terminal

$ cd $PETSC_DIR/src/ksp/ksp/tutorials
$ make ex2
/Users/patrick/petsc/arch-darwin-double-debug/bin/mpicc -o ex2.o -c -Wall -Wwrite-strings -Wno- strict-aliasing -Wno-unknown-pragmas -Qunused-arguments -fvisibility=hidden -g3 -I/Users/ patrick/petsc/include -I/Users/patrick/petsc/arch-darwin-double-debug/include -I/opt/X11/ include -I/opt/local/include ‘pwd‘/ex2.c
/Users/patrick/petsc/arch-darwin-double-debug/bin/mpicc -Wl,-multiply_defined,suppress -Wl,- multiply_defined -Wl,suppress -Wl,-commons,use_dylibs -Wl,-search_paths_first -Wl,- multiply_defined,suppress -Wl,-multiply_defined -Wl,suppress -Wl,-commons,use_dylibs -Wl,- search_paths_first -Wall -Wwrite-strings -Wno-strict-aliasing -Wno-unknown-pragmas -Qunused- arguments -fvisibility=hidden -g3 -o ex2 ex2.o -Wl,-rpath,/Users/patrick/petsc/arch-darwin- double-debug/lib -L/Users/patrick/petsc/arch-darwin-double-debug/lib -lpetsc -Wl,-rpath,/Users /patrick/petsc/arch-darwin-double-debug/lib -lf2clapack -lf2cblas -Wl,-rpath,/opt/X11/lib -L/ opt/X11/lib -lX11 -lssl -lcrypto -Wl,-rpath,/Applications/Xcode.app/Contents/Developer/ Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/7.0.2/lib/darwin -L/Applications/Xcode.app/ Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/7.0.2/lib/darwin -lmpifort
-lgfortran -Wl,-rpath,/opt/local/lib/gcc5/gcc/x86_64-apple-darwin14/5.3.0 -L/opt/local/lib/ gcc5/gcc/x86_64-apple-darwin14/5.3.0 -Wl,-rpath,/opt/local/lib/gcc5 -L/opt/local/lib/gcc5 - lgfortran -lgcc_ext.10.5 -lquadmath -lm -lclang_rt.osx -lmpicxx -lc++ -Wl,-rpath,/Applications/ Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.0.2/lib /darwin -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/ bin/../lib/clang/7.0.2/lib/darwin -lclang_rt.osx -Wl,-rpath,/Users/patrick/petsc/arch-darwin- double-debug/lib -L/Users/patrick/petsc/arch-darwin-double-debug/lib -ldl -lmpi -lpmpi -lSystem
-Wl,-rpath,/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/ bin/../lib/clang/7.0.2/lib/darwin -L/Applications/Xcode.app/Contents/Developer/Toolchains/ XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.0.2/lib/darwin -lclang_rt.osx -ldl
/bin/rm -f ex2.o
$ $PETSC_DIR/lib/petsc/bin/petscmpiexec -n 1 ./ex2 
Norm of error 0.000156044 iterations 6
$ $PETSC_DIR/lib/petsc/bin/petscmpiexec -n 2 ./ex2 
Norm of error 0.000411674 iterations 7
```

計算精度のオーダーも大体一緒でうまくいってそうですね(手元のMacで動かしたので2ノードの計算はやってないと思いますが)

## make install について
多くのライブラリでは`./configure` `make` `make install`とすると勝手にヘッダーファイルやバイナリーファイルがいい感じにパスの通っている場所にコピーされ、どこからでも使えるようになるみたいです。( `/usr/local/include `とか`/usr/bin`とか`/usr/local/bin`とか)
 
PETScはそうではないようで(他に方法があればごめんささい)、インクルード先はmakeファイルに書く必要があります。

どうしても、`make install`したいという方は`DEST_DIR`を指定すると`make install`することができます。

`DEST_DIR`とは、make install でincludeディレクトリやbinディレクトリをコピーする先のパスです。

これを例えば`DEST_DIR = /usr/local/petsc`のように指定するとその中に必要なディレクトリがコピーされます。

適切にmakeファイルを使用すればこの作業は必要ありませんが、もし必要があれば試してみてください。

## PETScを手元で使う

実際に自分のコードにPETScの関数を組み込むには、公式マニュアルの[1.5 Writing Application Codes with PETSc](https://www.mcs.anl.gov/petsc/petsc-current/docs/manual.pdf)を参照し、適切なmakeファイルを作成する必要があります。

`$PETSC_DIR/share/petsc/Makefile.user`を見ると、PETSc.pcというファイルから、`CC`や`CFLAGS`などコンパイルやリンクに必要なオプションが指定されていることがわかります。

実際にそのオプションが`make print`を行うと参照することができます。
今回の場合だと以下のようになります。

```terminal
$ make print
CC=gcc
CXX=g++
FC=gfortran
CFLAGS=-Wall -Wwrite-strings -Wno-strict-aliasing -Wno-unknown-pragmas -fstack-protector -fno-stack-check -Qunused-arguments -fvisibility=hidden -g3
CXXFLAGS=-Wall -Wwrite-strings -Wno-strict-aliasing -Wno-unknown-pragmas -fstack-protector -fno-stack-check -fvisibility=hidden -g -std=c++14
FFLAGS=-Wall -ffree-line-length-0 -Wno-unused-dummy-argument -g
CPPFLAGS=-I/opt/petsc/petsc-3.13.4/arch-darwin-c-debug/include -I/opt/petsc/petsc-3.13.4/include
LDFLAGS=-L/opt/petsc/petsc-3.13.4/arch-darwin-c-debug/lib -Wl,-rpath,/opt/petsc/petsc-3.13.4/arch-darwin-c-debug/lib
LDLIBS=-lpetsc -lm

```

これらのオプションをコピーして以下のようなmakeファイルを作成してもコンパイルすることができます。
例えば、`ex2.c`というファイルをコンパイルするためには

```makefile
CC=gcc
CFLAGS=-Wall -Wwrite-strings -Wno-strict-aliasing -Wno-unknown-pragmas -fstack-protector -fno-stack-check -Qunused-arguments -fvisibility=hidden -g3
#this 'CPPFLAGS' is include option 
CPPFLAGS=-I/opt/petsc/petsc-3.13.4/arch-darwin-c-debug/include -I/opt/petsc/petsc-3.13.4/include
LDFLAGS=-L/opt/petsc/petsc-3.13.4/arch-darwin-c-debug/lib -Wl,-rpath,/opt/petsc/petsc-3.13.4/arch-darwin-c-debug/lib
LDLIBS=-lpetsc -lm

OBJECTS=ex2.o

TARGETS = ex2

all : $(TARGETS) 

.SUFFIXES:
.SUFFIXES: .c .o
.c.o:
	$(CC) -c -o $@ $(CFLAGS) $(CPPFLAGS) $<

ex2 : $(OBJECTS)
	$(CC) -o $@ $(OBJECTS) $(LDFLAGS) $(LDLIBS)

clean:
	rm -f core *~ *.o $(TARGETS)
```

以下のように記述すると、うまくいきます。

[追記1/13]
わざわざ`make print`をしてコピーをしなくても、`$PETSC_DIR/share/petsc/Makefile.user`を見ると、PETSc.pcというファイルから、`CC`や`CFLAGS`などコンパイルやリンクに必要なオプションが自動的に指定されるので、その下に追加のオプションなり、上の例文の`OBJECTS`以下の部分を書き込めばOKです。

## 参照
[公式ドキュメント](https://www.mcs.anl.gov/petsc/documentation/index.html)