git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@14366 f3b2605a-c512-4ea7-a41b-209d697bcdaa

This commit is contained in:
sjplimp 2015-12-15 15:59:01 +00:00
parent 75de12f26a
commit 5f802f86b5
10 changed files with 399 additions and 543 deletions

View File

@ -9,23 +9,20 @@ INC = $(LPKINC) $(TCINC) $(SPGINC)
LIB = $(LPKLIB) $(TCLIB) $(SPGLIB)
#
# cLapack library needed
LPKINC = -I/opt/clapack/3.2.1/include
LPKLIB = -L/opt/clapack/3.2.1/lib -lclapack -lblas -lf2c #-lm
LPKINC = -I/opt/libs/clapack/3.2.1/include
LPKLIB = -L/opt/libs/clapack/3.2.1/lib -lclapack -lblas -lf2c #-lm
#
# Tricubic library needed
TCINC = -I/opt/tricubic/1.0/include
TCLIB = -L/opt/tricubic/1.0/lib -ltricubic
TCINC = -I/opt/libs/tricubic/1.0/include
TCLIB = -L/opt/libs/tricubic/1.0/lib -ltricubic
#
# spglib 0.7.1, used to get the irreducible q-points
# spglib 1.8.2, used to get the irreducible q-points
# if UFLAG is not set, spglib won't be used.
UFLAG = -DUseSPG
SPGINC = -I/opt/spglib/0.7.1/include
SPGLIB = -L/opt/spglib/0.7.1/lib -lsymspg
# if spglib > 0.7.1 is used, please
# 1) modify file phonon.cpp, instruction can be found by searching 0.7.1
# 2) uncomment the following two lines
#SPGINC = -I/opt/spglib/1.1.2/include
#SPGLIB = -L/opt/spglib/1.1.2/lib -lsymspg
SPGINC = -I/opt/libs/spglib/1.8.2/include
SPGLIB = -L/opt/libs/spglib/1.8.2/lib -lsymspg
# if spglib other than version 1.8.2 is used, please
# modify file phonon.cpp, instruction can be found by searching 1.8.2
# Debug flags
#DEBUG = -g -DDEBUG
@ -39,7 +36,7 @@ SRC = $(wildcard *.cpp)
OBJ = $(SRC:.cpp=.o)
#====================================================================
all: ${EXE}
all: ver ${EXE}
${EXE}: $(OBJ)
$(LINK) $(OFLAGS) $(OBJ) $(LIB) -o $@
@ -51,7 +48,7 @@ tar:
rm -f ${ROOT}.tar; tar -czvf ${ROOT}.tar.gz *.cpp *.h Makefile README
ver:
@echo "#define VERSION `svn info|grep '^Revision'|cut -d: -f2`" > version.h
@echo "#define VERSION `git log|grep '^commit'|wc -l`" > version.h
#====================================================================
.f.o:

View File

@ -1,31 +1,48 @@
phana = post-processing program for the fix phonon command
#-------------------------------------------------------------------------------
phana
#
This program reads the binary file created by fix_phonon and helps to
analyse the phonon related information.
#-------------------------------------------------------------------------------
1. Dependencies
The clapack library is needed to solve the eigen problems,
which could be downloaded from:
http://www.netlib.org/clapack/
This program reads the binary file created by the fix phonon command
and helps to analyse the phonon related info.
The tricubic library is also needed to do tricubic interpolations,
which could be obtained from:
http://orca.princeton.edu/francois/software/tricubic/
or
http://1drv.ms/1J2WFYk
The clapack library is needed to solve the eigen problems, which could
be downloaded from: http://www.netlib.org/clapack/
The spglib is optionally needed, enabling one to evaluate the
phonon density of states or vibrational thermal properties
using only the irreducible q-points in the first Brillouin zone,
as well as to evaluate the phonon dispersion curvers with the
automatic mode. Currently, the 1.8.3 version of spglib is used.
It can be obtained from:
http://spglib.sourceforge.net/
The tricubic library is also needed to to tricubic interpolations,
which could be obtained from:
http://orca.princeton.edu/francois/software/tricubic/ or
http://code.google.com/p/fix-phonon/downloads/list
2. Compilation
To compile the code, one needs therefore to install the above
libraries and set the paths correctly in the Makefile.
Once this is done, by typing
make
will yield the executable "phana".
The spglib (version 0.7.1) is optionally needed, enabling one to
evaluate the phonon density of states or vibrational thermal
properties using only the irreducible q-points in the first Brillouin
zone.
3. Unit system
The units of the output frequencies by this code is THz for
LAMMPS units "real", "si", "metal", and "cgs"; in these cases,
the frequencies are $\nu$ instead of $\omega$.
To compile the code, one needs therefore to install the above
libraries and set the paths correctly in the Makefile.
4. Updates
For updates of phana, please check:
http://nes.sjtu.edu.cn/english/research/software.htm
or
https://github.com/lingtikong/phana.git
The units of the output frequencies by this code is THz for LAMMPS
units "real", "si", "metal", and "cgs"; in these cases, the
frequencies are $\nu$ instead of $\omega$.
One is encouraged to visit http://code.google.com/p/fix-phonon/ to
check out the latest revision on fix-phonon and the post-processing
code.
Author: Ling-Ti Kong (konglt at sjtu.edu.cn)
Feb 2013
5. Bug report
If any bug found, please drop a line to: konglt(at)sjtu.edu.cn
#-------------------------------------------------------------------------------
Author: Ling-Ti Kong, konglt(at)sjtu.edu.cn
Oct 2015

View File

@ -1,8 +1,7 @@
#include "dynmat.h"
#include "math.h"
#include "version.h"
#define MAXLINE 256
#include "global.h"
// to intialize the class
DynMat::DynMat(int narg, char **arg)
@ -14,6 +13,8 @@ DynMat::DynMat(int narg, char **arg)
DM_q = DM_all = NULL;
binfile = funit = dmfile = NULL;
attyp = NULL;
basis = NULL;
flag_reset_gamma = flag_skip = 0;
// analyze the command line options
@ -74,21 +75,21 @@ DynMat::DynMat(int narg, char **arg)
npt = nx*ny*nz;
// display info related to the read file
printf("\n"); for (int i=0; i<80; i++) printf("="); printf("\n");
printf("\n"); for (int i = 0; i < 80; ++i) printf("="); printf("\n");
printf("Dynamical matrix is read from file: %s\n", binfile);
printf("The system size in three dimension: %d x %d x %d\n", nx, ny, nz);
printf("Number of atoms per unit cell : %d\n", nucell);
printf("System dimension : %d\n", sysdim);
printf("Boltzmann constant in used units : %g\n", boltz);
for (int i=0; i<80; i++) printf("="); printf("\n");
if (sysdim<1||sysdim>3||nx<1||ny<1||nz<1||nucell<1){
for (int i = 0; i < 80; ++i) printf("="); printf("\n");
if (sysdim < 1||sysdim > 3||nx < 1||ny < 1||nz < 1||nucell < 1){
printf("Wrong values read from header of file: %s, please check the binary file!\n", binfile);
fclose(fp); exit(3);
}
funit = new char[4];
strcpy(funit, "THz");
if (boltz == 1.){eml2f = 1.; delete funit; funit=new char[22]; strcpy(funit,"sqrt(epsilon/(m.sigma^2))");}
if (boltz == 1.){eml2f = 1.; delete funit; funit = new char[27]; strcpy(funit,"sqrt(epsilon/(m.sigma^2))");}
else if (boltz == 0.0019872067) eml2f = 3.256576161;
else if (boltz == 8.617343e-5) eml2f = 15.63312493;
else if (boltz == 1.3806504e-23) eml2f = 1.;
@ -100,9 +101,9 @@ DynMat::DynMat(int narg, char **arg)
}
// now to allocate memory for DM
memory = new Memory;
DM_all = memory->create(DM_all, npt, fftdim2, "DynMat:DM_all");
DM_q = memory->create(DM_q, fftdim,fftdim,"DynMat:DM_q");
memory = new Memory();
memory->create(DM_all, npt, fftdim2, "DynMat:DM_all");
memory->create(DM_q, fftdim,fftdim,"DynMat:DM_q");
// read all dynamical matrix info into DM_all
if ( fread(DM_all[0], sizeof(doublecomplex), npt*fftdim2, fp) != size_t(npt*fftdim2)){
@ -112,50 +113,38 @@ DynMat::DynMat(int narg, char **arg)
}
// now try to read unit cell info from the binary file
flag_latinfo = 0;
basis = memory->create(basis,nucell,sysdim,"DynMat:basis");
attyp = memory->create(attyp,nucell, "DynMat:attyp");
M_inv_sqrt = memory->create(M_inv_sqrt, nucell, "DynMat:M_inv_sqrt");
int flag_mass_read = 0;
memory->create(basis, nucell, sysdim, "DynMat:basis");
memory->create(attyp, nucell, "DynMat:attyp");
memory->create(M_inv_sqrt, nucell, "DynMat:M_inv_sqrt");
if ( fread(&Tmeasure, sizeof(double), 1, fp) == 1) flag_latinfo |= 1;
if ( fread(&basevec[0], sizeof(double), 9, fp) == 9) flag_latinfo |= 2;
if ( fread(basis[0], sizeof(double), fftdim, fp) == fftdim) flag_latinfo |= 4;
if ( fread(&attyp[0], sizeof(int), nucell, fp) == nucell) flag_latinfo |= 8;
if ( fread(&M_inv_sqrt[0], sizeof(double), nucell, fp) == nucell) flag_mass_read = 1;
if ( fread(&Tmeasure, sizeof(double), 1, fp) != 1 ){printf("\nError while reading temperature from file: %s\n", binfile); fclose(fp); exit(3);}
if ( fread(&basevec[0], sizeof(double), 9, fp) != 9 ){printf("\nError while reading lattice info from file: %s\n", binfile); fclose(fp); exit(3);}
if ( fread(basis[0], sizeof(double), fftdim, fp) != fftdim){printf("\nError while reading basis info from file: %s\n", binfile); fclose(fp); exit(3);}
if ( fread(&attyp[0], sizeof(int), nucell, fp) != nucell){printf("\nError while reading atom types from file: %s\n", binfile); fclose(fp); exit(3);}
if ( fread(&M_inv_sqrt[0], sizeof(double), nucell, fp) != nucell){printf("\nError while reading atomic masses from file: %s\n", binfile); fclose(fp); exit(3);}
fclose(fp);
if ((flag_latinfo&15) == 15){
car2dir(flag_mass_read);
car2dir();
real2rec();
flag_latinfo = 1;
} else {
Tmeasure = 0.;
flag_latinfo = 0;
}
// initialize interpolation
interpolate = new Interpolate(nx,ny,nz,fftdim2,DM_all);
if (flag_reset_gamma) interpolate->reset_gamma();
if ( flag_mass_read ){ // M_inv_sqrt info read, the data stored are force constant matrix instead of dynamical matrix.
// Enforcing Austic Sum Rule
EnforceASR();
// get the dynamical matrix from force constant matrix: D = 1/M x Phi
for (int idq=0; idq< npt; idq++){
for (int idq = 0; idq < npt; ++idq){
int ndim =0;
for (int idim=0; idim<fftdim; idim++){
for (int jdim=0; jdim<fftdim; jdim++){
for (int idim = 0; idim < fftdim; ++idim)
for (int jdim = 0; jdim < fftdim; ++jdim){
double inv_mass = M_inv_sqrt[idim/sysdim]*M_inv_sqrt[jdim/sysdim];
DM_all[idq][ndim].r *= inv_mass;
DM_all[idq][ndim].i *= inv_mass;
ndim++;
}
}
}
}
// ask for the interpolation method
interpolate->set_method();
@ -191,7 +180,7 @@ void DynMat::writeDMq(double *q)
if (dmfile == NULL){
char str[MAXLINE], *ptr;
printf("\n");
while (1){
while ( 1 ){
printf("Please input the filename to output the DM at selected q: ");
fgets(str,MAXLINE,stdin);
ptr = strtok(str, " \r\t\n\f");
@ -208,8 +197,8 @@ void DynMat::writeDMq(double *q)
}
fprintf(fp,"# q = [%lg %lg %lg]\n", q[0], q[1], q[2]);
for (int i=0; i<fftdim; i++){
for (int j=0; j<fftdim; j++) fprintf(fp,"%lg %lg\t", DM_q[i][j].r, DM_q[i][j].i);
for (int i = 0; i < fftdim; ++i){
for (int j = 0; j < fftdim; ++j) fprintf(fp,"%lg %lg\t", DM_q[i][j].r, DM_q[i][j].i);
fprintf(fp,"\n");
}
fprintf(fp,"\n");
@ -225,9 +214,9 @@ void DynMat::writeDMq(double *q, const double qr, FILE *fp)
fprintf(fp, "%lg %lg %lg %lg ", q[0], q[1], q[2], qr);
for (int i=0; i<fftdim; i++){
for (int j=0; j<fftdim; j++) fprintf(fp,"%lg %lg\t", DM_q[i][j].r, DM_q[i][j].i);
}
for (int i = 0; i < fftdim; ++i)
for (int j = 0; j < fftdim; ++j) fprintf(fp,"%lg %lg\t", DM_q[i][j].r, DM_q[i][j].i);
fprintf(fp,"\n");
return;
}
@ -254,14 +243,14 @@ int DynMat::geteigen(double *egv, int flag)
liwork = 3 + 5*n;
lda = n;
work = memory->create(work, lwork, "geteigen:work");
rwork = memory->create(rwork, lrwork, "geteigen:rwork");
iwork = memory->create(iwork, liwork, "geteigen:iwork");
memory->create(work, lwork, "geteigen:work");
memory->create(rwork, lrwork, "geteigen:rwork");
memory->create(iwork, liwork, "geteigen:iwork");
zheevd_(&jobz, &uplo, &n, DM_q[0], &lda, w, work, &lwork, rwork, &lrwork, iwork, &liwork, &info);
// to get w instead of w^2; and convert w into v (THz hopefully)
for (int i=0; i<n; i++){
for (int i = 0; i < n; ++i){
if (w[i]>= 0.) w[i] = sqrt(w[i]);
else w[i] = -sqrt(-w[i]);
@ -298,24 +287,17 @@ return;
/* ----------------------------------------------------------------------------
* private method to convert the cartisan coordinate of basis into fractional
* ---------------------------------------------------------------------------- */
void DynMat::car2dir(int flag)
void DynMat::car2dir()
{
if (!flag){ // in newer version, this is done in fix-phonon
for (int i=0; i<3; i++){
basevec[i] /= double(nx);
basevec[i+3] /= double(ny);
basevec[i+6] /= double(nz);
}
}
double mat[9];
for (int idim=0; idim<9; idim++) mat[idim] = basevec[idim];
for (int idim = 0; idim < 9; ++idim) mat[idim] = basevec[idim];
GaussJordan(3, mat);
for (int i=0; i<nucell; i++){
for (int i = 0; i < nucell; ++i){
double x[3];
x[0] = x[1] = x[2] = 0.;
for (int idim=0; idim<sysdim; idim++) x[idim] = basis[i][idim];
for (int idim=0; idim<sysdim; idim++)
for (int idim = 0; idim < sysdim; idim++) x[idim] = basis[i][idim];
for (int idim = 0; idim < sysdim; idim++)
basis[i][idim] = x[0]*mat[idim] + x[1]*mat[3+idim] + x[2]*mat[6+idim];
}
@ -330,7 +312,7 @@ void DynMat::EnforceASR()
char str[MAXLINE];
int nasr = 20;
if (nucell <= 1) nasr = 1;
printf("\n"); for (int i=0; i<80; i++) printf("=");
printf("\n"); for (int i = 0; i < 80; ++i) printf("=");
// compute and display eigenvalues of Phi at gamma before ASR
if (nucell > 100){
@ -339,11 +321,11 @@ void DynMat::EnforceASR()
}
double egvs[fftdim];
for (int i=0; i<fftdim; i++)
for (int j=0; j<fftdim; j++) DM_q[i][j] = DM_all[0][i*fftdim+j];
for (int i = 0; i < fftdim; ++i)
for (int j = 0; j < fftdim; ++j) DM_q[i][j] = DM_all[0][i*fftdim+j];
geteigen(egvs, 0);
printf("\nEigenvalues of Phi at gamma before enforcing ASR:\n");
for (int i=0; i<fftdim; i++){
for (int i = 0; i < fftdim; ++i){
printf("%lg ", egvs[i]);
if (i%10 == 9) printf("\n");
if (i == 99){ printf("...... (%d more skipped)\n", fftdim-100); break;}
@ -355,20 +337,23 @@ void DynMat::EnforceASR()
fgets(str,MAXLINE,stdin);
char *ptr = strtok(str," \t\n\r\f");
if (ptr) nasr = atoi(ptr);
if (nasr < 1){return; for (int i=0; i<80; i++) printf("="); printf("\n");}
if (nasr < 1){
for (int i=0; i<80; i++) printf("="); printf("\n");
return;
}
for (int iit=0; iit<nasr; iit++){
for (int iit = 0; iit < nasr; ++iit){
// simple ASR; the resultant matrix might not be symmetric
for (int a=0; a<sysdim; a++)
for (int b=0; b<sysdim; b++){
for (int k=0; k<nucell; k++){
for (int a = 0; a < sysdim; ++a)
for (int b = 0; b < sysdim; ++b){
for (int k = 0; k < nucell; ++k){
double sum = 0.;
for (int kp=0; kp<nucell; kp++){
for (int kp = 0; kp < nucell; ++kp){
int idx = (k*sysdim+a)*fftdim+kp*sysdim+b;
sum += DM_all[0][idx].r;
}
sum /= double(nucell);
for (int kp=0; kp<nucell; kp++){
for (int kp = 0; kp < nucell; ++kp){
int idx = (k*sysdim+a)*fftdim+kp*sysdim+b;
DM_all[0][idx].r -= sum;
}
@ -376,11 +361,11 @@ void DynMat::EnforceASR()
}
// symmetrize
for (int k=0; k<nucell; k++)
for (int kp=k; kp<nucell; kp++){
for (int k = 0; k < nucell; ++k)
for (int kp = k; kp < nucell; ++kp){
double csum = 0.;
for (int a=0; a<sysdim; a++)
for (int b=0; b<sysdim; b++){
for (int a = 0; a < sysdim; ++a)
for (int b = 0; b < sysdim; ++b){
int idx = (k*sysdim+a)*fftdim+kp*sysdim+b;
int jdx = (kp*sysdim+b)*fftdim+k*sysdim+a;
csum = (DM_all[0][idx].r + DM_all[0][jdx].r )*0.5;
@ -390,16 +375,16 @@ void DynMat::EnforceASR()
}
// symmetric ASR
for (int a=0; a<sysdim; a++)
for (int b=0; b<sysdim; b++){
for (int k=0; k<nucell; k++){
for (int a = 0; a < sysdim; ++a)
for (int b = 0; b < sysdim; ++b){
for (int k = 0; k < nucell; ++k){
double sum = 0.;
for (int kp=0; kp<nucell; kp++){
for (int kp = 0; kp < nucell; ++kp){
int idx = (k*sysdim+a)*fftdim+kp*sysdim+b;
sum += DM_all[0][idx].r;
}
sum /= double(nucell-k);
for (int kp=k; kp<nucell; kp++){
for (int kp = k; kp < nucell; ++kp){
int idx = (k*sysdim+a)*fftdim+kp*sysdim+b;
int jdx = (kp*sysdim+b)*fftdim+k*sysdim+a;
DM_all[0][idx].r -= sum;
@ -409,16 +394,17 @@ void DynMat::EnforceASR()
}
// compute and display eigenvalues of Phi at gamma after ASR
for (int i=0; i<fftdim; i++)
for (int j=0; j<fftdim; j++) DM_q[i][j] = DM_all[0][i*fftdim+j];
for (int i = 0; i < fftdim; ++i)
for (int j = 0; j < fftdim; ++j) DM_q[i][j] = DM_all[0][i*fftdim+j];
geteigen(egvs, 0);
printf("Eigenvalues of Phi at gamma after enforcing ASR:\n");
for (int i=0; i<fftdim; i++){
for (int i = 0; i < fftdim; ++i){
printf("%lg ", egvs[i]);
if (i%10 == 9) printf("\n");
if (i == 99){ printf("...... (%d more skiped)", fftdim-100); break;}
}
printf("\n"); for (int i=0; i<80; i++) printf("="); printf("\n\n");
printf("\n");
for (int i = 0; i < 80; ++i) printf("="); printf("\n\n");
return;
}
@ -441,23 +427,23 @@ void DynMat::real2rec()
ibasevec[8] = basevec[0]*basevec[4] - basevec[1]*basevec[3];
double vol = 0.;
for (int i=0; i<sysdim; i++) vol += ibasevec[i] * basevec[i];
for (int i = 0; i < sysdim; ++i) vol += ibasevec[i] * basevec[i];
vol = 8.*atan(1.)/vol;
for (int i=0; i<9; i++) ibasevec[i] *= vol;
for (int i = 0; i < 9; ++i) ibasevec[i] *= vol;
printf("\n"); for (int i=0; i<80; i++) printf("=");
printf("\n"); for (int i = 0; i < 80; ++i) printf("=");
printf("\nBasis vectors of the unit cell in real space:");
for (int i=0; i<sysdim; i++){
for (int i = 0; i < sysdim; ++i){
printf("\n A%d: ", i+1);
for (int j=0; j<sysdim; j++) printf("%8.4f ", basevec[i*3+j]);
for (int j = 0; j < sysdim; ++j) printf("%8.4f ", basevec[i*3+j]);
}
printf("\nBasis vectors of the corresponding reciprocal cell:");
for (int i=0; i<sysdim; i++){
for (int i = 0; i < sysdim; ++i){
printf("\n B%d: ", i+1);
for (int j=0; j<sysdim; j++) printf("%8.4f ", ibasevec[i*3+j]);
for (int j = 0; j < sysdim; ++j) printf("%8.4f ", ibasevec[i*3+j]);
}
printf("\n"); for (int i=0; i<80; i++) printf("="); printf("\n");
printf("\n"); for (int i = 0; i < 80; ++i) printf("="); printf("\n");
return;
}
@ -479,21 +465,21 @@ void DynMat::GaussJordan(int n, double *Mat)
indxr = new int[n];
ipiv = new int[n];
for (i=0; i<n; i++) ipiv[i] = 0;
for (i=0; i<n; i++){
for (i = 0; i < n; ++i) ipiv[i] = 0;
for (i = 0; i < n; ++i){
big = 0.;
for (j=0; j<n; j++){
for (j = 0; j < n; ++j){
if (ipiv[j] != 1){
for (k=0; k<n; k++){
for (k = 0; k < n; ++k){
if (ipiv[k] == 0){
idr = j*n+k;
idr = j * n + k;
nmjk = abs(Mat[idr]);
if (nmjk >= big){
big = nmjk;
irow = j;
icol = k;
}
}else if (ipiv[k]>1){
} else if (ipiv[k] > 1){
printf("DynMat: Singular matrix in double GaussJordan!\n"); exit(1);
}
}
@ -501,7 +487,7 @@ void DynMat::GaussJordan(int n, double *Mat)
}
ipiv[icol] += 1;
if (irow != icol){
for (l=0; l<n; l++){
for (l = 0; l < n; ++l){
idr = irow*n+l;
idc = icol*n+l;
dum = Mat[idr];
@ -511,7 +497,7 @@ void DynMat::GaussJordan(int n, double *Mat)
}
indxr[i] = irow;
indxc[i] = icol;
idr = icol*n+icol;
idr = icol * n + icol;
if (Mat[idr] == 0.){
printf("DynMat: Singular matrix in double GaussJordan!");
exit(1);
@ -520,24 +506,24 @@ void DynMat::GaussJordan(int n, double *Mat)
pivinv = 1./ Mat[idr];
Mat[idr] = 1.;
idr = icol*n;
for (l=0; l<n; l++) Mat[idr+l] *= pivinv;
for (ll=0; ll<n; ll++){
for (l = 0; l < n; ++l) Mat[idr+l] *= pivinv;
for (ll = 0; ll < n; ++ll){
if (ll != icol){
idc = ll*n+icol;
idc = ll * n + icol;
dum = Mat[idc];
Mat[idc] = 0.;
idc -= icol;
for (l=0; l<n; l++) Mat[idc+l] -= Mat[idr+l]*dum;
for (l = 0; l < n; ++l) Mat[idc+l] -= Mat[idr+l]*dum;
}
}
}
for (l=n-1; l>=0; l--){
for (l = n-1; l >= 0; --l){
int rl = indxr[l];
int cl = indxc[l];
if (rl != cl){
for (k=0; k<n; k++){
idr = k*n+rl;
idc = k*n+cl;
for (k = 0; k < n; ++k){
idr = k * n + rl;
idc = k * n + cl;
dum = Mat[idr];
Mat[idr] = Mat[idc];
Mat[idc] = dum;
@ -547,6 +533,7 @@ void DynMat::GaussJordan(int n, double *Mat)
delete []indxr;
delete []indxc;
delete []ipiv;
return;
}
@ -595,7 +582,7 @@ void DynMat::ShowVersion()
printf(" ( _ \\( )_( ) /__\\ ( \\( ) /__\\ \n");
printf(" )___/ ) _ ( /(__)\\ ) ( /(__)\\ \n");
printf(" (__) (_) (_)(__)(__)(_)\\_)(__)(__)\n");
printf("\nPHonon ANAlyzer for Fix-Phonon, version 2.%d, compiled on %s.\n", VERSION, __DATE__);
printf("\nPHonon ANAlyzer for Fix-Phonon, version 2.%02d, compiled on %s.\n", VERSION, __DATE__);
return;
}

View File

@ -56,7 +56,7 @@ private:
doublecomplex **DM_all;
void car2dir(int); // to convert basis from cartisian coordinate into factional.
void car2dir(); // to convert basis from cartisian coordinate into factional.
void real2rec();
void GaussJordan(int, double *);

View File

@ -4,8 +4,7 @@
#include <math.h>
#include "green.h"
#include <complex>
#define MAXLINE 256
#include "global.h"
/*******************************************************************************
* The class of Green is designed to evaluate the LDOS via the Green's Function
@ -45,7 +44,7 @@ Green::Green(const int ntm, const int sdim, const int niter, const double min, c
H = Hessian; iatom = itm;
ldos = lpdos;
memory = new Memory;
memory = new Memory();
if (natom < 1 || iatom < 0 || iatom >= natom){
printf("\nError: Wrong number of total atoms or wrong index of interested atom!\n");
return;
@ -58,9 +57,9 @@ Green::Green(const int ntm, const int sdim, const int niter, const double min, c
// initialize variables and allocate local memories
dw = (wmax - wmin)/double(nw-1);
alpha = memory->create(alpha, sysdim,nit, "Green_Green:alpha");
beta = memory->create(beta, sysdim,nit+1,"Green_Green:beta");
//ldos = memory->create(ldos, nw,sysdim, "Green_Green:ldos");
memory->create(alpha, sysdim,nit, "Green_Green:alpha");
memory->create(beta, sysdim,nit+1,"Green_Green:beta");
//memory->create(ldos, nw,sysdim, "Green_Green:ldos");
// use Lanczos algorithm to diagonalize the Hessian
Lanczos();
@ -100,35 +99,35 @@ void Green::Lanczos()
int ipos = iatom*sysdim;
// Loop over dimension
for (int idim=0; idim<sysdim; idim++){
for (int idim = 0; idim < sysdim; ++idim){
beta[idim][0] = 0.;
for (int i=0; i<ndim; i++){vp[i] = v[i] = 0.;}
for (int i = 0; i < ndim; ++i) vp[i] = v[i] = 0.;
v[ipos+idim] = 1.;
// Loop on fraction levels
for (int i=0; i<nit; i++){
for (int i = 0; i < nit; ++i){
double sum_a = 0.;
for (int j=0; j<ndim; j++){
for (int j = 0; j < ndim; ++j){
double sumHv = 0.;
for (int k=0; k<ndim; k++) sumHv += H[j][k]*v[k];
for (int k = 0; k < ndim; ++k) sumHv += H[j][k]*v[k];
w[j] = sumHv - beta[idim][i]*vp[j];
sum_a += w[j]*v[j];
}
alpha[idim][i] = sum_a;
for (int k=0; k<ndim; k++) w[k] -= alpha[idim][i]*v[k];
for (int k = 0; k < ndim; ++k) w[k] -= alpha[idim][i]*v[k];
double gamma = 0.;
for (int k=0; k<ndim; k++) gamma += w[k]*v[k];
for (int k=0; k<ndim; k++) w[k] -= gamma*v[k];
for (int k = 0; k < ndim; ++k) gamma += w[k]*v[k];
for (int k = 0; k < ndim; ++k) w[k] -= gamma*v[k];
double sum_b = 0.;
for (int k=0; k<ndim; k++) sum_b += w[k]*w[k];
for (int k = 0; k < ndim; ++k) sum_b += w[k]*w[k];
beta[idim][i+1] = sqrt(sum_b);
ptr = vp; vp = v; v = ptr;
double tmp = 1./beta[idim][i+1];
for (int k=0; k<ndim; k++) v[k] = w[k]*tmp;
for (int k = 0; k < ndim; ++k) v[k] = w[k] * tmp;
}
}
@ -154,10 +153,10 @@ void Green::Recursion()
xmax = new double [sysdim];
int nave = nit/4;
for (int idim=0; idim<sysdim; idim++){
for (int idim = 0; idim < sysdim; ++idim){
alpha_inf[idim] = beta_inf[idim] = 0.;
for (int i= nit-nave; i<nit; i++){
for (int i = nit-nave; i < nit; ++i){
alpha_inf[idim] += alpha[idim][i];
beta_inf[idim] += beta[idim][i+1];
}
@ -173,11 +172,11 @@ void Green::Recursion()
double sr, si;
double w = wmin;
for (int i=0; i<nw; i++){
for (int i = 0; i < nw; ++i){
double a = w*w, ax, bx;
Z = std::complex<double>(w*w, epson);
for (int idim=0; idim<sysdim; idim++){
for (int idim = 0; idim < sysdim; ++idim){
double two_b = 2.*beta_inf[idim]*beta_inf[idim];
double rtwob = 1./two_b;
@ -201,7 +200,7 @@ void Green::Recursion()
si = epson * rtwob + bx;
rec_x = std::complex<double> (sr, si);
for (int j=0; j<nit; j++){
for (int j = 0; j < nit; ++j){
rec_x_inv = Z - alpha[idim][nit-j-1] - beta[idim][nit-j]*beta[idim][nit-j]*rec_x;
rec_x = 1./rec_x_inv;
}
@ -229,13 +228,13 @@ void Green::recursion()
double w = wmin;
for (int i=0; i<nw; i++){
for (int i = 0; i < nw; ++i){
Z = std::complex<double>(w*w, epson);
for (int idim=0; idim<sysdim; idim++){
for (int idim = 0; idim < sysdim; ++idim){
rec_x = std::complex<double>(0.,0.);
for (int j=0; j<nit; j++){
for (int j = 0; j < nit; ++j){
rec_x_inv = Z - alpha[idim][nit-j-1] - beta[idim][nit-j]*beta[idim][nit-j]*rec_x;
rec_x = 1./rec_x_inv;
}

View File

@ -1,9 +1,6 @@
#include "interpolate.h"
#include "math.h"
#define MAXLINE 256
#define MIN(a,b) ((a)>(b)?(b):(a))
#define MAX(a,b) ((a)>(b)?(a):(b))
#include "global.h"
/* ----------------------------------------------------------------------------
* Constructor used to get info from caller, and prepare other necessary data
@ -15,7 +12,7 @@ Interpolate::Interpolate(int nx, int ny, int nz, int ndm, doublecomplex **DM)
Nz = nz;
Npt = Nx*Ny*Nz;
ndim = ndm;
memory = new Memory;
memory = new Memory();
which = UseGamma = 0;
@ -33,13 +30,13 @@ void Interpolate::tricubic_init()
{
// prepare necessary data for tricubic
if (flag_allocated_dfs == 0){
Dfdx = memory->create(Dfdx, Npt, ndim, "Interpolate_Interpolate:Dfdx");
Dfdy = memory->create(Dfdy, Npt, ndim, "Interpolate_Interpolate:Dfdy");
Dfdz = memory->create(Dfdz, Npt, ndim, "Interpolate_Interpolate:Dfdz");
D2fdxdy = memory->create(D2fdxdy, Npt, ndim, "Interpolate_Interpolate:D2fdxdy");
D2fdxdz = memory->create(D2fdxdz, Npt, ndim, "Interpolate_Interpolate:D2fdxdz");
D2fdydz = memory->create(D2fdydz, Npt, ndim, "Interpolate_Interpolate:D2fdydz");
D3fdxdydz = memory->create(D3fdxdydz, Npt, ndim, "Interpolate_Interpolate:D2fdxdydz");
memory->create(Dfdx, Npt, ndim, "Interpolate_Interpolate:Dfdx");
memory->create(Dfdy, Npt, ndim, "Interpolate_Interpolate:Dfdy");
memory->create(Dfdz, Npt, ndim, "Interpolate_Interpolate:Dfdz");
memory->create(D2fdxdy, Npt, ndim, "Interpolate_Interpolate:D2fdxdy");
memory->create(D2fdxdz, Npt, ndim, "Interpolate_Interpolate:D2fdxdz");
memory->create(D2fdydz, Npt, ndim, "Interpolate_Interpolate:D2fdydz");
memory->create(D3fdxdydz, Npt, ndim, "Interpolate_Interpolate:D2fdxdydz");
flag_allocated_dfs = 1;
}
@ -47,9 +44,9 @@ void Interpolate::tricubic_init()
// get the derivatives
int n=0;
const double half = 0.5, one4 = 0.25, one8 = 0.125;
for (int ii=0; ii<Nx; ii++)
for (int jj=0; jj<Ny; jj++)
for (int kk=0; kk<Nz; kk++){
for (int ii = 0; ii < Nx; ++ii)
for (int jj = 0; jj < Ny; ++jj)
for (int kk = 0; kk < Nz; ++kk){
int ip = (ii+1)%Nx, jp = (jj+1)%Ny, kp = (kk+1)%Nz;
int im = (ii-1+Nx)%Nx, jm = (jj-1+Ny)%Ny, km = (kk-1+Nz)%Nz;
@ -127,8 +124,8 @@ void Interpolate::tricubic(double *qin, doublecomplex *DMq)
{
// qin should be in unit of 2*pi/L
double q[3];
for (int i=0; i<3; i++) q[i] = qin[i];
for (int i=0; i<3; i++){
for (int i = 0; i < 3; ++i) q[i] = qin[i];
for (int i = 0; i < 3; ++i){
while (q[i] < 0.) q[i] += 1.;
while (q[i] >= 1.) q[i] -= 1.;
}
@ -150,8 +147,8 @@ void Interpolate::tricubic(double *qin, doublecomplex *DMq)
vidx[7] = (ixp*Ny+iyp)*Nz+izp;
for (int i=0; i<8; i++) if (vidx[i] == 0) UseGamma = 1;
for (int idim=0; idim<ndim; idim++){
for (int i=0; i<8; i++){
for (int idim = 0; idim < ndim; ++idim){
for (int i = 0; i < 8; ++i){
f[i] = data[vidx[i]][idim].r;
dfdx[i] = Dfdx[vidx[i]][idim].r;
dfdy[i] = Dfdy[vidx[i]][idim].r;
@ -164,7 +161,7 @@ void Interpolate::tricubic(double *qin, doublecomplex *DMq)
tricubic_get_coeff(&a[0],&f[0],&dfdx[0],&dfdy[0],&dfdz[0],&d2fdxdy[0],&d2fdxdz[0],&d2fdydz[0],&d3fdxdydz[0]);
DMq[idim].r = tricubic_eval(&a[0],x,y,z);
for (int i=0; i<8; i++){
for (int i = 0; i < 8; ++i){
f[i] = data[vidx[i]][idim].i;
dfdx[i] = Dfdx[vidx[i]][idim].i;
dfdy[i] = Dfdy[vidx[i]][idim].i;
@ -177,6 +174,8 @@ void Interpolate::tricubic(double *qin, doublecomplex *DMq)
tricubic_get_coeff(&a[0],&f[0],&dfdx[0],&dfdy[0],&dfdz[0],&d2fdxdy[0],&d2fdxdz[0],&d2fdydz[0],&d3fdxdydz[0]);
DMq[idim].i = tricubic_eval(&a[0],x,y,z);
}
return;
}
/* ----------------------------------------------------------------------------
@ -188,8 +187,8 @@ void Interpolate::trilinear(double *qin, doublecomplex *DMq)
{
// rescale q[i] into [0 1)
double q[3];
for (int i=0; i<3; i++) q[i] = qin[i];
for (int i=0; i<3; i++){
for (int i = 0; i < 3; ++i) q[i] = qin[i];
for (int i = 0; i < 3; ++i){
while (q[i] < 0.) q[i] += 1.;
while (q[i] >= 1.) q[i] -= 1.;
}
@ -220,7 +219,7 @@ void Interpolate::trilinear(double *qin, doublecomplex *DMq)
vidx[5] = ((ix*Ny)+iyp)*Nz + izp;
vidx[6] = ((ixp*Ny)+iyp)*Nz + iz;
vidx[7] = ((ixp*Ny)+iyp)*Nz + izp;
for (int i=0; i<8; i++) if (vidx[i] == 0) UseGamma = 1;
for (int i = 0; i < 8; ++i) if (vidx[i] == 0) UseGamma = 1;
double fac[8];
fac[0] = (1.-x)*(1.-y)*(1.-z);
@ -233,10 +232,10 @@ void Interpolate::trilinear(double *qin, doublecomplex *DMq)
fac[7] = x*y*z;
// now to do the interpolation
for (int idim=0; idim<ndim; idim++){
for (int idim = 0; idim < ndim; ++idim){
DMq[idim].r = 0.;
DMq[idim].i = 0.;
for (int i=0; i<8; i++){
for (int i = 0; i < 8; ++i){
DMq[idim].r += data[vidx[i]][idim].r*fac[i];
DMq[idim].i += data[vidx[i]][idim].i*fac[i];
}
@ -268,7 +267,7 @@ void Interpolate::set_method()
printf("\n");for(int i=0; i<80; i++) printf("=");
printf("\nWhich interpolation method would you like to use?\n");
printf(" 1. Tricubic;\n 2. Trilinear;\n");
printf("Your choice[1]: ");
printf("Your choice [1]: ");
fgets(str,MAXLINE,stdin);
char *ptr = strtok(str," \t\n\r\f");
if (ptr) im = atoi(ptr);

View File

@ -3,6 +3,7 @@
#include "phonon.h"
#include "green.h"
#include "timer.h"
#include "global.h"
#ifdef UseSPG
extern "C"{
@ -10,10 +11,6 @@ extern "C"{
}
#endif
#define MAXLINE 256
#define MIN(a,b) ((a)>(b)?(b):(a))
#define MAX(a,b) ((a)>(b)?(a):(b))
/* ----------------------------------------------------------------------------
* Class Phonon is the main driver to calculate phonon DOS, phonon
* dispersion curve and some other things.
@ -42,7 +39,10 @@ Phonon::Phonon(DynMat *dm)
// display the menu
char str[MAXLINE];
while ( 1 ){
printf("\n"); for (int i=0; i<37;i++) printf("="); printf(" Menu "); for (int i=0; i<37;i++) printf("="); printf("\n");
printf("\n");
for (int i = 0; i < 37; ++i) printf("=");
printf(" Menu ");
for (int i = 0; i < 37; ++i) printf("="); printf("\n");
printf(" 1. Phonon DOS evaluation;\n");
printf(" 2. Phonon dispersion curves;\n");
printf(" 3. Dynamical matrix at arbitrary q;\n");
@ -52,14 +52,15 @@ Phonon::Phonon(DynMat *dm)
printf(" 7. Local phonon DOS from eigenvectors;\n");
printf(" 8. Local phonon DOS by RSGF method;\n");
printf(" 9. Freqs and eigenvectors at arbitrary q;\n");
printf(" 10. Show information related to the unit cell;\n");
printf(" -1. Reset the interpolation method;\n");
printf(" 0. Exit.\n");
// read user choice
int job = 0;
printf("Your choice[0]: ");
printf("Your choice [0]: ");
if (count_words(fgets(str,MAXLINE,stdin)) > 0) job = atoi(strtok(str," \t\n\r\f"));
printf("\nYour selection: %d\n", job);
for (int i=0; i<80;i++) printf("=");printf("\n\n");
for (int i = 0; i < 80; ++i) printf("=");printf("\n\n");
// now to do the job according to user's choice
if (job == 1) pdos();
@ -71,6 +72,7 @@ Phonon::Phonon(DynMat *dm)
else if (job == 7) ldos_egv();
else if (job == 8) ldos_rsgf();
else if (job == 9) vecanyq();
else if (job ==10) ShowCell();
else if (job ==-1) dynmat->reset_interp_method();
else break;
}
@ -113,12 +115,11 @@ void Phonon::pdos()
char str[MAXLINE];
fmin = fmax = eigs[0][0];
for (int iq=0; iq<nq; iq++){
for (int j=0; j<ndim; j++){
for (int iq = 0; iq < nq; ++iq)
for (int j = 0; j < ndim; ++j){
fmin = MIN(fmin, eigs[iq][j]);
fmax = MAX(fmax, eigs[iq][j]);
}
}
// Now to ask for the output frequency range
printf("\nThe frequency range of all q-points are: [%g %g]\n", fmin, fmax);
@ -139,14 +140,14 @@ void Phonon::pdos()
df = (fmax-fmin)/double(ndos-1);
rdf = 1./df;
memory->destroy(dos);
dos = memory->create(dos, ndos, "pdos:dos");
memory->create(dos, ndos, "pdos:dos");
for (int i=0; i<ndos; i++) dos[i] = 0.;
// now to calculate the DOS
double offset = fmin-0.5*df;
for (int iq=0; iq<nq; iq++){
for (int iq = 0; iq < nq; ++iq){
if (wt[iq] > 0.){
for (int j=0; j<ndim; j++){
for (int j = 0; j < ndim; ++j){
int idx = int((eigs[iq][j]-offset)*rdf);
if (idx>=0 && idx<ndos) dos[idx] += wt[iq];
}
@ -220,17 +221,20 @@ void Phonon::writeLDOS()
printf("The phonon LDOSs will be written to file(s) : pldos_?.dat\n\n");
const double one3 = 1./double(sysdim);
char str[MAXLINE];
for (int ilocal=0; ilocal<nlocal; ilocal++){
for (int ilocal = 0; ilocal < nlocal; ++ilocal){
sprintf(str,"pldos_%d.dat", locals[ilocal]);
char *fname = strtok(str," \t\n\r\f");
FILE *fp = fopen(fname, "w"); fname = NULL;
fprintf(fp,"#freq xDOS yDOS zDOS total\n");
double freq = fmin;
for (int i=0; i<ndos; i++){
for (int i = 0; i < ndos; ++i){
fprintf(fp,"%lg", freq);
double total = 0.;
for (int idim=0; idim<sysdim; idim++) {fprintf(fp," %lg",ldos[ilocal][i][idim]); total += ldos[ilocal][i][idim];}
for (int idim = 0; idim < sysdim; ++idim){
fprintf(fp," %lg",ldos[ilocal][i][idim]);
total += ldos[ilocal][i][idim];
}
fprintf(fp," %lg\n", total*one3);
freq += df;
}
@ -250,21 +254,21 @@ void Phonon::ldos_rsgf()
const double tpi = 8.*atan(1.);
double **Hessian, scale;
scale = dynmat->eml2f*tpi; scale *= scale;
Hessian = memory->create(Hessian, ndim, ndim, "phonon_ldos:Hessian");
memory->create(Hessian, ndim, ndim, "phonon_ldos:Hessian");
double q0[3];
q0[0] = q0[1] = q0[2] = 0.;
dynmat->getDMq(q0);
for (int i=0; i<ndim; i++)
for (int j=0; j<ndim; j++) Hessian[i][j] = dynmat->DM_q[i][j].r*scale;
for (int i = 0; i < ndim; ++i)
for (int j = 0; j < ndim; ++j) Hessian[i][j] = dynmat->DM_q[i][j].r*scale;
if (ndim < 300){
double *egvs = new double [ndim];
dynmat->geteigen(egvs, 0);
fmin = fmax = egvs[0];
for (int i=1; i<ndim; i++){fmin = MIN(fmin, egvs[i]); fmax = MAX(fmax, egvs[i]);}
for (int i = 1; i < ndim; ++i){fmin = MIN(fmin, egvs[i]); fmax = MAX(fmax, egvs[i]);}
delete []egvs;
} else {
fmin = 0.; fmax = 20.;
@ -284,24 +288,29 @@ void Phonon::ldos_rsgf()
if (nr < 1){
istr = iend = ik;
iinc = 1;
} else if (nr == 1) {
char *ptr = strtok(str," \t\n\r\f");
if (strcmp(ptr,"q") == 0) break;
ik = atoi(ptr);
if (ik < 0 || ik >= dynmat->nucell) break;
ik = MAX(0, MIN(ik, dynmat->nucell-1));
istr = iend = ik;
iinc = 1;
} else if (nr == 2) {
istr = atoi(strtok(str," \t\n\r\f"));
iend = atoi(strtok(NULL," \t\n\r\f"));
iinc = 1;
if (istr < 0||iend >= dynmat->nucell||istr > iend) break;
istr = MAX(0, MIN(istr, dynmat->nucell-1));
iend = MAX(0, MIN(iend, dynmat->nucell-1));
} else if (nr >= 3) {
istr = atoi(strtok(str," \t\n\r\f"));
iend = atoi(strtok(NULL," \t\n\r\f"));
iinc = atoi(strtok(NULL," \t\n\r\f"));
if (istr<0 || iend >= dynmat->nucell || istr > iend || iinc<1) break;
istr = MAX(0, MIN(istr, dynmat->nucell-1));
iend = MAX(0, MIN(iend, dynmat->nucell-1));
}
printf("Please input the frequency range to evaluate LDOS [%g %g]: ", fmin, fmax);
@ -332,7 +341,7 @@ void Phonon::ldos_rsgf()
ldos = memory->create(ldos,nlocal,ndos,dynmat->sysdim,"ldos_rsgf:ldos");
memory->destroy(locals);
locals = memory->create(locals, nlocal, "ldos_rsgf:locals");
memory->create(locals, nlocal, "ldos_rsgf:locals");
df = (fmax-fmin)/double(ndos-1);
rdf = 1./df;
@ -366,104 +375,6 @@ void Phonon::ldos_rsgf()
return;
}
/*------------------------------------------------------------------------------
* Private method to evaluate the phonon dispersion curves
*----------------------------------------------------------------------------*/
void Phonon::pdisp()
{
// ask the output file name and write the header.
char str[MAXLINE];
printf("Please input the filename to output the dispersion data [pdisp.dat]:");
if (count_words(fgets(str,MAXLINE,stdin)) < 1) strcpy(str, "pdisp.dat");
char *ptr = strtok(str," \t\n\r\f");
char *fname = new char[strlen(ptr)+1];
strcpy(fname,ptr);
FILE *fp = fopen(fname, "w");
fprintf(fp,"# q qr freq\n");
fprintf(fp,"# 2pi/L 2pi/L %s\n", dynmat->funit);
// to store the nodes of the dispersion curve
std::vector<double> nodes; nodes.clear();
// now the calculate the dispersion curve
double qstr[3], qend[3], q[3], qinc[3], qr=0., dq;
int nq = MAX(MAX(dynmat->nx,dynmat->ny),dynmat->nz)/2+1;
qend[0] = qend[1] = qend[2] = 0.;
double *egvs = new double [ndim];
while (1){
for (int i=0; i<3; i++) qstr[i] = qend[i];
int quit = 0;
printf("\nPlease input the start q-point in unit of B1->B3, q to exit [%g %g %g]: ", qstr[0], qstr[1], qstr[2]);
int n = count_words(fgets(str,MAXLINE,stdin));
ptr = strtok(str," \t\n\r\f");
if ((n == 1) && (strcmp(ptr,"q") == 0)) break;
else if (n >= 3){
qstr[0] = atof(ptr);
qstr[1] = atof(strtok(NULL," \t\n\r\f"));
qstr[2] = atof(strtok(NULL," \t\n\r\f"));
}
do printf("Please input the end q-point in unit of B1->B3: ");
while (count_words(fgets(str,MAXLINE,stdin)) < 3);
qend[0] = atof(strtok(str," \t\n\r\f"));
qend[1] = atof(strtok(NULL," \t\n\r\f"));
qend[2] = atof(strtok(NULL," \t\n\r\f"));
printf("Please input the # of points along the line [%d]: ", nq);
if (count_words(fgets(str,MAXLINE,stdin)) > 0) nq = atoi(strtok(str," \t\n\r\f"));
nq = MAX(nq,2);
for (int i=0; i<3; i++) qinc[i] = (qend[i]-qstr[i])/double(nq-1);
dq = sqrt(qinc[0]*qinc[0]+qinc[1]*qinc[1]+qinc[2]*qinc[2]);
nodes.push_back(qr);
for (int i=0; i<3; i++) q[i] = qstr[i];
for (int ii=0; ii<nq; ii++){
double wii = 1.;
dynmat->getDMq(q, &wii);
if (wii > 0.){
dynmat->geteigen(egvs, 0);
fprintf(fp,"%lg %lg %lg %lg ", q[0], q[1], q[2], qr);
for (int i=0; i<ndim; i++) fprintf(fp," %lg", egvs[i]);
}
fprintf(fp,"\n");
for (int i=0; i<3; i++) q[i] += qinc[i];
qr += dq;
}
qr -= dq;
}
if (qr > 0.) nodes.push_back(qr);
fclose(fp);
delete []egvs;
// write the gnuplot script which helps to visualize the result
int nnd = nodes.size();
if (nnd > 1){
fp = fopen("pdisp.gnuplot", "w");
fprintf(fp,"set term post enha colo 20\nset out %cpdisp.eps%c\n\n",char(34),char(34));
fprintf(fp,"set xlabel %cq%c\n",char(34),char(34));
fprintf(fp,"set ylabel %cfrequency (THz)%c\n\n",char(34),char(34));
fprintf(fp,"set xrange [0:%lg]\nset yrange [0:*]\n\n", nodes[nnd-1]);
fprintf(fp,"set grid xtics\n");
fprintf(fp,"# {/Symbol G} will give you letter gamma in the label\nset xtics (");
for (int i=0; i<nnd-1; i++) fprintf(fp,"%c%c %lg, ", char(34),char(34),nodes[i]);
fprintf(fp,"%c%c %lg)\n\n",char(34),char(34),nodes[nnd-1]);
fprintf(fp,"unset key\n\n");
fprintf(fp,"plot %c%s%c u 4:5 w l lt 1",char(34),fname,char(34));
for (int i=1; i<ndim; i++) fprintf(fp,",\\\n%c%c u 4:%d w l lt 1",char(34),char(34),i+5);
fclose(fp);
}
delete []fname;
nodes.clear();
return;
}
/* ----------------------------------------------------------------------------
* Private method to write out the dynamical matrix at selected q
* ---------------------------------------------------------------------------- */
@ -491,7 +402,7 @@ void Phonon::vfanyq()
char str[MAXLINE];
double q[3], egvs[ndim];
while (1){
while ( 1 ){
printf("Please input the q-point to compute the frequencies, q to exit: ");
if (count_words(fgets(str,MAXLINE,stdin)) < 3) break;
@ -503,7 +414,7 @@ void Phonon::vfanyq()
dynmat->geteigen(egvs, 0);
printf("q-point: [%lg %lg %lg], ", q[0], q[1], q[2]);
printf("vibrational frequencies at this q-point:\n");
for (int i=0; i<ndim; i++) printf("%lg ", egvs[i]); printf("\n\n");
for (int i = 0; i < ndim; ++i) printf("%lg ", egvs[i]); printf("\n\n");
}
return;
@ -521,7 +432,7 @@ void Phonon::vecanyq()
if (count_words(fgets(str,MAXLINE,stdin)) < 1) strcpy(str,"eigvec.dat");
FILE *fp = fopen(strtok(str," \t\n\r\f"), "w");
while (1){
while ( 1 ){
printf("Please input the q-point to compute the frequencies, q to exit: ");
if (count_words(fgets(str,MAXLINE,stdin)) < 3) break;
@ -533,14 +444,14 @@ void Phonon::vecanyq()
dynmat->geteigen(egvs, 1);
fprintf(fp,"# q-point: [%lg %lg %lg], sysdim: %d, # of atoms per cell: %d\n",
q[0],q[1],q[2], sysdim, dynmat->nucell);
for (int i=0; i<ndim; i++){
for (int i = 0; i < ndim; ++i){
fprintf(fp,"# frequency %d at [%lg %lg %lg]: %lg\n",i+1,q[0],q[1],q[2],egvs[i]);
fprintf(fp,"# atom eigenvector : |e|\n");
for (int j=0; j<dynmat->nucell; j++){
for (int j = 0; j < dynmat->nucell; ++j){
int ipos = j * sysdim;
double sum = 0.;
fprintf(fp,"%d", j+1);
for (int idim=0; idim<sysdim; idim++){
for (int idim = 0; idim < sysdim; ++idim){
fprintf(fp," %lg %lg", eigvec[i][ipos+idim].r, eigvec[i][ipos+idim].i);
sum += eigvec[i][ipos+idim].r * eigvec[i][ipos+idim].r + eigvec[i][ipos+idim].i * eigvec[i][ipos+idim].i;
}
@ -575,9 +486,8 @@ void Phonon::DMdisp()
int nq = MAX(MAX(dynmat->nx,dynmat->ny),dynmat->nz)/2;
qend[0] = qend[1] = qend[2] = 0.;
while (1){
for (int i=0; i<3; i++) qstr[i] = qend[i];
while ( 1 ){
for (int i = 0; i < 3; ++i) qstr[i] = qend[i];
printf("\nPlease input the start q-point in unit of B1->B3, q to exit [%g %g %g]: ", qstr[0], qstr[1], qstr[2]);
int n = count_words(fgets(str,MAXLINE,stdin));
@ -602,16 +512,17 @@ void Phonon::DMdisp()
for (int i=0; i<3; i++) qinc[i] = (qend[i]-qstr[i])/double(nq-1);
dq = sqrt(qinc[0]*qinc[0]+qinc[1]*qinc[1]+qinc[2]*qinc[2]);
for (int i=0; i<3; i++) q[i] = qstr[i];
for (int ii=0; ii<nq; ii++){
for (int i = 0; i < 3; ++i) q[i] = qstr[i];
for (int ii = 0; ii < nq; ++ii){
dynmat->getDMq(q);
dynmat->writeDMq(q, qr, fp);
for (int i=0; i<3; i++) q[i] += qinc[i];
for (int i = 0; i < 3; ++i) q[i] += qinc[i];
qr += dq;
}
qr -= dq;
}
fclose(fp);
return;
}
@ -625,26 +536,26 @@ void Phonon::smooth(double *array, const int npt)
int nlag = npt/4;
double *tmp, *table;
tmp = memory->create(tmp, npt, "smooth:tmp");
table = memory->create(table, nlag+1, "smooth:table");
memory->create(tmp, npt, "smooth:tmp");
memory->create(table, nlag+1, "smooth:table");
double fnorm = -1.;
double sigma = 4., fac = 1./(sigma*sigma);
for (int jj=0; jj<= nlag; jj++){
for (int jj = 0; jj <= nlag; ++jj){
table[jj] = exp(-double(jj*jj)*fac);
fnorm += table[jj];
}
fnorm = 1./fnorm;
for (int i=0; i<npt; i++){
for (int i = 0; i < npt; ++i){
tmp[i] = 0.;
for (int jj=-nlag; jj<= nlag; jj++){
for (int jj = -nlag; jj <= nlag; ++jj){
int j = (i+jj+npt)%npt; // assume periodical data
tmp [i] += array[j]*table[abs(jj)];
}
}
for (int i=0; i<npt; i++) array[i] = tmp[i]*fnorm;
for (int i = 0; i < npt; ++i) array[i] = tmp[i]*fnorm;
memory->destroy(tmp);
memory->destroy(table);
@ -682,9 +593,9 @@ void Phonon::therm()
double h_o_KbT = h/(Kb*T)*1.e12, KbT_in_eV = Kb*T/eV;
double Uvib = 0., Svib = 0., Fvib = 0., Cvib = 0., ZPE = 0.;
for (int iq=0; iq<nq; iq++){
for (int iq = 0; iq < nq; ++iq){
double Utmp = 0., Stmp = 0., Ftmp = 0., Ztmp = 0., Ctmp = 0.;
for (int i=0; i<ndim; i++){
for (int i = 0; i < ndim; ++i){
if (eigs[iq][i] <= 0.) continue;
double x = eigs[iq][i] * h_o_KbT;
double expterm = 1./(exp(x)-1.);
@ -709,6 +620,7 @@ void Phonon::therm()
printf("Please input the desired temperature (K), enter to exit: ");
if (count_words(fgets(str,MAXLINE,stdin)) < 1) break;
T = atof(strtok(str," \t\n\r\f"));
} while (T > 0.);
fclose(fp);
@ -737,15 +649,15 @@ void Phonon::local_therm()
fprintf(fp,"#-------------------------------------------------------------------------------\n");
double **Uvib, **Svib, **Fvib, **Cvib, **ZPE;
Uvib = memory->create(Uvib,nlocal,sysdim,"local_therm:Uvib");
Svib = memory->create(Svib,nlocal,sysdim,"local_therm:Svib");
Fvib = memory->create(Fvib,nlocal,sysdim,"local_therm:Fvib");
Cvib = memory->create(Cvib,nlocal,sysdim,"local_therm:Cvib");
ZPE = memory->create(ZPE ,nlocal,sysdim,"local_therm:ZPE");
memory->create(Uvib,nlocal,sysdim,"local_therm:Uvib");
memory->create(Svib,nlocal,sysdim,"local_therm:Svib");
memory->create(Fvib,nlocal,sysdim,"local_therm:Fvib");
memory->create(Cvib,nlocal,sysdim,"local_therm:Cvib");
memory->create(ZPE ,nlocal,sysdim,"local_therm:ZPE");
// constants J.s J/K J
const double h = 6.62606896e-34, Kb = 1.380658e-23, eV = 1.60217733e-19;
double T = dynmat->Tmeasure;
while (1){
while ( 1 ){
printf("\nPlease input the temperature at which to evaluate the local vibrational\n");
printf("thermal properties, non-positive number to exit [%g]: ", T);
if (count_words(fgets(str,MAXLINE,stdin)) > 0){
@ -755,11 +667,11 @@ void Phonon::local_therm()
// constants under the same temperature; assuming angular frequency in THz
double h_o_KbT = h/(Kb*T)*1.e12, KbT_in_eV = Kb*T/eV;
for (int i=0; i<nlocal; i++)
for (int j=0; j<sysdim; j++) Uvib[i][j] = Svib[i][j] = Fvib[i][j] = Cvib[i][j] = ZPE[i][j] = 0.;
for (int i = 0; i <nlocal; ++i)
for (int j = 0; j <sysdim; ++j) Uvib[i][j] = Svib[i][j] = Fvib[i][j] = Cvib[i][j] = ZPE[i][j] = 0.;
double freq = fmin-df;
for (int i=0; i<ndos; i++){
for (int i = 0; i < ndos; ++i){
freq += df;
if (freq <= 0.) continue;
@ -772,8 +684,8 @@ void Phonon::local_therm()
double Ctmp = x*x*exp(x)*expterm*expterm;
double Ztmp = 0.5*h*freq;
for (int il=0; il<nlocal; il++)
for (int idim=0; idim<sysdim; idim++){
for (int il = 0; il < nlocal; ++il)
for (int idim = 0; idim < sysdim; ++idim){
Uvib[il][idim] += ldos[il][i][idim]*Utmp;
Svib[il][idim] += ldos[il][i][idim]*Stmp;
Fvib[il][idim] += ldos[il][i][idim]*Ftmp;
@ -781,8 +693,8 @@ void Phonon::local_therm()
ZPE [il][idim] += ldos[il][i][idim]*Ztmp;
}
}
for (int il=0; il<nlocal; il++)
for (int idim=0; idim<sysdim; idim++){
for (int il = 0; il < nlocal; ++il)
for (int idim = 0; idim < sysdim; ++idim){
Uvib[il][idim] *= KbT_in_eV*df;
Svib[il][idim] *= df;
Fvib[il][idim] *= KbT_in_eV*df;
@ -791,34 +703,34 @@ void Phonon::local_therm()
}
// output result under current temperature
for (int il=0; il<nlocal; il++){
for (int il = 0; il < nlocal; ++il){
fprintf(fp,"%d %g ", locals[il], T);
double total = 0.;
for (int idim=0; idim<sysdim; idim++){
for (int idim = 0; idim < sysdim; ++idim){
fprintf(fp,"%g ", Uvib[il][idim]);
total += Uvib[il][idim];
}
fprintf(fp,"%g ", total); total = 0.;
for (int idim=0; idim<sysdim; idim++){
for (int idim = 0; idim < sysdim; ++idim){
fprintf(fp,"%g ", Svib[il][idim]);
total += Svib[il][idim];
}
fprintf(fp,"%g ", total); total = 0.;
for (int idim=0; idim<sysdim; idim++){
for (int idim = 0; idim < sysdim; ++idim){
fprintf(fp,"%g ", Fvib[il][idim]);
total += Fvib[il][idim];
}
fprintf(fp,"%g ", total); total = 0.;
for (int idim=0; idim<sysdim; idim++){
for (int idim = 0; idim < sysdim; ++idim){
fprintf(fp,"%g ", Cvib[il][idim]);
total += Cvib[il][idim];
}
fprintf(fp,"%g ", total); total = 0.;
for (int idim=0; idim<sysdim; idim++){
for (int idim = 0; idim < sysdim; ++idim){
fprintf(fp,"%g ", ZPE[il][idim]);
total += ZPE[il][idim];
}
@ -846,7 +758,7 @@ void Phonon::QMesh()
ny = atoi(strtok(NULL," \t\n\r\f"));
nz = atoi(strtok(NULL," \t\n\r\f"));
}
if (nx<1||ny<1||nz<1) return;
if (nx < 1||ny < 1||nz < 1) return;
if (dynmat->nx == 1) nx = 1;
if (dynmat->ny == 1) ny = 1;
if (dynmat->nz == 1) nz = 1;
@ -855,9 +767,9 @@ void Phonon::QMesh()
// ask method to generate q-points
int method = 2;
printf("Please select your method to generate the q-points:\n");
printf(" 1. uniform;\n 2. Monkhost-Pack mesh;\nYour choice[2]: ");
printf(" 1. uniform;\n 2. Monkhost-Pack mesh;\nYour choice [2]: ");
if (count_words(fgets(str,MAXLINE,stdin)) > 0) method = atoi(strtok(str," \t\n\r\f"));
method = 2-method%2;
method = 2 - method%2;
printf("Your selection: %d\n", method);
#endif
@ -869,149 +781,52 @@ void Phonon::QMesh()
#endif
nq = nx*ny*nz;
double w = 1./double(nq);
wt = memory->create(wt, nq, "QMesh:wt");
qpts = memory->create(qpts, nq, 3, "QMesh:qpts");
memory->create(wt, nq, "QMesh:wt");
memory->create(qpts, nq, 3, "QMesh:qpts");
int iq = 0;
for (int i=0; i<nx; i++)
for (int j=0; j<ny; j++)
for (int k=0; k<nz; k++){
for (int i = 0; i < nx; ++i)
for (int j = 0; j < ny; ++j)
for (int k = 0; k < nz; ++k){
qpts[iq][0] = double(i)/double(nx);
qpts[iq][1] = double(j)/double(ny);
qpts[iq][2] = double(k)/double(nz);
wt[iq++] = w;
}
#ifdef UseSPG
}
if ((method == 2) && (atpos == NULL)){
atpos = memory->create(atpos, dynmat->nucell,3,"QMesh:atpos");
attyp = memory->create(attyp, dynmat->nucell, "QMesh:attyp");
} else {
if (atpos == NULL) memory->create(atpos, dynmat->nucell,3,"QMesh:atpos");
if (attyp == NULL) memory->create(attyp, dynmat->nucell, "QMesh:attyp");
for (int i=0; i<dynmat->nucell; i++)
for (int idim=0; idim<3; idim++) atpos[i][idim] = 0.;
for (int i=0; i<3; i++) latvec[i][i] = 1.;
int flag_lat_info_read = dynmat->flag_latinfo;
if ( flag_lat_info_read ){ // get unit cell info from binary file; done by dynmat
num_atom = dynmat->nucell;
// set default, in case system dimension under study is not 3.
for (int i=0; i<dynmat->nucell; i++)
for (int idim=0; idim<3; idim++) atpos[i][idim] = 0.;
for (int i=0; i<3; i++) latvec[i][i] = 1.;
for (int i = 0; i < dynmat->nucell; ++i)
for (int idim = 0; idim < 3; ++idim) atpos[i][idim] = 0.;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j) latvec[i][j] = 0.;
for (int i = 0; i < 3; ++i) latvec[i][i] = 1.;
// get atomic type info
for (int i=0; i<num_atom; i++) attyp[i] = dynmat->attyp[i];
for (int i = 0; i < num_atom; ++i) attyp[i] = dynmat->attyp[i];
// get unit cell vector info
int ndim = 0;
for (int idim=0; idim<3; idim++)
for (int jdim=0; jdim<3; jdim++) latvec[jdim][idim] = dynmat->basevec[ndim++];
for (int idim = 0; idim < 3; ++idim)
for (int jdim = 0; jdim < 3; ++jdim) latvec[jdim][idim] = dynmat->basevec[ndim++];
// get atom position in unit cell; fractional
for (int i=0; i<num_atom; i++)
for (int idim=0; idim<sysdim; idim++) atpos[i][idim] = dynmat->basis[i][idim];
for (int i = 0; i < num_atom; ++i)
for (int idim = 0; idim < sysdim; ++idim) atpos[i][idim] = dynmat->basis[i][idim];
// display the unit cell info read
printf("\n");for (int ii=0; ii<80; ii++) printf("="); printf("\n");
printf("\n");for (int ii = 0; ii < 80; ++ii) printf("="); printf("\n");
printf("The basis vectors of the unit cell:\n");
for (int idim=0; idim<3; idim++) printf(" A%d = %lg %lg %lg\n", idim+1, latvec[0][idim], latvec[1][idim], latvec[2][idim]);
for (int idim = 0; idim < 3; ++idim) printf(" A%d = %lg %lg %lg\n", idim+1, latvec[0][idim], latvec[1][idim], latvec[2][idim]);
printf("Atom(s) in the unit cell:\n");
printf(" No. type sx sy sz\n");
for (int i=0; i<num_atom; i++) printf(" %d %d %lg %lg %lg\n", i+1, attyp[i], atpos[i][0], atpos[i][1], atpos[i][2]);
printf("\nIs the above info correct? (y/n)[y]: ");
fgets(str,MAXLINE,stdin);
char *ptr = strtok(str," \t\n\r\f");
if ( (ptr) && ( (strcmp(ptr,"y") != 0) && (strcmp(ptr,"Y") != 0)) ) flag_lat_info_read = 0;
}
for (int i = 0; i < MIN(num_atom, NUMATOM); ++i) printf(" %d %d %lg %lg %lg\n", i+1, attyp[i], atpos[i][0], atpos[i][1], atpos[i][2]);
if (num_atom > NUMATOM) printf(" ... (%d atoms omitted.)\n", num_atom - NUMATOM);
if (flag_lat_info_read == 0) { // get unit cell info from file or user input
int latsrc = 1;
printf("\nPlease select the way to provide the unit cell info:\n");
printf(" 1. By file;\n 2. Read in.\nYour choice [1]: ");
if (count_words(fgets(str,MAXLINE,stdin)) > 0) latsrc = atoi(strtok(str," \t\n\r\f"));
latsrc = 2-latsrc%2;
/*----------------------------------------------------------------
* Ask for lattice info from the user; the format of the file is:
* A1_x A1_y A1_z
* A2_x A2_y A2_z
* A3_x A3_y A3_z
* natom
* Type_1 sx_1 sy_1 sz_1
* ...
* Type_n sx_n sy_n sz_n
*----------------------------------------------------------------*/
if (latsrc == 1){ // to read unit cell info from file; get file name first
do printf("Please input the file name containing the unit cell info: ");
while (count_words(fgets(str,MAXLINE,stdin)) < 1);
char *fname = strtok(str," \t\n\r\f");
FILE *fp = fopen(fname,"r"); fname = NULL;
if (fp == NULL) latsrc = 2;
else {
for (int i=0; i<3; i++){ // read unit cell vector info; # of atoms per unit cell
if (count_words(fgets(str,MAXLINE,fp)) < 3){
latsrc = 2;
break;
}
latvec[0][i] = atof(strtok(str, " \t\n\r\f"));
latvec[1][i] = atof(strtok(NULL," \t\n\r\f"));
latvec[2][i] = atof(strtok(NULL," \t\n\r\f"));
}
if (count_words(fgets(str,MAXLINE,fp)) < 1) latsrc = 2;
else {
num_atom = atoi(strtok(str," \t\n\r\f"));
if (num_atom > dynmat->nucell){
printf("\nError: # of atoms read from file (%d) is bigger than that given by the dynamical matrix (%d)!\n", num_atom, dynmat->nucell);
return;
}
for (int i=0; i<num_atom; i++){ // read atomic type and fractional positions
if (count_words(fgets(str,MAXLINE,fp)) < 4){
latsrc = 2;
break;
} else {
attyp[i] = atoi(strtok(str," \t\n\r\f"));
atpos[i][0] = atof(strtok(NULL," \t\n\r\f"));
atpos[i][1] = atof(strtok(NULL," \t\n\r\f"));
atpos[i][2] = atof(strtok(NULL," \t\n\r\f"));
}
}
}
}
fclose(fp);
}
if (latsrc == 2){
for (int i=0; i<3; i++){
do printf("Please input the vector A%d: ", i+1);
while (count_words(fgets(str,MAXLINE,stdin)) < 3);
latvec[0][i] = atof(strtok(str," \t\n\r\f"));
latvec[1][i] = atof(strtok(NULL," \t\n\r\f"));
latvec[2][i] = atof(strtok(NULL," \t\n\r\f"));
}
do printf("please input the number of atoms per unit cell: ");
while (count_words(fgets(str,MAXLINE,stdin)) < 1);
num_atom = atoi(strtok(str," \t\n\r\f"));
if (num_atom > dynmat->nucell){
printf("\nError: # of atoms input (%d) is bigger than that given by the dynamical matrix (%d)!\n", num_atom, dynmat->nucell);
return;
}
for (int i=0; i<num_atom; i++){
do printf("Please input the type, and fractional coordinate of atom No.%d: ", i+1);
while (count_words(fgets(str,MAXLINE,stdin)) < 4);
attyp[i] = atoi(strtok(str," \t\n\r\f"));
atpos[i][0] = atof(strtok(NULL," \t\n\r\f"));
atpos[i][1] = atof(strtok(NULL," \t\n\r\f"));
atpos[i][2] = atof(strtok(NULL," \t\n\r\f"));
}
}
} // end of read from file or input
} // end of if (method == 2 && ...
if (method == 2){
int mesh[3], shift[3], is_time_reversal = 0;
mesh[0] = nx; mesh[1] = ny; mesh[2] = nz;
shift[0] = shift[1] = shift[2] = 0;
@ -1019,29 +834,28 @@ void Phonon::QMesh()
int grid_point[num_grid][3], map[num_grid];
double symprec = 1.e-4, pos[num_atom][3];
for (int i=0; i<num_atom; i++)
for (int j=0; j<3; j++) pos[i][j] = atpos[i][j];
for (int i = 0; i < num_atom; ++i)
for (int j = 0; j < 3; ++j) pos[i][j] = atpos[i][j];
//spg_show_symmetry(latvec, pos, attyp, num_atom, symprec);
// if spglib 0.7.1 is used
nq = spg_get_ir_reciprocal_mesh(grid_point, map, num_grid, mesh, shift, is_time_reversal, latvec, pos, attyp, num_atom, symprec);
// nq = spg_get_ir_reciprocal_mesh(grid_point, map, num_grid, mesh, shift, is_time_reversal, latvec, pos, attyp, num_atom, symprec);
// if spglib >= 1.0.3 is used
//nq = spg_get_ir_reciprocal_mesh(grid_point, map, mesh, shift, is_time_reversal, latvec, pos, attyp, num_atom, symprec);
nq = spg_get_ir_reciprocal_mesh(grid_point, map, mesh, shift, is_time_reversal, latvec, pos, attyp, num_atom, symprec);
wt = memory->create(wt, nq, "QMesh:wt");
qpts = memory->create(qpts, nq,3,"QMesh:qpts");
memory->create(wt, nq, "QMesh:wt");
memory->create(qpts, nq,3,"QMesh:qpts");
int *iq2idx = new int[num_grid];
int numq = 0;
for (int i=0; i<num_grid; i++){
for (int i = 0; i < num_grid; ++i){
int iq = map[i];
if (iq == i) iq2idx[iq] = numq++;
}
for (int iq=0; iq<nq; iq++) wt[iq] = 0.;
for (int iq = 0; iq < nq; ++iq) wt[iq] = 0.;
numq = 0;
for (int i=0; i<num_grid; i++){
for (int i = 0; i < num_grid; ++i){
int iq = map[i];
if (iq == i){
qpts[numq][0] = double(grid_point[i][0])/double(mesh[0]);
@ -1054,8 +868,8 @@ void Phonon::QMesh()
delete []iq2idx;
double wsum = 0.;
for (int iq=0; iq<nq; iq++) wsum += wt[iq];
for (int iq=0; iq<nq; iq++) wt[iq] /= wsum;
for (int iq = 0; iq < nq; ++iq) wsum += wt[iq];
for (int iq = 0; iq < nq; ++iq) wt[iq] /= wsum;
}
#endif
@ -1078,7 +892,7 @@ void Phonon::ldos_egv()
if (nmax < 1) return;
memory->destroy(locals);
locals = memory->create(locals, nmax, "ldos_egv:locals");
memory->create(locals, nmax, "ldos_egv:locals");
nlocal = 0;
ptr = strtok(str," \t\n\r\f");
@ -1091,7 +905,7 @@ void Phonon::ldos_egv()
if (nlocal < 1) return;
printf("Local PDOS for atom(s):");
for (int i=0; i<nlocal; i++) printf(" %d", locals[i]);
for (int i = 0; i < nlocal; ++i) printf(" %d", locals[i]);
printf(" will be computed.\n");
fmin = 0.; fmax = 10.;
@ -1118,14 +932,14 @@ void Phonon::ldos_egv()
memory->destroy(dos);
memory->destroy(ldos);
dos = memory->create(dos, ndos,"ldos_egv:dos");
ldos = memory->create(ldos,nlocal,ndos,sysdim,"ldos_egv:ldos");
memory->create(dos, ndos,"ldos_egv:dos");
memory->create(ldos,nlocal,ndos,sysdim,"ldos_egv:ldos");
for (int i=0; i<ndos; i++) dos[i] = 0.;
for (int i = 0; i < ndos; ++i) dos[i] = 0.;
for (int ilocal=0; ilocal<nlocal; ilocal++)
for (int i=0; i<ndos; i++)
for (int idim=0; idim<sysdim; idim++) ldos[ilocal][i][idim] = 0.;
for (int ilocal = 0; ilocal < nlocal; ++ilocal)
for (int i = 0; i < ndos; ++i)
for (int idim = 0; idim < sysdim; ++idim) ldos[ilocal][i][idim] = 0.;
int nprint;
if (nq > 10) nprint = nq/10;
@ -1137,7 +951,7 @@ void Phonon::ldos_egv()
doublecomplex **egvec = dynmat->DM_q;
printf("\nNow to compute the phonons and DOSs "); fflush(stdout);
for (int iq=0; iq<nq; iq++){
for (int iq = 0; iq < nq; ++iq){
if ((iq+1)%nprint == 0) {printf("."); fflush(stdout);}
dynmat->getDMq(qpts[iq], &wt[iq]);
@ -1145,14 +959,14 @@ void Phonon::ldos_egv()
dynmat->geteigen(&egval[0], 1);
for (int idim=0; idim<ndim; idim++){
for (int idim = 0; idim < ndim; ++idim){
int hit = int((egval[idim] - offset)*rdf);
if (hit >= 0 && hit <ndos){
dos[hit] += wt[iq];
for (int ilocal=0; ilocal<nlocal; ilocal++){
for (int ilocal = 0; ilocal < nlocal; ++ilocal){
int ipos = locals[ilocal]*sysdim;
for (int jdim=0; jdim<sysdim; jdim++){
for (int jdim = 0; jdim < sysdim; ++jdim){
double dr = egvec[idim][ipos+jdim].r, di = egvec[idim][ipos+jdim].i;
double norm = dr * dr + di * di;
ldos[ilocal][hit][jdim] += wt[iq] * norm;
@ -1179,6 +993,33 @@ void Phonon::ldos_egv()
return;
}
/* ----------------------------------------------------------------------------
* Private method to show the unit cell info
* ---------------------------------------------------------------------------- */
void Phonon::ShowCell()
{
printf("\n");
for (int i = 0; i < 30; ++i) printf("=");
printf(" Unit Cell Info ");
for (int i = 0; i < 30; ++i) printf("="); printf("\n");
printf("Number of atoms in the unit cell: %d\n", dynmat->nucell);
printf("Basis vectors of the unit cell:\n");
printf(" %15.8f %15.8f %15.8f\n", dynmat->basevec[0], dynmat->basevec[1], dynmat->basevec[2]);
printf(" %15.8f %15.8f %15.8f\n", dynmat->basevec[3], dynmat->basevec[4], dynmat->basevec[5]);
printf(" %15.8f %15.8f %15.8f\n", dynmat->basevec[6], dynmat->basevec[7], dynmat->basevec[8]);
printf("Basis vectors of the reciprocal:\n");
printf(" %15.8f %15.8f %15.8f\n", dynmat->ibasevec[0], dynmat->ibasevec[1], dynmat->ibasevec[2]);
printf(" %15.8f %15.8f %15.8f\n", dynmat->ibasevec[3], dynmat->ibasevec[4], dynmat->ibasevec[5]);
printf(" %15.8f %15.8f %15.8f\n", dynmat->ibasevec[6], dynmat->ibasevec[7], dynmat->ibasevec[8]);
printf("Atomic type and fractional coordinates:\n");
for (int i = 0; i < dynmat->nucell; ++i)
printf("%4d %12.8f %12.8f %12.8f\n", dynmat->attyp[i], dynmat->basis[i][0], dynmat->basis[i][1], dynmat->basis[i][2]);
for (int i = 0; i < 80; ++i) printf("=");
printf("\n");
return;
}
/* ----------------------------------------------------------------------------
* Private method to normalize the DOS and/or Local DOS.
* Simpson's rule is used for the integration.
@ -1188,24 +1029,24 @@ void Phonon::Normalize()
double odd, even, sum;
if (dos){
odd = even = 0.;
for (int i=1; i<ndos-1; i +=2) odd += dos[i];
for (int i=2; i<ndos-1; i +=2) even += dos[i];
for (int i = 1; i < ndos-1; i +=2) odd += dos[i];
for (int i = 2; i < ndos-1; i +=2) even += dos[i];
sum = dos[0] + dos[ndos-1];
sum += 4.*odd + 2.*even;
sum = 3.*rdf/sum;
for (int i=0; i<ndos; i++) dos[i] *= sum;
for (int i = 0; i < ndos; ++i) dos[i] *= sum;
}
if (ldos){
for (int ilocal=0; ilocal<nlocal; ilocal++)
for (int idim=0; idim<sysdim; idim++){
for (int ilocal = 0; ilocal < nlocal; ++ilocal)
for (int idim = 0; idim < sysdim; ++idim){
odd = even = 0.;
for (int i=1; i<ndos-1; i +=2) odd += ldos[ilocal][i][idim];
for (int i=2; i<ndos-1; i +=2) even += ldos[ilocal][i][idim];
for (int i = 1; i < ndos-1; i += 2) odd += ldos[ilocal][i][idim];
for (int i = 2; i < ndos-1; i += 2) even += ldos[ilocal][i][idim];
sum = ldos[ilocal][0][idim] + ldos[ilocal][ndos-1][idim];
sum += 4.*odd + 2.*even;
sum = 3.*rdf/sum;
for (int i=0; i<ndos; i++) ldos[ilocal][i][idim] *= sum;
for (int i = 0; i < ndos; ++i) ldos[ilocal][i][idim] *= sum;
}
}
@ -1225,9 +1066,9 @@ void Phonon::ComputeAll()
printf("\nNow to compute the phonons "); fflush(stdout);
// now to calculate the frequencies at all q-points
memory->destroy(eigs);
eigs = memory->create(eigs, nq,ndim,"QMesh_eigs");
memory->create(eigs, nq,ndim,"QMesh_eigs");
for (int iq=0; iq<nq; iq++){
for (int iq = 0; iq < nq; ++iq){
if ((iq+1)%nprint == 0) {printf("."); fflush(stdout);}
dynmat->getDMq(qpts[iq], &wt[iq]);
@ -1246,7 +1087,7 @@ int Phonon::count_words(const char *line)
{
int n = strlen(line) + 1;
char *copy;
copy = memory->create(copy, n, "count_words:copy");
memory->create(copy, n, "count_words:copy");
strcpy(copy,line);
char *ptr;

View File

@ -43,6 +43,8 @@ private:
void DMdisp();
void vecanyq();
void ShowCell();
void smooth(double *, const int);
void writeDOS();
void writeLDOS();

View File

@ -1,5 +1,7 @@
#include "timer.h"
/* -----------------------------------------------------------------------------
* Initialization of time
* -------------------------------------------------------------------------- */
Timer::Timer()
{
flag = 0;
@ -7,6 +9,9 @@ Timer::Timer()
return;
}
/* -----------------------------------------------------------------------------
* public function, start the timer
* -------------------------------------------------------------------------- */
void Timer::start()
{
t1 = clock();
@ -15,6 +20,9 @@ void Timer::start()
return;
}
/* -----------------------------------------------------------------------------
* public function, stop the timer
* -------------------------------------------------------------------------- */
void Timer::stop()
{
if ( flag&1 ) {
@ -24,6 +32,9 @@ void Timer::stop()
return;
}
/* -----------------------------------------------------------------------------
* public function, print the total time used after timer stops
* -------------------------------------------------------------------------- */
void Timer::print()
{
if ( (flag&3) != 3) return;
@ -34,6 +45,9 @@ void Timer::print()
return;
}
/* -----------------------------------------------------------------------------
* public function, return the total time used up to now, in seconds
* -------------------------------------------------------------------------- */
double Timer::elapse()
{
if ( (flag&3) != 3) return 0.;

View File

@ -1 +1 @@
#define VERSION 75
#define VERSION 7