ParticleSampler_JP - CCSEPBVR/CS-IS-PBVR GitHub Wiki
シミュレーションコードにgenerate_partices関数を挿入することで、粒子サンプラがIn-Situに可視化用粒子を生成できるようになる。
この関数はkvs_wrapper.hで定義されており、粒子生成ライブラリを参照・リンクすることで使用可能となる。
シミュレーションに結合された粒子サンプラはシミュレーションのバッチ処理と共に実行され、環境変数と伝達関数ファイルを参照しながら計算結果のボリュームデータを可視化用粒子データに変換する。
粒子サンプラはPARTICLE_DIRで指定されたディレクトリに粒子データファイルと、領域の最小最大値を記したt_pfi_coords_minmax.txtファイルを出力する。
粒子データファイルは、ヘッダファイル(kvsml)、座標ファイル(coord.dat)、色ファイル(color.dat)、法線ファイル(normal.dat)で構成されており、各タイムステップで1ノードにつき1組ずつ出力される。
同時に粒子サンプラはVIS_PARAM_DIRに伝達関数の変更履歴を記した$TF_NAME_タイムステップ.tfファイルとヒストグラムや可視化対象の物理値のレンジを記したhistory_タイムステップ.txtファイル、処理タイムステップ区間を記したstate.txtを出力する。
#include “kvs_wrapper.h”
void generate_particles( int time_step, domain_parameters dom, Typs** volume_data, int num_volume_data );
この関数はシミュレーションのタイムステップや計算領域の錠法、シミュレーション結果のボリュームデータを引数とする。
-
int time_step : シミュレーションタイムステップ
-
domain_parameters dom : 以下に示す計算領域を定義する構造体
typedef struct { float x_global_min; //全計算領域のx座標の最小値 float y_global_min; //全計算領域の y 座標の最小値 float z_global_min; //全計算領域の z 座標の最小値 float x_global_max; //全計算領域のx座標の最大値 float y_global_max; //全計算領域の y 座標の最大値 float z_global_max; //全計算領域の z 座標の最大値 float x_min; //部分領域のx座標の最小値 float y_min; //部分領域の y 座標の最小値 float z_min; //部分領域の z 座標の最小値 int* resolution; //格子解像度 int resolution[3]へのポインタ float cell_length; //格子の単位長さ } domain_parameters;
- Types** volume_data : シミュレーション結果のボリュームデータの配列へのポインタ。Typeはユーザ指定の物理値の型であり、多変数のボリュームデータは2次元配列として定義される。格子解像度(X,Y,Z)のボリュームデータにおいて、n番目の変数の位置(i, j, k)の値はvolume_data[n][i+jX+kX*Y]で参照する。
- int num_volume_data : 変数の数
#include “kvs_wrapper.h”
void generate_particles(
int time_step, domain_parameters dom, Type** values, int nvariables, float* coordinates,
int ncoords, unsigned int* connections, int ncells,
const pbvr::VolumeObjectBase::CellType& celltype );
この関数はシミュレーションのタイムステップや計算領域の錠法、シミュレーション結果のボリュームデータ、非構造格子の格子錠法を引数とする。
-
int time_step : シミュレーションタイムステップ
-
domain_parameters dom : 以下に示す計算領域を定義する構造体
typedef struct { float x_global_min; //全計算領域のx座標の最小値 float y_global_min; //全計算領域の y 座標の最小値 float z_global_min; //全計算領域の z 座標の最小値 float x_global_max; //全計算領域のx座標の最大値 float y_global_max; //全計算領域の y 座標の最大値 float z_global_max; //全計算領域の z 座標の最大値 } domain_parameters;
- Typs** volume_data:シミュレーション結果のボリュームデータの配列へのポインタ。Type はユーザ指定の物理値の型であり、多変数のボリュームデータは 2 次元配列として定義される。n 番目の変数の cell 番目の頂点上の値は volume_data[n][cell]で参照する。
- float* coordinates:頂点座標の配列へのポインタ。i 番目の頂点座標(x,y,z)は(coordinates[3i],coordinates[3i+1], coordinates[3*i+2])で参照する。
- int ncoords:頂点の数。
- unsigned int* connections:六面体要素を構成する頂点 ID の接続リストへのポインタ。六面体要素の構成を以下の図に示す。i 番目の六面体要素の n 番目の頂点は connections[8*i+n]で参照する。
- int ncells:要素の数。
- pbvr::VolumeObjectBase::CellType& celltype:要素タイプ。IS-PBVR は四面体、六面体、ピラミッド、プリズム、四面体二次要素、六面体二次要素が使用可能である。各要素タイプは以下のファイルの VolumeObjectBase クラス内で定義されている。/DaemonAndSampler/InSituLib/unstruct/TFS/VolumeObjectBase.h
In-Situ PBVR ではメニーコア計算機のメモリレイアウトに最適化された階層格子構造(Block Structured AMR)をサポートしている。 このタイプの格子は、N3の直交格子を最小の処理領域の単位(リーフ)と定義し、各階層でサイズの異なるリーフが接続されている。 そのため Block Structured AMRは NxNxNxL(L はリーフ数)の四次元格子として定義される。 以下に二次元の例を示す。
#include “kvs_wrapper.h”
void generate_particles(
int time_step, domain_* parameters dom,
std::vector<float>& leaf_length,
std::vector<float>& leaf_min_coord,
int nvariables, float** values);
この関数はシミュレーションのタイムステップや計算領域の情報、階層格子の構成情報、シミュレーション結果のボリュームデータを引数とする。
-
int time_step : シミュレーションタイムステップ。
-
domain_patameters dom : 以下に示す計算領域を定義する構造体。
typedef struct { float x_global_min; //全計算領域のx座標の最小値 float y_global_min; //全計算領域の y 座標の最小値 float z_global_min; //全計算領域の z 座標の最小値 float x_global_max; //全計算領域のx座標の最大値 float y_global_max; //全計算領域の y 座標の最大値 float z_global_max; //全計算領域の z 座標の最大値 int* resolution; //格子解像度 int resolution[4]へのポインタ } domain_parameters;
-
std::vector& leaf_length:リーフの長さの配列への参照。l 番目のリーフの長さはleaf_length[l]で参照する。
-
std::vector& leaf_min_coord:リーフの最小位置座標の配列への参照。l 番目のリーフの座
-
標は(leaf_min_coord[3l], leaf_min_coord[3l+1], leaf_min_coord[3l+2])で参照する。float** values:シミュレーション結果のボリュームデータの配列へのポインタ。多変数のボリュームデータは 2 次元配列として定義される。格子解像度(X,Y,Z,L)のボリュームデータにおいて、n 番目の変数の位置(i,j,k,l)の値は values[n][i+jX+kXY+lXY*Z]で参照する。
-
int nvariables:変数の数
ユーザのシミュレーションコードに generate_particles 関数を組み込みコンパイルすることで、In−Situ 可視化が可能になる。 この章ではテストシミュレーションコードを例とした粒子サンプラの組み込み手順を示す。 テストシミュレーションコードは、水素の電荷密度の式により各タイムステップで格子頂点上に電荷密度の値を計算する。 そのため計算するクラス名は Hydrogen となっている。粒子サンプラの組み込みがない状態のコードは以下のようになっている。
#include "Hydrogen.h"
#include <iostream>
#include <mpi.h>
int main( int argc, char** argv )
{
MPI_Init(&argc, &argv);
Hydrogen hydro;
int time_step = 0;
for(;;)
{
hydro.values;
time_step++;
}
MPI_Finalize();
return 0 ;
}
上記ソースコードにおいて、Hydrogenクラスはfor文中のhydro.valuesで各タイムステップのボリュームデータを出力している。
generate_particles 関数は構造体 domain_parameters によって領域情報を取得する。 ユーザはシミュレーションコードから得られる領域情報を構造体にコピーする必要がある。
int mpi_rank;
MPI_Comm_rank( MPI_COMM_WORLD, &(mpi_rank) );
int resol[3] = { hydro.resolution.x(), hydro.resolution.y(), hydro.resolution.z() };
domain_parameters dom = {
hydro.global_min_coord.x(),
hydro.global_min_coord.y(),
hydro.global_min_coord.z(),
hydro.global_max_coord.x(),
hydro.global_max_coord.y(),
hydro.global_max_coord.z(),
hydro.global_region[mpi_rank].x(),
hydro.global_region[mpi_rank].y(),
0.0,
resol,
hydro.cell_length
};
上記コードでは、Hydrogen の部分領域の情報を得るために MPI のランク数を取得している。 領域情報とシミュレーション結果のボリュームデータを generate_particles 関数に入力する。 generate_particles 関数はタイムステップループの内部でシミュレーション後にコールされる。 Hydrogen の例の場合、以下のように挿入される。
int time_step = 0;
for(;;) {
generate_particles( time_step, dom, hydro.values, hydro.nvariables )
time_step++;
}