basic linked list / cell method support implemented
[physik/posic.git] / moldyn.c
index 7f9745a..dbb3e6c 100644 (file)
--- a/moldyn.c
+++ b/moldyn.c
@@ -21,6 +21,7 @@
 #include "init/init.h"
 #include "random/random.h"
 #include "visual/visual.h"
+#include "list/list.h"
 
 int moldyn_usage(char **argv) {
 
@@ -338,6 +339,144 @@ double estimate_time_step(t_moldyn *moldyn,double nn_dist,double t) {
        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;
+}
 
 /*
  *
@@ -352,25 +491,40 @@ int moldyn_integrate(t_moldyn *moldyn) {
        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);
 
@@ -423,7 +577,7 @@ int moldyn_integrate(t_moldyn *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;
 
@@ -437,10 +591,20 @@ int velocity_verlet(t_moldyn *moldyn) {
                /* 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);
@@ -536,8 +700,8 @@ int force_harmonic_oscillator(t_moldyn *moldyn) {
 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;
@@ -553,13 +717,19 @@ double potential_lennard_jones(t_moldyn *moldyn) {
 
        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;
                }
        }
        
@@ -569,8 +739,8 @@ double potential_lennard_jones(t_moldyn *moldyn) {
 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;
@@ -586,8 +756,11 @@ int force_lennard_jones(t_moldyn *moldyn) {
        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) {
@@ -604,8 +777,10 @@ int force_lennard_jones(t_moldyn *moldyn) {
                                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;
                }
        }