if(moldyn->rfd) {
dprintf(moldyn->rfd,report_end);
close(moldyn->rfd);
- snprintf(sc,255,"cd %s && pdflatex report",moldyn->vlsdir);
+ snprintf(sc,255,"cd %s && pdflatex report >/dev/null 2>&1",
+ moldyn->vlsdir);
system(sc);
- snprintf(sc,255,"cd %s && pdflatex report",moldyn->vlsdir);
+ snprintf(sc,255,"cd %s && pdflatex report >/dev/null 2>&1",
+ moldyn->vlsdir);
system(sc);
- snprintf(sc,255,"cd %s && dvipdf report",moldyn->vlsdir);
+ snprintf(sc,255,"cd %s && dvipdf report >/dev/null 2>&1",
+ moldyn->vlsdir);
system(sc);
}
if(&(moldyn->vis)) visual_tini(&(moldyn->vis));
v+=(virial->xx+virial->yy+virial->zz);
}
+ /* virial sum and mean virial */
+ moldyn->virial_sum+=v;
+ moldyn->mean_v=moldyn->virial_sum/moldyn->total_steps;
+
/* assume up to date kinetic energy */
- moldyn->p=2.0*moldyn->ekin+v;
+ moldyn->p=2.0*moldyn->ekin+moldyn->mean_v;
moldyn->p/=(3.0*moldyn->volume);
moldyn->p_sum+=moldyn->p;
moldyn->mean_p=moldyn->p_sum/moldyn->total_steps;
double thermodynamic_pressure_calc(t_moldyn *moldyn) {
t_3dvec dim,*tp;
- double u,p;
- double scale,dv;
+ double u_up,u_down,dv;
+ double scale,p;
t_atom *store;
/*
*
* => p = - dU/dV
*
- * dV: dx,y,z = 0.001 x,y,z
*/
- scale=1.00000000000001;
-printf("\n\nP-DEBUG:\n");
+ scale=0.00001;
+ dv=8*scale*scale*scale*moldyn->volume;
- tp=&(moldyn->tp);
store=malloc(moldyn->count*sizeof(t_atom));
if(store==NULL) {
printf("[moldyn] allocating store mem failed\n");
}
/* save unscaled potential energy + atom/dim configuration */
- u=moldyn->energy;
memcpy(store,moldyn->atom,moldyn->count*sizeof(t_atom));
dim=moldyn->dim;
- /* derivative with respect to x direction */
- scale_dim(moldyn,scale,TRUE,0,0);
- scale_atoms(moldyn,scale,TRUE,0,0);
- dv=0.00000000000001*moldyn->dim.x*moldyn->dim.y*moldyn->dim.z;
+ /* scale up dimension and atom positions */
+ scale_dim(moldyn,SCALE_UP,scale,TRUE,TRUE,TRUE);
+ scale_atoms(moldyn,SCALE_UP,scale,TRUE,TRUE,TRUE);
link_cell_shutdown(moldyn);
link_cell_init(moldyn,QUIET);
potential_force_calc(moldyn);
- tp->x=(moldyn->energy-u)/dv;
- p=tp->x*tp->x;
+ u_up=moldyn->energy;
/* restore atomic configuration + dim */
memcpy(moldyn->atom,store,moldyn->count*sizeof(t_atom));
moldyn->dim=dim;
- /* derivative with respect to y direction */
- scale_dim(moldyn,scale,0,TRUE,0);
- scale_atoms(moldyn,scale,0,TRUE,0);
- dv=0.00000000000001*moldyn->dim.y*moldyn->dim.x*moldyn->dim.z;
+ /* scale down dimension and atom positions */
+ scale_dim(moldyn,SCALE_DOWN,scale,TRUE,TRUE,TRUE);
+ scale_atoms(moldyn,SCALE_DOWN,scale,TRUE,TRUE,TRUE);
link_cell_shutdown(moldyn);
link_cell_init(moldyn,QUIET);
potential_force_calc(moldyn);
- tp->y=(moldyn->energy-u)/dv;
- p+=tp->y*tp->y;
-
- /* restore atomic configuration + dim */
- memcpy(moldyn->atom,store,moldyn->count*sizeof(t_atom));
- moldyn->dim=dim;
-
- /* derivative with respect to z direction */
- scale_dim(moldyn,scale,0,0,TRUE);
- scale_atoms(moldyn,scale,0,0,TRUE);
- dv=0.00000000000001*moldyn->dim.z*moldyn->dim.x*moldyn->dim.y;
- link_cell_shutdown(moldyn);
- link_cell_init(moldyn,QUIET);
- potential_force_calc(moldyn);
- tp->z=(moldyn->energy-u)/dv;
- p+=tp->z*tp->z;
+ u_down=moldyn->energy;
+
+ /* calculate pressure */
+ p=-(u_up-u_down)/dv;
+printf("-------> %.10f %.10f %f\n",u_up/EV/moldyn->count,u_down/EV/moldyn->count,p/BAR);
/* restore atomic configuration + dim */
memcpy(moldyn->atom,store,moldyn->count*sizeof(t_atom));
moldyn->dim=dim;
/* restore energy */
- moldyn->energy=u;
+ potential_force_calc(moldyn);
link_cell_shutdown(moldyn);
link_cell_init(moldyn,QUIET);
- return sqrt(p);
+ return p;
}
double get_pressure(t_moldyn *moldyn) {
}
-int scale_dim(t_moldyn *moldyn,double scale,u8 x,u8 y,u8 z) {
+int scale_dim(t_moldyn *moldyn,u8 dir,double scale,u8 x,u8 y,u8 z) {
t_3dvec *dim;
dim=&(moldyn->dim);
+ if(dir==SCALE_UP)
+ scale=1.0+scale;
+
+ if(dir==SCALE_DOWN)
+ scale=1.0-scale;
+
if(x) dim->x*=scale;
if(y) dim->y*=scale;
if(z) dim->z*=scale;
return 0;
}
-int scale_atoms(t_moldyn *moldyn,double scale,u8 x,u8 y,u8 z) {
+int scale_atoms(t_moldyn *moldyn,u8 dir,double scale,u8 x,u8 y,u8 z) {
int i;
t_3dvec *r;
+ if(dir==SCALE_UP)
+ scale=1.0+scale;
+
+ if(dir==SCALE_DOWN)
+ scale=1.0-scale;
+
for(i=0;i<moldyn->count;i++) {
r=&(moldyn->atom[i].r);
if(x) r->x*=scale;
moldyn->debug=scale;
/* scale the atoms and dimensions */
- scale_atoms(moldyn,scale,TRUE,TRUE,TRUE);
- scale_dim(moldyn,scale,TRUE,TRUE,TRUE);
+ scale_atoms(moldyn,SCALE_DIRECT,scale,TRUE,TRUE,TRUE);
+ scale_dim(moldyn,SCALE_DIRECT,scale,TRUE,TRUE,TRUE);
/* visualize dimensions */
if(vdim->x!=0) {
temperature_calc(moldyn);
pressure_calc(moldyn);
//tp=thermodynamic_pressure_calc(moldyn);
-//printf("thermodynamic p: %f %f %f - %f\n",moldyn->tp.x/BAR,moldyn->tp.y/BAR,moldyn->tp.z/BAR,tp/BAR);
+//printf("thermodynamic p: %f\n",thermodynamic_pressure_calc(moldyn)/BAR);
/* p/t scaling */
if(moldyn->pt_scale&(T_SCALE_BERENDSEN|T_SCALE_DIRECT))
}
/* check for hooks */
- if(sched->hook)
- sched->hook(moldyn,sched->hook_params);
+ if(sched->count+1<sched->total_sched)
+ if(sched->hook)
+ sched->hook(moldyn,sched->hook_params);
/* get a new info line */
printf("\n");
/* single particle potential/force */
if(itom[i].attr&ATOM_ATTR_1BP)
- moldyn->func1b(moldyn,&(itom[i]));
+ if(moldyn->func1b)
+ moldyn->func1b(moldyn,&(itom[i]));
if(!(itom[i].attr&(ATOM_ATTR_2BP|ATOM_ATTR_3BP)))
continue;
return 0;
}
+
+/*
+ * postprocessing functions
+ */
+
+int get_line(int fd,char *line,int max) {
+
+ int count,ret;
+
+ count=0;
+
+ while(1) {
+ if(count==max) return count;
+ ret=read(fd,line+count,1);
+ if(ret<=0) return ret;
+ if(line[count]=='\n') {
+ line[count]='\0';
+ return count+1;
+ }
+ count+=1;
+ }
+}
+
+int calc_fluctuations(double start,double end,t_moldyn *moldyn) {
+
+ int fd;
+ int count,ret;
+ double time,pot,kin,tot;
+ double p_sum,k_sum,t_sum;
+ char buf[64];
+ char file[128+7];
+
+ printf("[moldyn] calculating energy fluctuations [eV]:\n");
+
+ snprintf(file,128+7,"%s/energy",moldyn->vlsdir);
+ fd=open(file,O_RDONLY);
+ if(fd<0) {
+ perror("[moldyn] post proc energy open");
+ return fd;
+ }
+
+ /* first calc the averages */
+ p_sum=0.0;
+ k_sum=0.0;
+ t_sum=0.0;
+ count=0;
+ while(1) {
+ ret=get_line(fd,buf,63);
+ if(ret<=0) break;
+ if(buf[0]=='#') continue;
+ sscanf(buf,"%lf %lf %lf %lf",&time,&kin,&pot,&tot);
+ if(time<start) continue;
+ if(time>end) break;
+ p_sum+=pot;
+ k_sum+=kin;
+ t_sum+=tot;
+ count+=1;
+ }
+
+ moldyn->p_m=p_sum/count;
+ moldyn->k_m=k_sum/count;
+ moldyn->t_m=t_sum/count;
+
+ /* mean square fluctuations */
+ if(lseek(fd,SEEK_SET,0)<0) {
+ perror("[moldyn] lseek");
+ return -1;
+ }
+ count=0;
+ p_sum=0.0;
+ k_sum=0.0;
+ t_sum=0.0;
+ while(1) {
+ ret=get_line(fd,buf,63);
+ if(ret<=0) break;
+ if(buf[0]=='#') continue;
+ sscanf(buf,"%lf %lf %lf %lf",&time,&kin,&pot,&tot);
+ if(time<start) continue;
+ if(time>end) break;
+ k_sum+=((kin-moldyn->k_m)*(kin-moldyn->k_m));
+ p_sum+=((pot-moldyn->p_m)*(pot-moldyn->p_m));
+ t_sum+=((tot-moldyn->t_m)*(tot-moldyn->t_m));
+ count+=1;
+ }
+
+ moldyn->dp2_m=p_sum/count;
+ moldyn->dk2_m=k_sum/count;
+ moldyn->dt2_m=t_sum/count;
+
+ printf(" averages : %f %f %f\n",moldyn->k_m,
+ moldyn->p_m,
+ moldyn->t_m);
+ printf(" mean square: %f %f %f\n",moldyn->dk2_m,
+ moldyn->dp2_m,
+ moldyn->dt2_m);
+
+ close(fd);
+
+ return 0;
+}
+
+int get_heat_capacity(t_moldyn *moldyn) {
+
+ double temp2,mass,ighc;
+ int i;
+
+ /* (temperature average)^2 */
+ temp2=2.0*moldyn->k_m*EV/(3.0*K_BOLTZMANN);
+ printf("[moldyn] specific heat capacity for T=%f K [J/(kg K)]\n",temp2);
+ temp2*=temp2;
+
+ /* total mass */
+ mass=0.0;
+ for(i=0;i<moldyn->count;i++)
+ mass+=moldyn->atom[i].mass;
+
+ /* ideal gas contribution */
+ ighc=3.0*moldyn->count*K_BOLTZMANN/2.0;
+ printf(" ideal gas contribution: %f\n",ighc/mass*KILOGRAM/JOULE);
+
+ moldyn->c_v_nvt=moldyn->dp2_m*moldyn->count*moldyn->count*EV/(K_BOLTZMANN*temp2)+ighc;
+ moldyn->c_v_nvt/=mass;
+ moldyn->c_v_nve=ighc/(1.0-(moldyn->dp2_m*moldyn->count*moldyn->count*EV/(ighc*K_BOLTZMANN*temp2)));
+ moldyn->c_v_nve/=mass;
+
+ printf(" NVE: %f\n",moldyn->c_v_nve*KILOGRAM/JOULE);
+ printf(" NVT: %f\n",moldyn->c_v_nvt*KILOGRAM/JOULE);
+
+ return 0;
+}