int moldyn_init(t_moldyn *moldyn,int argc,char **argv) {
+ printf("[moldyn] init\n");
+
memset(moldyn,0,sizeof(t_moldyn));
rand_init(&(moldyn->random),NULL,1);
int moldyn_shutdown(t_moldyn *moldyn) {
printf("[moldyn] shutdown\n");
+
moldyn_log_shutdown(moldyn);
link_cell_shutdown(moldyn);
rand_close(&(moldyn->random));
int set_int_alg(t_moldyn *moldyn,u8 algo) {
+ printf("[moldyn] integration algorithm: ");
+
switch(algo) {
case MOLDYN_INTEGRATE_VERLET:
moldyn->integrate=velocity_verlet;
+ printf("velocity verlet\n");
break;
default:
printf("unknown integration algorithm: %02x\n",algo);
+ printf("unknown\n");
return -1;
}
moldyn->cutoff=cutoff;
+ printf("[moldyn] cutoff [A]: %f\n",moldyn->cutoff);
+
return 0;
}
moldyn->t_ref=t_ref;
+ printf("[moldyn] temperature: %f\n",moldyn->t_ref);
+
return 0;
}
moldyn->p_ref=p_ref;
+ printf("[moldyn] pressure: %f\n",moldyn->p_ref);
+
return 0;
}
moldyn->t_tc=ttc;
moldyn->p_tc=ptc;
+ printf("[moldyn] p/t scaling:\n");
+
+ printf(" p: %s",ptype?"yes":"no ");
+ if(ptype)
+ printf(" | type: %02x | factor: %f",ptype,ptc);
+ printf("\n");
+
+ printf(" t: %s",ttype?"yes":"no ");
+ if(ttype)
+ printf(" | type: %02x | factor: %f",ttype,ttc);
+ printf("\n");
+
return 0;
}
moldyn->vis.dim.z=z;
}
+ moldyn->dv=0.000001*moldyn->volume;
+
printf("[moldyn] dimensions in A and A^3 respectively:\n");
printf(" x: %f\n",moldyn->dim.x);
printf(" y: %f\n",moldyn->dim.y);
printf(" z: %f\n",moldyn->dim.z);
printf(" volume: %f\n",moldyn->volume);
- printf(" visualize simulation box: %s\n",visualize?"on":"off");
+ printf(" visualize simulation box: %s\n",visualize?"yes":"no");
+ printf(" delta volume (pressure calc): %f\n",moldyn->dv);
return 0;
}
int set_pbc(t_moldyn *moldyn,u8 x,u8 y,u8 z) {
+ printf("[moldyn] periodic boundary conditions:\n");
+
if(x)
moldyn->status|=MOLDYN_STAT_PBX;
if(z)
moldyn->status|=MOLDYN_STAT_PBZ;
+ printf(" x: %s\n",x?"yes":"no");
+ printf(" y: %s\n",y?"yes":"no");
+ printf(" z: %s\n",z?"yes":"no");
+
return 0;
}
return 0;
}
+
+int moldyn_set_report(t_moldyn *moldyn,char *author,char *title) {
+
+ strncpy(moldyn->rauthor,author,63);
+ strncpy(moldyn->rtitle,title,63);
+
+ return 0;
+}
int moldyn_set_log(t_moldyn *moldyn,u8 type,int timer) {
char filename[128];
int ret;
+ printf("[moldyn] set log: ");
+
switch(type) {
case LOG_TOTAL_ENERGY:
moldyn->ewrite=timer;
return moldyn->efd;
}
dprintf(moldyn->efd,"# total energy log file\n");
+ printf("total energy (%d)\n",timer);
break;
case LOG_TOTAL_MOMENTUM:
moldyn->mwrite=timer;
return moldyn->mfd;
}
dprintf(moldyn->efd,"# total momentum log file\n");
+ printf("total momentum (%d)\n",timer);
break;
case SAVE_STEP:
moldyn->swrite=timer;
+ printf("save file (%d)\n",timer);
break;
case VISUAL_STEP:
moldyn->vwrite=timer;
printf("[moldyn] visual init failure\n");
return ret;
}
+ printf("visual file (%d)\n",timer);
+ break;
+ case CREATE_REPORT:
+ snprintf(filename,127,"%s/report.tex",moldyn->vlsdir);
+ moldyn->rfd=open(filename,
+ O_WRONLY|O_CREAT|O_EXCL,
+ S_IRUSR|S_IWUSR);
+ if(moldyn->rfd<0) {
+ perror("[moldyn] report fd open");
+ return moldyn->rfd;
+ }
+ snprintf(filename,127,"%s/plot.scr",moldyn->vlsdir);
+ moldyn->pfd=open(filename,
+ O_WRONLY|O_CREAT|O_EXCL,
+ S_IRUSR|S_IWUSR);
+ if(moldyn->pfd<0) {
+ perror("[moldyn] plot fd open");
+ return moldyn->pfd;
+ }
+ dprintf(moldyn->rfd,report_start,
+ moldyn->rauthor,moldyn->rtitle);
+ dprintf(moldyn->pfd,plot_script);
+ close(moldyn->pfd);
break;
default:
- printf("[moldyn] unknown log mechanism: %02x\n",type);
+ printf("unknown log type: %02x\n",type);
return -1;
}
int moldyn_log_shutdown(t_moldyn *moldyn) {
+ char sc[256];
+
printf("[moldyn] log shutdown\n");
if(moldyn->efd) close(moldyn->efd);
if(moldyn->mfd) close(moldyn->mfd);
+ if(moldyn->rfd) {
+ dprintf(moldyn->rfd,report_end);
+ close(moldyn->rfd);
+ snprintf(sc,255,"cd %s && gnuplot plot.scr",moldyn->vlsdir);
+ system(sc);
+ snprintf(sc,255,"cd %s && pdflatex report",moldyn->vlsdir);
+ system(sc);
+ snprintf(sc,255,"cd %s && pdflatex report",moldyn->vlsdir);
+ system(sc);
+ snprintf(sc,255,"cd %s && dvipdf report",moldyn->vlsdir);
+ system(sc);
+ }
if(&(moldyn->vis)) visual_tini(&(moldyn->vis));
return 0;
count=moldyn->count;
/* how many atoms do we expect */
+ if(type==CUBIC) new*=1;
if(type==FCC) new*=4;
if(type==DIAMOND) new*=8;
v3_zero(&origin);
switch(type) {
+ case CUBIC:
+ ret=cubic_init(a,b,c,lc,atom,NULL);
+ break;
case FCC:
- ret=fcc_init(a,b,c,lc,atom,&origin);
+ ret=fcc_init(a,b,c,lc,atom,NULL);
break;
case DIAMOND:
ret=diamond_init(a,b,c,lc,atom,&origin);
return ret;
}
+/* cubic init */
+int cubic_init(int a,int b,int c,double lc,t_atom *atom,t_3dvec *origin) {
+
+ int count;
+ t_3dvec r;
+ int i,j,k;
+ t_3dvec o;
+
+ count=0;
+ if(origin)
+ v3_copy(&o,origin);
+ else
+ v3_zero(&o);
+
+ r.x=o.x;
+ for(i=0;i<a;i++) {
+ r.y=o.y;
+ for(j=0;j<b;j++) {
+ for(k=0;k<c;k++) {
+ r.z=o.z;
+ v3_copy(&(atom[count].r),&r);
+ count+=1;
+ r.z+=lc;
+ }
+ r.y+=lc;
+ }
+ r.x+=lc;
+ }
+
+ for(i=0;i<count;i++) {
+ atom[i].r.x-=(a*lc)/2.0;
+ atom[i].r.y-=(b*lc)/2.0;
+ atom[i].r.z-=(c*lc)/2.0;
+ }
+
+ return count;
+}
+
/* fcc lattice init */
int fcc_init(int a,int b,int c,double lc,t_atom *atom,t_3dvec *origin) {
atom=moldyn->atom;
random=&(moldyn->random);
+ printf("[moldyn] thermal init (equi init: %s)\n",equi_init?"yes":"no");
+
/* gaussian distribution of velocities */
v3_zero(&p_total);
for(i=0;i<moldyn->count;i++) {
return 0;
}
+double temperature_calc(t_moldyn *moldyn) {
+
+ double double_ekin;
+ int i;
+ t_atom *atom;
+
+ atom=moldyn->atom;
+
+ double_ekin=0;
+ for(i=0;i<moldyn->count;i++)
+ double_ekin+=atom[i].mass*v3_absolute_square(&(atom[i].v));
+
+ /* kinetic energy = 3/2 N k_B T */
+ moldyn->t=double_ekin/(3.0*K_BOLTZMANN*moldyn->count);
+
+ return moldyn->t;
+}
+
+double get_temperature(t_moldyn *moldyn) {
+
+ return moldyn->t;
+}
+
int scale_velocity(t_moldyn *moldyn,u8 equi_init) {
int i;
count=0;
for(i=0;i<moldyn->count;i++) {
if((equi_init&TRUE)||(atom[i].attr&ATOM_ATTR_HB)) {
- e+=0.5*atom[i].mass*v3_absolute_square(&(atom[i].v));
+ e+=atom[i].mass*v3_absolute_square(&(atom[i].v));
count+=1;
}
}
+ e*=0.5;
if(count!=0) moldyn->t=e/(1.5*count*K_BOLTZMANN);
else return 0; /* no atoms involved in scaling! */
return 0;
}
+double ideal_gas_law_pressure(t_moldyn *moldyn) {
+
+ double p;
+
+ p=moldyn->count*moldyn->t*K_BOLTZMANN/moldyn->volume;
+
+ return p;
+}
+
+double pressure_calc(t_moldyn *moldyn) {
+
+ int i;
+ double v;
+ t_virial *virial;
+
+ v=0.0;
+ for(i=0;i<moldyn->count;i++) {
+ virial=&(moldyn->atom[i].virial);
+ v+=(virial->xx+virial->yy+virial->zz);
+ }
+ v*=ONE_THIRD;
+printf("kieck mal: %f %f %f\n",v,moldyn->count*K_BOLTZMANN*moldyn->t,v/moldyn->count);
+
+ moldyn->p=moldyn->count*K_BOLTZMANN*moldyn->t+v;
+ moldyn->p/=moldyn->volume;
+
+ return moldyn->p;
+}
+
+double thermodynamic_pressure_calc(t_moldyn *moldyn) {
+
+ t_3dvec dim,*tp;
+ double u,p;
+ double scale;
+ t_atom *store;
+
+ tp=&(moldyn->tp);
+ store=malloc(moldyn->count*sizeof(t_atom));
+ if(store==NULL) {
+ printf("[moldyn] allocating store mem failed\n");
+ return -1;
+ }
+
+ /* 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=1.0+moldyn->dv/(moldyn->dim.y*moldyn->dim.z);
+ scale_dim(moldyn,scale,TRUE,0,0);
+ scale_atoms(moldyn,scale,TRUE,0,0);
+ link_cell_shutdown(moldyn);
+ link_cell_init(moldyn);
+ potential_force_calc(moldyn);
+ tp->x=(moldyn->energy-u)/moldyn->dv;
+ p=tp->x*tp->x;
+
+ /* restore atomic configuration + dim */
+ memcpy(moldyn->atom,store,moldyn->count*sizeof(t_atom));
+ moldyn->dim=dim;
+
+ /* derivative with respect to y direction */
+ scale=1.0+moldyn->dv/(moldyn->dim.x*moldyn->dim.z);
+ scale_dim(moldyn,scale,0,TRUE,0);
+ scale_atoms(moldyn,scale,0,TRUE,0);
+ link_cell_shutdown(moldyn);
+ link_cell_init(moldyn);
+ potential_force_calc(moldyn);
+ tp->y=(moldyn->energy-u)/moldyn->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=1.0+moldyn->dv/(moldyn->dim.x*moldyn->dim.y);
+ scale_dim(moldyn,scale,0,0,TRUE);
+ scale_atoms(moldyn,scale,0,0,TRUE);
+ link_cell_shutdown(moldyn);
+ link_cell_init(moldyn);
+ potential_force_calc(moldyn);
+ tp->z=(moldyn->energy-u)/moldyn->dv;
+ p+=tp->z*tp->z;
+
+ /* restore atomic configuration + dim */
+ memcpy(moldyn->atom,store,moldyn->count*sizeof(t_atom));
+ moldyn->dim=dim;
+
+ printf("dU/dV komp addiert = %f %f %f\n",tp->x,tp->y,tp->z);
+
+ scale=1.0+pow(moldyn->dv/moldyn->volume,ONE_THIRD);
+
+printf("debug: %f %f\n",moldyn->atom[0].r.x,moldyn->dim.x);
+ scale_dim(moldyn,scale,1,1,1);
+ scale_atoms(moldyn,scale,1,1,1);
+ link_cell_shutdown(moldyn);
+ link_cell_init(moldyn);
+ potential_force_calc(moldyn);
+printf("debug: %f %f\n",moldyn->atom[0].r.x,moldyn->dim.x);
+
+ printf("dU/dV einfach = %f\n",((moldyn->energy-u)/moldyn->dv)/ATM);
+
+ /* restore atomic configuration + dim */
+ memcpy(moldyn->atom,store,moldyn->count*sizeof(t_atom));
+ moldyn->dim=dim;
+
+ /* restore energy */
+ moldyn->energy=u;
+
+ link_cell_shutdown(moldyn);
+ link_cell_init(moldyn);
+
+ return sqrt(p);
+}
+
+double get_pressure(t_moldyn *moldyn) {
+
+ return moldyn->p;
+
+}
+
+int scale_dim(t_moldyn *moldyn,double scale,u8 x,u8 y,u8 z) {
+
+ t_3dvec *dim;
+
+ dim=&(moldyn->dim);
+
+ 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 i;
+ t_3dvec *r;
+
+ for(i=0;i<moldyn->count;i++) {
+ r=&(moldyn->atom[i].r);
+ if(x) r->x*=scale;
+ if(y) r->y*=scale;
+ if(z) r->z*=scale;
+ }
+
+ return 0;
+}
+
int scale_volume(t_moldyn *moldyn) {
t_atom *atom;
}
/* just a guess so far ... */
- v=sqrt(virial.xx*virial.xx+virial.yy*virial.yy+virial.zz+virial.zz);
+ v=virial.xx+virial.yy+virial.zz;
printf("%f\n",v);
/* get pressure from virial */
- moldyn->p=moldyn->count*K_BOLTZMANN*moldyn->t-ONE_THIRD*v;
+ moldyn->p=moldyn->count*K_BOLTZMANN*moldyn->t+ONE_THIRD*v;
moldyn->p/=moldyn->volume;
-printf("%f\n",moldyn->p/(ATM));
+printf("%f | %f\n",moldyn->p/(ATM),moldyn->p_ref/ATM);
/* scale factor */
if(moldyn->pt_scale&P_SCALE_BERENDSEN)
return moldyn->ekin;
}
-double get_e_pot(t_moldyn *moldyn) {
-
- return moldyn->energy;
-}
-
double update_e_kin(t_moldyn *moldyn) {
return(get_e_kin(moldyn));
lc->cells=lc->nx*lc->ny*lc->nz;
lc->subcell=malloc(lc->cells*sizeof(t_list));
+ if(lc->cells<27)
+ printf("[moldyn] FATAL: less then 27 subcells!\n");
+
printf("[moldyn] initializing linked cells (%d)\n",lc->cells);
for(i=0;i<lc->cells;i++)
schedule->tau=ptr;
schedule->tau[count-1]=tau;
+ printf("[moldyn] schedule added:\n");
+ printf(" number: %d | runs: %d | tau: %f\n",count-1,runs,tau);
+
+
return 0;
}
-int moldyn_set_schedule_hook(t_moldyn *moldyn,void *hook,void *hook_params) {
+int moldyn_set_schedule_hook(t_moldyn *moldyn,set_hook hook,void *hook_params) {
moldyn->schedule.hook=hook;
moldyn->schedule.hook_params=hook_params;
int fd;
char dir[128];
double ds;
+ double energy_scale;
sched=&(moldyn->schedule);
atom=moldyn->atom;
moldyn->tau_square=moldyn->tau*moldyn->tau;
moldyn->cutoff_square=moldyn->cutoff*moldyn->cutoff;
+ /* energy scaling factor */
+ energy_scale=moldyn->count*EV;
+
/* calculate initial forces */
potential_force_calc(moldyn);
/* debugging, ignore */
moldyn->debug=0;
+ /* tell the world */
+ printf("[moldyn] integration start, go get a coffee ...\n");
+
/* executing the schedule */
for(sched->count=0;sched->count<sched->total_sched;sched->count++) {
if(moldyn->pt_scale&(P_SCALE_BERENDSEN|P_SCALE_DIRECT))
scale_volume(moldyn);
+ temperature_calc(moldyn);
+ pressure_calc(moldyn);
+ //thermodynamic_pressure_calc(moldyn);
+
/* check for log & visualization */
if(e) {
if(!(i%e))
+ update_e_kin(moldyn);
dprintf(moldyn->efd,
"%f %f %f %f\n",
- moldyn->time,update_e_kin(moldyn),
- moldyn->energy,
- get_total_energy(moldyn));
+ moldyn->time,moldyn->ekin/energy_scale,
+ moldyn->energy/energy_scale,
+ get_total_energy(moldyn)/energy_scale);
}
if(m) {
if(!(i%m)) {
if(!(i%v)) {
visual_atoms(&(moldyn->vis),moldyn->time,
moldyn->atom,moldyn->count);
- printf("\rsched: %d, steps: %d, debug: %d",
- sched->count,i,moldyn->debug);
+ printf("\rsched: %d, steps: %d, debug: %f | %f",
+ sched->count,i,moldyn->p/ATM,moldyn->debug/ATM);
fflush(stdout);
}
}
int velocity_verlet(t_moldyn *moldyn) {
int i,count;
- double tau,tau_square;
+ double tau,tau_square,h;
t_3dvec delta;
t_atom *atom;
for(i=0;i<count;i++) {
/* new positions */
+ h=0.5/atom[i].mass;
v3_scale(&delta,&(atom[i].v),tau);
v3_add(&(atom[i].r),&(atom[i].r),&delta);
- v3_scale(&delta,&(atom[i].f),0.5*tau_square/atom[i].mass);
+ v3_scale(&delta,&(atom[i].f),h*tau_square);
v3_add(&(atom[i].r),&(atom[i].r),&delta);
check_per_bound(moldyn,&(atom[i].r));
- /* velocities */
- v3_scale(&delta,&(atom[i].f),0.5*tau/atom[i].mass);
+ /* velocities [actually v(t+tau/2)] */
+ v3_scale(&delta,&(atom[i].f),h*tau);
v3_add(&(atom[i].v),&(atom[i].v),&delta);
}
potential_force_calc(moldyn);
for(i=0;i<count;i++) {
- /* again velocities */
+ /* again velocities [actually v(t+tau)] */
v3_scale(&delta,&(atom[i].f),0.5*tau/atom[i].mass);
v3_add(&(atom[i].v),&(atom[i].v),&delta);
}
/*
*
- * potentials & corresponding forces
+ * potentials & corresponding forces & virial routine
*
*/
/* reset energy */
moldyn->energy=0.0;
-
- /* get energy and force of every atom */
+
+ /* reset force, site energy and virial of every atom */
for(i=0;i<count;i++) {
/* reset force */
v3_zero(&(itom[i].f));
- /* reset viral of atom i */
- virial=&(itom[i].virial);
+ /* reset virial */
+ virial=(&(itom[i].virial));
virial->xx=0.0;
virial->yy=0.0;
virial->zz=0.0;
virial->xy=0.0;
virial->xz=0.0;
virial->yz=0.0;
-
+
/* reset site energy */
itom[i].e=0.0;
+ }
+
+ /* get energy,force and virial of every atom */
+ for(i=0;i<count;i++) {
+
/* single particle potential/force */
if(itom[i].attr&ATOM_ATTR_1BP)
moldyn->func1b(moldyn,&(itom[i]));
}
}
+
#ifdef DEBUG
printf("\n\n");
+#endif
+#ifdef VDEBUG
+printf("\n\n");
#endif
return 0;
}
+/*
+ * virial calculation
+ */
+
+inline int virial_calc(t_atom *a,t_3dvec *f,t_3dvec *d) {
+
+ a->virial.xx+=f->x*d->x;
+ a->virial.yy+=f->y*d->y;
+ a->virial.zz+=f->z*d->z;
+ a->virial.xy+=f->x*d->y;
+ a->virial.xz+=f->x*d->z;
+ a->virial.yz+=f->y*d->z;
+
+ return 0;
+}
+
/*
* periodic boundayr checking
*/
t_ho_params *params;
t_3dvec force,distance;
- double d;
+ double d,f;
double sc,equi_dist;
params=moldyn->pot2b_params;
sc=params->spring_constant;
equi_dist=params->equilibrium_distance;
+ if(ai<aj) return 0;
+
v3_sub(&distance,&(aj->r),&(ai->r));
if(bc) check_per_bound(moldyn,&distance);
d=v3_norm(&distance);
if(d<=moldyn->cutoff) {
- /* energy is 1/2 (d-d0)^2, but we will add this twice ... */
- moldyn->energy+=(0.25*sc*(d-equi_dist)*(d-equi_dist));
+ moldyn->energy+=(0.5*sc*(d-equi_dist)*(d-equi_dist));
/* f = -grad E; grad r_ij = -1 1/r_ij distance */
- v3_scale(&force,&distance,sc*(1.0-(equi_dist/d)));
+ f=sc*(1.0-equi_dist/d);
+ v3_scale(&force,&distance,f);
v3_add(&(ai->f),&(ai->f),&force);
+ virial_calc(ai,&force,&distance);
+ virial_calc(aj,&force,&distance); /* f and d signe switched */
+ v3_scale(&force,&distance,-f);
+ v3_add(&(aj->f),&(aj->f),&force);
}
return 0;
sig6=params->sigma6;
sig12=params->sigma12;
+ if(ai<aj) return 0;
+
v3_sub(&distance,&(aj->r),&(ai->r));
if(bc) check_per_bound(moldyn,&distance);
d=v3_absolute_square(&distance); /* 1/r^2 */
h2=d*d; /* 1/r^4 */
h2*=d; /* 1/r^6 */
h1=h2*h2; /* 1/r^12 */
- /* energy is eps*..., but we will add this twice ... */
- moldyn->energy+=0.5*eps*(sig12*h1-sig6*h2);
+ moldyn->energy+=(eps*(sig12*h1-sig6*h2)-params->uc);
h2*=d; /* 1/r^8 */
h1*=d; /* 1/r^14 */
h2*=6*sig6;
h1*=12*sig12;
d=+h1-h2;
d*=eps;
+ v3_scale(&force,&distance,d);
+ v3_add(&(aj->f),&(aj->f),&force);
v3_scale(&force,&distance,-1.0*d); /* f = - grad E */
v3_add(&(ai->f),&(ai->f),&force);
+ virial_calc(ai,&force,&distance);
+ virial_calc(aj,&force,&distance); /* f and d signe switched */
}
return 0;
/* save for use in 3bp */
exchange->d_ij=d_ij;
+ exchange->d_ij2=d_ij2;
exchange->dist_ij=dist_ij;
/* more constants */
/* add forces of 2bp (ij, ji) contribution
* dVij = dVji and we sum up both: no 1/2) */
v3_add(&(ai->f),&(ai->f),&force);
+
+ /* virial */
+ ai->virial.xx-=force.x*dist_ij.x;
+ ai->virial.yy-=force.y*dist_ij.y;
+ ai->virial.zz-=force.z*dist_ij.z;
+ ai->virial.xy-=force.x*dist_ij.y;
+ ai->virial.xz-=force.x*dist_ij.z;
+ ai->virial.yz-=force.y*dist_ij.z;
+
#ifdef DEBUG
if(ai==&(moldyn->atom[0])) {
printf("dVij, dVji (2bp) contrib:\n");
printf("%f | %f\n",force.y,ai->f.y);
printf("%f | %f\n",force.z,ai->f.z);
}
+#endif
+#ifdef VDEBUG
+if(ai==&(moldyn->atom[0])) {
+ printf("dVij, dVji (2bp) contrib:\n");
+ printf("%f | %f\n",force.x*dist_ij.x,ai->virial.xx);
+ printf("%f | %f\n",force.y*dist_ij.y,ai->virial.yy);
+ printf("%f | %f\n",force.z*dist_ij.z,ai->virial.zz);
+}
#endif
/* energy 2bp contribution (ij, ji) is 0.5 f_r f_c ... */
zeta=exchange->zeta_ij;
if(zeta==0.0) {
moldyn->debug++; /* just for debugging ... */
- db=0.0;
b=chi;
v3_scale(&force,dist_ij,df_a*b*f_c);
}
/* add force */
v3_add(&(ai->f),&(ai->f),&force);
+
+ /* virial */
+ ai->virial.xx-=force.x*dist_ij->x;
+ ai->virial.yy-=force.y*dist_ij->y;
+ ai->virial.zz-=force.z*dist_ij->z;
+ ai->virial.xy-=force.x*dist_ij->y;
+ ai->virial.xz-=force.x*dist_ij->z;
+ ai->virial.yz-=force.y*dist_ij->z;
+
#ifdef DEBUG
if(ai==&(moldyn->atom[0])) {
printf("dVij (3bp) contrib:\n");
printf("%f | %f\n",force.y,ai->f.y);
printf("%f | %f\n",force.z,ai->f.z);
}
+#endif
+#ifdef VDEBUG
+if(ai==&(moldyn->atom[0])) {
+ printf("dVij (3bp) contrib:\n");
+ printf("%f | %f\n",force.x*dist_ij->x,ai->virial.xx);
+ printf("%f | %f\n",force.y*dist_ij->y,ai->virial.yy);
+ printf("%f | %f\n",force.z*dist_ij->z,ai->virial.zz);
+}
#endif
/* add energy of 3bp sum */
/* add force */
v3_add(&(ai->f),&(ai->f),&force);
+
+ /* virial - plus sign, as dist_ij = - dist_ji - (really??) */
+// TEST ... with a minus instead
+ ai->virial.xx-=force.x*dist_ij->x;
+ ai->virial.yy-=force.y*dist_ij->y;
+ ai->virial.zz-=force.z*dist_ij->z;
+ ai->virial.xy-=force.x*dist_ij->y;
+ ai->virial.xz-=force.x*dist_ij->z;
+ ai->virial.yz-=force.y*dist_ij->z;
+
#ifdef DEBUG
if(ai==&(moldyn->atom[0])) {
printf("dVji (3bp) contrib:\n");
printf("%f | %f\n",force.y,ai->f.y);
printf("%f | %f\n",force.z,ai->f.z);
}
+#endif
+#ifdef VDEBUG
+if(ai==&(moldyn->atom[0])) {
+ printf("dVji (3bp) contrib:\n");
+ printf("%f | %f\n",force.x*dist_ij->x,ai->virial.xx);
+ printf("%f | %f\n",force.y*dist_ij->y,ai->virial.yy);
+ printf("%f | %f\n",force.z*dist_ij->z,ai->virial.zz);
+}
#endif
return 0;
t_3dvec dist_ij,dist_ik,dist_jk;
t_3dvec temp1,temp2;
t_3dvec *dzeta;
- double R,S,s_r;
+ double R,S,S2,s_r;
double B,mu;
- double d_ij,d_ik,d_jk;
+ double d_ij,d_ik,d_jk,d_ij2,d_ik2,d_jk2;
double rr,dd;
double f_c,df_c;
double f_c_ik,df_c_ik,arg;
/* dist_ij, d_ij - this is < S_ij ! */
dist_ij=exchange->dist_ij;
d_ij=exchange->d_ij;
+ d_ij2=exchange->d_ij2;
/* f_c_ij, df_c_ij (same for ji) */
f_c=exchange->f_c;
/* dist_ik, d_ik */
v3_sub(&dist_ik,&(ak->r),&(ai->r));
if(bc) check_per_bound(moldyn,&dist_ik);
- d_ik=v3_norm(&dist_ik);
+ d_ik2=v3_absolute_square(&dist_ik);
/* ik constants */
brand=ai->brand;
if(brand==ak->brand) {
R=params->R[brand];
S=params->S[brand];
+ S2=params->S2[brand];
}
else {
R=params->Rmixed;
S=params->Smixed;
+ S2=params->S2mixed;
}
/* zeta_ij/dzeta_ij contribution only for d_ik < S */
- if(d_ik<S) {
+ if(d_ik2<S2) {
+
+ /* now we need d_ik */
+ d_ik=sqrt(d_ik2);
/* get constants_i from exchange data */
n=*(exchange->n_i);
/* d_costheta */
tmp=1.0/dd;
- d_costheta1=cos_theta/(d_ij*d_ij)-tmp;
- d_costheta2=cos_theta/(d_ik*d_ik)-tmp;
+ d_costheta1=cos_theta/d_ij2-tmp;
+ d_costheta2=cos_theta/d_ik2-tmp;
/* some usefull values */
h_cos=(h-cos_theta);
/* dist_jk, d_jk */
v3_sub(&dist_jk,&(ak->r),&(aj->r));
if(bc) check_per_bound(moldyn,&dist_jk);
- d_jk=v3_norm(&dist_jk);
+ d_jk2=v3_absolute_square(&dist_jk);
/* jk constants */
brand=aj->brand;
if(brand==ak->brand) {
R=params->R[brand];
S=params->S[brand];
+ S2=params->S2[brand];
B=params->B[brand];
mu=params->mu[brand];
chi=1.0;
else {
R=params->Rmixed;
S=params->Smixed;
+ S2=params->S2mixed;
B=params->Bmixed;
mu=params->mu_m;
chi=params->chi;
}
/* zeta_ji/dzeta_ji contribution only for d_jk < S_jk */
- if(d_jk<S) {
+ if(d_jk2<S2) {
+
+ /* now we need d_ik */
+ d_jk=sqrt(d_jk2);
/* constants_j from exchange data */
n=*(exchange->n_j);
/* d_costheta */
d_costheta1=1.0/dd;
- d_costheta2=cos_theta/(d_ij*d_ij);
+ d_costheta2=cos_theta/d_ij2;
/* some usefull values */
h_cos=(h-cos_theta);
/* g(cos_theta) */
g=1.0+c2d2-frac;
- /* d_costheta_ij and dg(cos_theta) - needed in any case! */
+ /* d_costheta_jik and dg(cos_theta) - needed in any case! */
v3_scale(&temp1,&dist_jk,d_costheta1);
v3_scale(&temp2,&dist_ij,-d_costheta2); /* ji -> ij => -1 */
- v3_add(&temp1,&temp1,&temp2);
+ //v3_add(&temp1,&temp1,&temp2);
+ v3_sub(&temp1,&temp1,&temp2); /* there is a minus! */
v3_scale(&temp1,&temp1,-2.0*frac*h_cos/d2_h_cos2); /* dg */
/* store dg in temp2 and use it for dVjk later */
v3_scale(&temp2,&temp2,tmp*B*exp(-mu*d_jk)*f_c_jk*0.5);
v3_add(&(ai->f),&(ai->f),&temp2); /* -1 skipped in f_a calc ^ */
/* scaled with 0.5 ^ */
+
+ /* virial */
+ ai->virial.xx-=temp2.x*dist_jk.x;
+ ai->virial.yy-=temp2.y*dist_jk.y;
+ ai->virial.zz-=temp2.z*dist_jk.z;
+ ai->virial.xy-=temp2.x*dist_jk.y;
+ ai->virial.xz-=temp2.x*dist_jk.z;
+ ai->virial.yz-=temp2.y*dist_jk.z;
+
#ifdef DEBUG
if(ai==&(moldyn->atom[0])) {
printf("dVjk (3bp) contrib:\n");
printf("%f | %f\n",temp2.y,ai->f.y);
printf("%f | %f\n",temp2.z,ai->f.z);
}
+#endif
+#ifdef VDEBUG
+if(ai==&(moldyn->atom[0])) {
+ printf("dVjk (3bp) contrib:\n");
+ printf("%f | %f\n",temp2.x*dist_jk.x,ai->virial.xx);
+ printf("%f | %f\n",temp2.y*dist_jk.y,ai->virial.yy);
+ printf("%f | %f\n",temp2.z*dist_jk.z,ai->virial.zz);
+}
#endif
}