#include "init/init.h"
#include "random/random.h"
#include "visual/visual.h"
+#include "list/list.h"
int moldyn_usage(char **argv) {
return tau;
}
+/*
+ * numerical tricks
+ */
+
+/* verlet list */
+
+int verlet_list_init(t_moldyn *moldyn) {
+
+ int i,fd;
+
+ fd=open("/dev/null",O_WRONLY);
+
+ for(i=0;i<moldyn->count;i++)
+ list_init(&(moldyn->atom[i].verlet),fd);
+
+ moldyn->r_verlet=1.1*moldyn->cutoff;
+ /* +moldyn->tau*\
+ sqrt(3.0*K_BOLTZMANN*moldyn->t/moldyn->atom[0].mass); */
+
+ printf("debug: r verlet = %.15f\n",moldyn->r_verlet);
+ printf(" r cutoff = %.15f\n",moldyn->cutoff);
+ printf(" dim = %.15f\n",moldyn->dim.x);
+
+ /* make sure to update the list in the beginning */
+ moldyn->dr_max1=moldyn->r_verlet;
+ moldyn->dr_max2=moldyn->r_verlet;
+
+ return 0;
+}
+
+int link_cell_init(t_moldyn *moldyn) {
+
+ t_linkcell *lc;
+
+ lc=&(moldyn->lc);
+
+ /* partitioning the md cell */
+ lc->nx=moldyn->dim.x/moldyn->cutoff;
+ lc->x=moldyn->dim.x/lc->nx;
+ lc->ny=moldyn->dim.y/moldyn->cutoff;
+ lc->y=moldyn->dim.y/lc->ny;
+ lc->nz=moldyn->dim.z/moldyn->cutoff;
+ lc->z=moldyn->dim.z/lc->nz;
+
+ lc->subcell=malloc(lc->nx*lc->ny*lc->nz*sizeof(t_list));
+
+ link_cell_update(moldyn);
+
+ return 0;
+}
+
+int verlet_list_update(t_moldyn *moldyn) {
+
+ int i,j;
+ t_3dvec d;
+ t_atom *atom;
+
+ atom=moldyn->atom;
+
+ puts("debug: list update start");
+
+ for(i=0;i<moldyn->count;i++) {
+ list_destroy(&(atom[i].verlet));
+ for(j=0;j<moldyn->count;j++) {
+ if(i!=j) {
+ v3_sub(&d,&(atom[i].r),&(atom[j].r));
+ v3_per_bound(&d,&(moldyn->dim));
+ if(v3_norm(&d)<=moldyn->r_verlet)
+ list_add_immediate_ptr(&(atom[i].verlet),&(atom[j]));
+ }
+ }
+ }
+
+ moldyn->dr_max1=0.0;
+ moldyn->dr_max2=0.0;
+
+ puts("debug: list update end");
+
+ return 0;
+}
+
+int link_cell_update(t_moldyn *moldyn) {
+
+ int count,i,j,k;
+ int nx,ny,nz;
+ t_atom *atom;
+
+ atom=moldyn->atom;
+ nx=moldyn->lc.nx; ny=moldyn->lc.ny; nz=moldyn->lc.nz;
+
+ for(i=0;i<nx*ny*nz;i++)
+ list_destroy(&(moldyn->lc.subcell[i]));
+
+ for(count=0;count<moldyn->count;count++) {
+ for(i=0;i<nx;i++) {
+ if((atom[count].r.x>=i*moldyn->dim.x) && \
+ (atom[count].r.x<(i+1)*moldyn->dim.x))
+ break;
+ }
+ for(j=0;j<ny;j++) {
+ if((atom[count].r.y>=j*moldyn->dim.y) && \
+ (atom[count].r.y<(j+1)*moldyn->dim.y))
+ break;
+ }
+ for(k=0;k<nz;k++) {
+ if((atom[count].r.z>=k*moldyn->dim.z) && \
+ (atom[count].r.z<(k+1)*moldyn->dim.z))
+ break;
+ }
+ list_add_immediate_ptr(&(moldyn->lc.subcell[i+j*nx+k*nx*ny]),
+ &(atom[count]));
+ }
+
+ return 0;
+}
+
+int verlet_list_shutdown(t_moldyn *moldyn) {
+
+ int i;
+
+ for(i=0;i<moldyn->count;i++)
+ list_shutdown(&(moldyn->atom[i].verlet));
+
+ return 0;
+}
+
+int link_cell_shutdown(t_moldyn *moldyn) {
+
+ int i;
+ t_linkcell *lc;
+
+ lc=&(moldyn->lc);
+
+ for(i=0;i<lc->nx*lc->ny*lc->nz;i++)
+ list_shutdown(&(moldyn->lc.subcell[i]));
+
+ return 0;
+}
/*
*
int i;
unsigned int e,m,s,d,v;
t_3dvec p;
+ double rlc;
int fd;
char fb[128];
+ /* logging & visualization */
e=moldyn->ewrite;
m=moldyn->mwrite;
s=moldyn->swrite;
d=moldyn->dwrite;
v=moldyn->vwrite;
+ /* verlet list */
+ rlc=moldyn->r_verlet-moldyn->cutoff;
+
if(!(moldyn->lvstat&MOLDYN_LVSTAT_INITIALIZED)) {
printf("[moldyn] warning, lv system not initialized\n");
return -1;
}
+ /* create the verlet list */
+ verlet_list_update(moldyn);
+
/* calculate initial forces */
moldyn->force(moldyn);
for(i=0;i<moldyn->time_steps;i++) {
+ /* check for velet list update */
+ printf(".");
+ if(moldyn->dr_max1+moldyn->dr_max2>rlc) {
+ printf("\n");
+ verlet_list_update(moldyn);
+ }
+
/* integration step */
moldyn->integrate(moldyn);
int velocity_verlet(t_moldyn *moldyn) {
int i,count;
- double tau,tau_square;
+ double tau,tau_square,dr;
t_3dvec delta;
t_atom *atom;
/* new positions */
v3_scale(&delta,&(atom[i].v),tau);
v3_add(&(atom[i].r),&(atom[i].r),&delta);
+ v3_add(&(atom[i].dr),&(atom[i].dr),&delta);
v3_scale(&delta,&(atom[i].f),0.5*tau_square/atom[i].mass);
v3_add(&(atom[i].r),&(atom[i].r),&delta);
+ v3_add(&(atom[i].dr),&(atom[i].dr),&delta);
v3_per_bound(&(atom[i].r),&(moldyn->dim));
+ /* set maximum dr (possible list update) */
+ dr=v3_norm(&(atom[i].dr));
+ if(dr>moldyn->dr_max1) {
+ moldyn->dr_max2=moldyn->dr_max1;
+ moldyn->dr_max1=dr;
+ }
+ else if(dr>moldyn->dr_max2) moldyn->dr_max2=dr;
+
/* velocities */
v3_scale(&delta,&(atom[i].f),0.5*tau/atom[i].mass);
v3_add(&(atom[i].v),&(atom[i].v),&delta);
double potential_lennard_jones(t_moldyn *moldyn) {
t_lj_params *params;
- t_atom *atom;
- int i,j;
+ t_atom *atom,*btom;
+ int i;
int count;
t_3dvec distance;
double d,help;
u=0.0;
for(i=0;i<count;i++) {
- for(j=0;j<i;j++) {
- v3_sub(&distance,&(atom[i].r),&(atom[j].r));
+ list_reset(&(atom[i].verlet));
+ if(atom[i].verlet.current==NULL) continue;
+ while(1) {
+ btom=atom[i].verlet.current->data;
+ v3_sub(&distance,&(atom[i].r),&(btom->r));
+ v3_per_bound(&distance,&(moldyn->dim));
d=1.0/v3_absolute_square(&distance); /* 1/r^2 */
help=d*d; /* 1/r^4 */
help*=d; /* 1/r^6 */
d=help*help; /* 1/r^12 */
- u+=eps*(sig6*help-sig12*d);
+ u+=eps*(sig12*d-sig6*help);
+ if(list_next(&(atom[i].verlet))==L_NO_NEXT_ELEMENT)
+ break;
}
}
int force_lennard_jones(t_moldyn *moldyn) {
t_lj_params *params;
- int i,j,count;
- t_atom *atom;
+ int i,count;
+ t_atom *atom,*btom;
t_3dvec distance;
t_3dvec force;
double d,h1,h2;
for(i=0;i<count;i++) v3_zero(&(atom[i].f));
for(i=0;i<count;i++) {
- for(j=0;j<i;j++) {
- v3_sub(&distance,&(atom[i].r),&(atom[j].r));
+ list_reset(&(atom[i].verlet));
+ if(atom[i].verlet.current==NULL) continue;
+ while(1) {
+ btom=atom[i].verlet.current->data;
+ v3_sub(&distance,&(atom[i].r),&(btom->r));
v3_per_bound(&distance,&(moldyn->dim));
d=v3_absolute_square(&distance);
if(d<=moldyn->cutoff_square) {
d*=eps;
v3_scale(&force,&distance,d);
v3_add(&(atom[i].f),&(atom[i].f),&force);
- v3_sub(&(atom[j].f),&(atom[j].f),&force);
+ //v3_sub(&(atom[j].f),&(atom[j].f),&force);
}
+ if(list_next(&(atom[i].verlet))==L_NO_NEXT_ELEMENT)
+ break;
}
}
#include "math/math.h"
#include "random/random.h"
+#include "list/list.h"
/* datatypes */
t_3dvec r; /* positions */
t_3dvec v; /* velocities */
t_3dvec f; /* forces */
+ t_3dvec dr; /* delta r for verlet list updates */
int element; /* number of element in pse */
double mass; /* atom mass */
- //t_list vicinity /* verlet neighbour list */
+ t_list verlet; /* verlet neighbour list */
} t_atom;
+typedef struct s_linkcell {
+ int nx,ny,nz;
+ double x,y,z;
+ t_list *subcell;
+} t_linkcell;
+
#include "visual/visual.h"
typedef struct s_moldyn {
double (*potential)(struct s_moldyn *moldyn);
int (*force)(struct s_moldyn *moldyn);
void *pot_params;
+ /* cut off radius, verlet list & co */
double cutoff;
double cutoff_square;
+ double r_verlet;
+ double dr_max1;
+ double dr_max2;
+ /* linked list / cell method */
+ t_linkcell lc;
/* temperature */
double t;
/* integration of newtons equations */
double estimate_time_step(t_moldyn *moldyn,double nn_dist,double t);
+int verlet_list_init(t_moldyn *moldyn);
+int link_cell_init(t_moldyn *moldyn);
+int verlet_list_update(t_moldyn *moldyn);
+int link_cell_update(t_moldyn *moldyn);
+int verlet_list_shutdown(t_moldyn *moldyn);
+int link_cell_shutdown(t_moldyn *moldyn);
+
int moldyn_integrate(t_moldyn *moldyn);
int velocity_verlet(t_moldyn *moldyn);
t_random random;
int a,b,c;
- double e,u;
+ double e;
double help;
t_3dvec p;
int count;
md.force=force_lennard_jones;
//md.potential=potential_harmonic_oscillator;
//md.force=force_harmonic_oscillator;
- md.cutoff=R_CUTOFF;
- md.cutoff_square=(R_CUTOFF*R_CUTOFF);
+ md.cutoff=R_CUTOFF*LC_SI;
+ md.cutoff_square=md.cutoff*md.cutoff;
md.pot_params=&lj;
//md.pot_params=&ho;
md.integrate=velocity_verlet;
//md.tau=TAU;
md.status=0;
md.visual=&vis;
+ /* dimensions of the simulation cell */
+ md.dim.x=a*LC_SI;
+ md.dim.y=b*LC_SI;
+ md.dim.z=c*LC_SI;
+
+ /* verlet list init */
+ // later integrated in moldyn_init function!
+ verlet_list_init(&md);
printf("setting thermal fluctuations (T=%f K)\n",md.t);
thermal_init(&md,&random,count);
e=get_e_kin(si,count);
printf("kinetic energy: %.40f [J]\n",e);
- printf("3/2 N k T = %.40f [J]\n",1.5*count*K_BOLTZMANN*md.t);
+ printf("3/2 N k T = %.40f [J] (T=%f [K])\n",
+ 1.5*count*K_BOLTZMANN*md.t,md.t);
/* check total momentum */
p=get_total_p(si,count);
printf("total momentum: %.30f [Ns]\n",v3_norm(&p));
- /* check potential energy */
+ /* potential paramters */
lj.sigma6=LJ_SIGMA_SI*LJ_SIGMA_SI;
help=lj.sigma6*lj.sigma6;
lj.sigma6*=help;
ho.equilibrium_distance=0.25*sqrt(3.0)*LC_SI;
ho.spring_constant=1.0;
- u=get_e_pot(&md);
-
- printf("potential energy: %.40f [J]\n",u);
- printf("total energy (1): %.40f [J]\n",e+u);
- printf("total energy (2): %.40f [J]\n",get_total_energy(&md));
-
- md.dim.x=a*LC_SI;
- md.dim.y=b*LC_SI;
- md.dim.z=c*LC_SI;
-
printf("estimated accurate time step: %.30f [s]\n",
estimate_time_step(&md,3.0,md.t));
/* close */
+ verlet_list_shutdown(&md);
+
rand_close(&random);
moldyn_shutdown(&md);