177 lines
5.8 KiB
C
177 lines
5.8 KiB
C
#include "dump2analysis.h"
|
|
/* DOCUMENT */
|
|
/* -m msd */
|
|
/* lammpstrjから指定した原子の平均二乗変位(MSD)を時間シフトしながら計算する */
|
|
/* 原子タイプで指定しても最初のステップのidで原子を選択する */
|
|
/* --shfitと--tauを小さくすればMSDの統計が稼げる。ただしシフトが小さすぎるMSDが変化する。 */
|
|
/* --shiftでMSDが変わらないようパラメータを調整する。 */
|
|
/* 教科書Pを参照 */
|
|
/* A原子(-a, -x, -s)を指定する。 */
|
|
/* --shiftはMSDを計算する時にシフトさせるステップ default:1 */
|
|
/* --tauはMSDを計算する時間ステップ範囲。-1でMDの全ステップでMSDを計算する default:-1 */
|
|
/* --dtはMDの時間ステップでの時間(fs単位) default:1.0 */
|
|
|
|
void ErrorMSD(){
|
|
printf("Required arguments atoms A\n");
|
|
printf("(-a, -x, -s) atom A\n");
|
|
printf("------------------------------------------------------------\n");
|
|
printf("Optional arguments for MSD analysis:\n");
|
|
printf("--shift time shift for MSD [1]\n");
|
|
printf("--tau time period for MSD (-1: all steps [-1]\n");
|
|
printf("--dt time period for one step (fs) [1.0]\n");
|
|
printf("------------------------------------------------------------\n");
|
|
printf("Example:\n");
|
|
printf("dump2analysis -m msd -x Li --dt 1.2 --tau 2500 --shift 100 -i hoge.lammpstrj -o hoge.msd\n");
|
|
exit(0);
|
|
}
|
|
|
|
void OutputMSD(PARAM *p, double **msd, ATOMS *a, int step){
|
|
int i;
|
|
double t;
|
|
FILE *f;
|
|
|
|
f = fopen(p->outfile, "w");
|
|
fprintf(f, "# Atomic list: ");
|
|
for (i=0; i<a->atoms; i++) fprintf(f, "%s(%d) ", a->elem[i], a->id[i]);
|
|
fprintf(f, "\n");
|
|
fprintf(f, "# TAU: %d\n", TAU);
|
|
fprintf(f, "# TAU_SHIFT: %d\n", TAU_SHIFT);
|
|
fprintf(f, "# total TAU step: %d\n", step);
|
|
fprintf(f, "# atoms: %d\n", a->atoms);
|
|
fprintf(f, "# %12s ", "time/fs");
|
|
fprintf(f, "%14s ", "msd/Ang.2");
|
|
fprintf(f, "%14s ", "a/Ang.2");
|
|
fprintf(f, "%14s ", "b/Ang.2");
|
|
fprintf(f, "%14s ", "c/Ang.2");
|
|
fprintf(f, "\n");
|
|
for (i=0; i<TAU; i++){
|
|
t = i * (double)DT;
|
|
fprintf(f, "%14lf ", t);
|
|
fprintf(f, "%14e ", msd[0][i]);
|
|
fprintf(f, "%14e ", msd[1][i]);
|
|
fprintf(f, "%14e ", msd[2][i]);
|
|
fprintf(f, "%14e ", msd[3][i]);
|
|
fprintf(f, "\n");
|
|
}
|
|
fclose(f);
|
|
|
|
}
|
|
|
|
void EstimateMSD(PARAM *param){
|
|
int i, j, k, p, step_counter=0;
|
|
FILE *f;
|
|
HEAD *head;
|
|
double A[3][3];
|
|
ATOMS a;
|
|
double **xx, **yy, **zz;
|
|
double **msd; /* r, a, b, c */
|
|
double xp, yp, zp;
|
|
double r, sum[4], dx, dy, dz;
|
|
|
|
if (ArgCheckInputOutput(param) != 0) ErrorMSD();
|
|
SetAtomsSteps(param);
|
|
if (CheckArgAtomSelect(param) != 1) ErrorMSD();
|
|
|
|
/* 選択元素が変わるとおかしくなるので元素選択は全てid */
|
|
SetIDfromElemTtype(param);
|
|
Allocate(&a, param->Aid[0]-1);
|
|
head = malloc(sizeof(HEAD) * param->steps);
|
|
f = fopen(param->infile, "r");
|
|
|
|
/* -1の場合は全ステップでMSDを計算する */
|
|
if (TAU == -1) {
|
|
TAU = param->steps;
|
|
TAU_SHIFT = param->steps;
|
|
}
|
|
|
|
/* steps * atoms * (x, y, z)のメモリ取得 */
|
|
xx = malloc(sizeof(double*) * param->steps);
|
|
yy = malloc(sizeof(double*) * param->steps);
|
|
zz = malloc(sizeof(double*) * param->steps);
|
|
for(i=0; i<param->steps; i++){
|
|
xx[i] = malloc(sizeof(double) * a.atoms);
|
|
yy[i] = malloc(sizeof(double) * a.atoms);
|
|
zz[i] = malloc(sizeof(double) * a.atoms);
|
|
}
|
|
|
|
/* 分率座標のデータを全ステップで取得する */
|
|
printf("Loading data...\n");
|
|
fflush(stdout);
|
|
for (i=0; i<param->steps; i++){
|
|
GetData(f, param, &head[i], &a, NULL, NULL);
|
|
/* xx, yy, zzは分率座標 */
|
|
for (j=0; j<a.atoms; j++){
|
|
xx[i][j] = a.x[j];
|
|
yy[i][j] = a.y[j];
|
|
zz[i][j] = a.z[j];
|
|
}
|
|
}
|
|
/* 分率座標のwarapを解く */
|
|
Unwrap(param->steps, a.atoms, xx, yy, zz);
|
|
|
|
/* msdの計算 r, a, b, c*/
|
|
/* メモリ確保と初期化 */
|
|
msd = malloc(sizeof(double*) * 4);
|
|
for(i=0; i<4; i++) msd[i] = malloc(sizeof(double) * TAU);
|
|
for (k=0; k<4; k++)
|
|
for (i=0; i<TAU; i++) msd[k][i] = 0.0;
|
|
|
|
for (p=0; p+TAU <= param->steps; p=p+TAU_SHIFT){
|
|
printf("MSD step range: from %d to %d\n", p, p+TAU);
|
|
fflush(stdout);
|
|
for (i=0; i<TAU; i++){
|
|
for (k=0; k<4; k++) sum[k] = 0.0;
|
|
for (j=0; j<a.atoms; j++){
|
|
dx = xx[p+i][j] - xx[p][j];
|
|
dy = yy[p+i][j] - yy[p][j];
|
|
dz = zz[p+i][j] - zz[p][j];
|
|
/* nptのための処理。正しいか検討すること */
|
|
A[0][0] = (head[p+i].A[0][0] + head[p].A[0][0])*0.5;
|
|
A[0][1] = (head[p+i].A[0][1] + head[p].A[0][1])*0.5;
|
|
A[0][2] = (head[p+i].A[0][2] + head[p].A[0][2])*0.5;
|
|
A[1][0] = (head[p+i].A[1][0] + head[p].A[1][0])*0.5;
|
|
A[1][1] = (head[p+i].A[1][1] + head[p].A[1][1])*0.5;
|
|
A[1][2] = (head[p+i].A[1][2] + head[p].A[1][2])*0.5;
|
|
A[2][0] = (head[p+i].A[2][0] + head[p].A[2][0])*0.5;
|
|
A[2][1] = (head[p+i].A[2][1] + head[p].A[2][1])*0.5;
|
|
A[2][2] = (head[p+i].A[2][2] + head[p].A[2][2])*0.5;
|
|
|
|
xp = dx*A[0][0] + dy*A[1][0] + dz*A[2][0];
|
|
yp = dx*A[0][1] + dy*A[1][1] + dz*A[2][1];
|
|
zp = dx*A[0][2] + dy*A[1][2] + dz*A[2][2];
|
|
|
|
r = pow(xp, 2) + pow(yp, 2) + pow(zp, 2);
|
|
sum[0] = sum[0] + r;
|
|
sum[1] = sum[1] + dx*dx*head[p+i].a*head[p+i].a;
|
|
sum[2] = sum[2] + dy*dy*head[p+i].b*head[p+i].b;
|
|
sum[3] = sum[3] + dz*dz*head[p+i].c*head[p+i].c;
|
|
}
|
|
msd[0][i] = msd[0][i] + sum[0]/(double)a.atoms;
|
|
msd[1][i] = msd[1][i] + sum[1]/(double)a.atoms;
|
|
msd[2][i] = msd[2][i] + sum[2]/(double)a.atoms;
|
|
msd[3][i] = msd[3][i] + sum[3]/(double)a.atoms;
|
|
}
|
|
step_counter++;
|
|
}
|
|
|
|
if (step_counter == 0){
|
|
printf("--tau is too long, can not calculate MSD!!!\n");
|
|
exit(0);
|
|
}
|
|
|
|
for (k=0; k<4; k++)
|
|
for (i=0; i<TAU; i++) msd[k][i] = msd[k][i]/(double)step_counter;
|
|
OutputMSD(param, msd, &a, step_counter);
|
|
free(head);
|
|
for(i=0; i<param->steps; i++){
|
|
free(xx[i]);
|
|
free(yy[i]);
|
|
free(zz[i]);
|
|
}
|
|
free(xx);
|
|
free(yy);
|
|
free(zz);
|
|
for(i=0; i<4; i++) free(msd[i]);
|
|
free(msd);
|
|
}
|