FDPS 講習会 C++編
細野 七月//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

習得しておきたいC++の機能◆FDPS用いるにおいて、知っておきたいC++の機能- 名前空間- PS::F64 など- クラス- メンバ変数とメンバ関数- テンプレート- template <typename T> など- 標準ライブラリ- std::vectorやstd::cout など
ただし今回のサンプルコードではI/O用のstd::coutなどが使われている程度なので省略
これ以上の事は基本的に必要ない。

//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：名前空間とは◆グローバルな変数、関数、型名などの名前被りを防ぐ機能。
FDPSでは、F64vecといった型が存在している(後述)が、これはFDPSが用意したPSという名前空間に含まれているので、ユーザーが独自にF64vecという型を定義する事ができる。
◆名前空間へのアクセスは::演算子を用いる。
.
﹁
曇
1,‑
.

PS::F64vec v_FDPS; // FDPS組み込みベクトル型︷．
｀

ビ~▲ユ―`~

饂 i,
t1・1．｀立• ” `r・// ユーザー定義ベクトル型

F64vec v_user;//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：クラスとは◆複数のデータをまとめたもの。
Cで言うところの構造体。
◆クラスを使うと- 演算子を定義出来る。
- サブルーチンに値を送るときに楽。
- 後からデータ付け足すのも楽。
◆FDPSでは、ユーザーは粒子データをまとめた粒子クラスを記述する必要がある。
また、2D/3Dベクトルをやりとりするのに便利なベクトルクラスが用意されている。
//==================================\\
位置や速度にはこのFDPSが用意したベクトルクラスを用いることを推奨。
|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：クラス例(ベクトルクラス)◆数学演算子が既に定義済みのため、直感的に書ける。
C++のI/Oである、std::coutにわたす事も可能。
町i

·~ぞ’

•PS::F64vec v1 = PS::F64vec( 1.0,
‑

‑ 』 ・

9 冒Jーゴゴリ︑↓幽・t

2.5, -3.0);
PS::F64vec v2 = PS::F64vec(-2.0, -1.5, 2.0);

l

i

,.﹁

i

g
'.19

i

；

，
＇
i
,"
̀
9
︑
.
ì
̀

‑44キ＂

︐冒｀︱

PS::F64vec v_add = v1 + v2;
PS::F64vec v_sub = v1 - v2;
PS::F64
inner = v1 * v2;
PS::F64vec outer = v1 ^ v2;
std::cout << v_add.x << std::endl;
std::cout << v_sub<< std::endl;

1

！

.
9↓

‑
̀
―

i
．看 ヽ 巳・//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：クラス例(粒子クラス)

Nbody個の粒子必要なデータは…
- mass- position(x, y, z)- velocity(x, y, z)- acceleration(x, y, z)//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：クラス例(粒子クラス)

Nbody個の粒子
f
i
,'
u,

double mass[Nbody];
double position[Nbody][3];double velocity[Nbody][3];double acceleration[Nbody][3];：//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：クラス例(粒子クラス)

Nbody個の粒子r・軍,

class FPGrav{
double mass;
double position[3];double velocity[3];double acceleration[3];}body[Nbody];//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：クラス例(粒子クラス)

Nbody個の粒子rclass FPGrav{
PS::F64
mass;
PS::F64vec position;
PS::F64vec velocity;
PS::F64vec acceleration;}body[Nbody];

クラス内クラスも可能//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：クラスのメリット◆クラスを使うとサブルーチンに値を送るときに簡単に書ける。
後からデータを付け足すのも楽。
void doSomething(double mass[],
double position[][3],double velocity[][3],double acceleration[][3]){//do something here}
void doSomething(FPGrav particle[]){//do something here}//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：メンバ関数◆クラス内の変数(メンバ変数)達に対して、何らかの処理を加えたい時に記述するもの。
アクセスには.演算子を用いる。
◆FDPSの場合、FDPSとユーザーコード間でデータのやりとりをするためのメンバ関数を書く必要がある。
class FPGrav{
PS::F64
mass;
PS::F64vec position;
PS::F64vec velocity;
PS::F64vec acceleration;
PS::F64vec getPos(){
return position;}}body[Nbody];
PS::F64vec position = body[0].getPos();//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：テンプレート◆同じ処理を違う型に対して行いたい時に書くもの。
クラスをテンプレート化したクラステンプレートと、関数をテンプレート化した関数テンプレートが存在する。
◆まずクラステンプレートについて解説し、その後関数テンプレートに関して解説する。

//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：クラステンプレート◆FDPSでは、粒子群クラステンプレートの< >の中に粒子クラスを入れる事で、粒子群クラスの実体が作られる。
同様に、相互作用ツリークラスの実体も作られる。
//粒子群クラス
PS::ParticleSystem<FPGrav> system_grav;//相互作用ツリークラス
PS::TreeForForceLong<FPGrav, FPGrav, FPGrav> Monopole tree_grav;//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：関数テンプレート◆FDPSでは相互作用関数は関数テンプレートを用いて記述出来る。
◆関数テンプレートを用いずに記述する事も可能だが、相互作用が長距離力の場合、計算内容的には全く同じものにも関わらず、近傍の粒子からの相互作用とツリーノードからの相互作用2つを書かなければならない。
◆関数テンプレートを用いると記述するのは1つだけで済むので、今回は関数テンプレートを用いたサンプルコードを紹介する。

//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

C++の機能：関数テンプレート(続き)◆FDPSでは、ツリーノードクラスは既に用意されている(PS::SPJMonopole)ため、それを使う。

ヽ

て 彎

,,
.
←

‑・"ヘ・，

・一．
9＝ . .』 .‑‑ 9し・9 ‑、 ‑‘,'·'9

ー

,

99

ヽ

罫

＇

.
.49

l

一

'

し一←ー疇盲

ヽ
・
・
＇
︐

‑99

＇
.
.

~一

︐i

＇

•=-·>ヽ亀う

―
̀

,.、
』~

template <class TparticleJ>
void CalcGravity(const FPGrav * ep_i,
const PS::S32 n_ip,
const TParitcleJ * ep_j,
const PS::S32 n_jp,
FPGrav * force){for(PS::S32 i = 0 ; i < n_ip ; i ++){
PS::F64vec xi = ep_i[i].getPos();for(PS::S32 j = 0 ; j < n_jp ; j ++){
PS::F64vec rij = x_i - ep_j[j].getPos();//calc gravity}}}

i~←i・Jr◆相互作用関数はSPJMonopoleも使うので、getPos();などを用いて書く必要がある。

//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

コード構成◆ユーザーが書くべきものは、- #include <particle̲simulator.h>- 粒子クラスと必要なメンバ関数- 相互作用関数- 時間積分ルーチン- I/O (粒子クラスのI/Oと、FileHeaderクラス)//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード◆今回のサンプルコードの内容- 粒子間相互作用は、重力- Phantom-GRAPE (Tanikawa+, 2011; 2012) ありとなし両方- 時間積分法はleap-frog法- 初期条件はその場生成- ファイル読み込みではない◆ファイル構成- user-deﬁned.hpp- nbody.cpp
他にも色々入っているが必要なものはすべてこの2つの中にある//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード user̲deﬁned.hpp

粒子クラス
物理量

//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード user̲deﬁned.hpp

メンバー関数//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード user̲deﬁned.hpp
I/O用メンバー関数//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード user̲deﬁned.hpp
関数テンプレート
Phantom GRAPEあり//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード user̲deﬁned.hpp//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード user̲deﬁned.hpp
相互作用関数テンプレート

メンバ関数呼び出し//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

PS::F64 poti = 0.0;
for(PS::S32 j = 0; j < n_jp; j++){
PS::F64vec rij= xi - ep_j[j].getPos();
PS::F64r3_inv = rij * rij + eps2;
PS::F64r_inv = 1.0/sqrt(r3_inv);
r3_inv = r_inv * r_inv;
r_inv *= ep_j[j].getCharge();r3_inv *= r_inv;ai-= r3_inv * rij;poti-= r_inv;}
force[i].acc += ai;force[i].pot += poti;

サンプルコード user̲deﬁned.hpp}}#endif//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード user̲deﬁned.hpp◆user̲deﬁned.hppはこれだけ。
おおよそ150行。

//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード nbody.cpp

FDPSのヘッダー読み込み//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード nbody.cpp

粒子数が取得可能//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード nbody.cpp

粒子群クラスに[i]をつけると粒子データにアクセス可能//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード nbody.cpp
メイン関数開始//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード nbody.cpp

FDPSの初期化//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード nbody.cpp
粒子群クラスの生成と初期化//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード nbody.cpp

ドメイン情報クラスの生成と初期化、領域分割//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード nbody.cpp

粒子交換//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード nbody.cpp

相互作用ツリークラスの生成と初期化//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード nbody.cpp

相互作用関数を用いた力の計算//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード nbody.cpp
時間積分//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード
nbody.cpp#else

dinfo,
n_walk_limit,true);

tree_grav.calcForceAllAndWriteBack(CalcGravity<FPGrav>,
CalcGravity<PS::SPJMonopole>,system_grav,
dinfo);#endifkick(system_grav, dt * 0.5);n_loop++;}#ifdef ENABLE_PHANTOM_GRAPE_X86
g5_close();#endif
PS::Finalize();
return 0;}

FDPS終了//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

サンプルコード nbody.cpp◆nbody.cppはこれだけ。
おおよそ350行。

//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

最後に◆ユーザーが書かなくてはいけないのは、150+350 = 500行 程度。
この500行の中には、コマンドライン引数などの解析も含むため、そのようなものが必要なければ実際には更に少なくて済む。
◆コード内に、並列化を意識しなくてはならないような場所は無かった。
つまり、コンパイルの方法だけでOpenMPやMPIを切り替えられる。

//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//

実習の流れ◆サンプルコードを(1)並列化なし (2)OpenMP (3)OpenMP + MPIの3パターンに関してコンパイルし、実行
サンプルコードは以下の2つ- 重力 cold collapse- 流体 (Smoothed Particle Hydrodynamics法) adiabatic sphere collapse
実行が終わったら、結果の解析
詳しくは、以下の講習会URLを参照
http://www.jmlab.jp/?p=1188//==================================\\|||| || ::::::: ::::::.
::::::. .::::::. || || :::: : :: :::|| || :::::: :: : ::::::' `:::::.
|| || ::::::::' ::` ...........' ||||Framework for Developing|| ||Particle Simulator|| \\==================================//