safety ci
[physik/posic.git] / moldyn.c
index 73becde..c25fed3 100644 (file)
--- a/moldyn.c
+++ b/moldyn.c
 
 #include "moldyn.h"
 
-#include "math/math.h"
-#include "init/init.h"
-#include "random/random.h"
-#include "visual/visual.h"
-#include "list/list.h"
-
-
 int moldyn_init(t_moldyn *moldyn,int argc,char **argv) {
 
-       //int ret;
-
-       //ret=moldyn_parse_argv(moldyn,argc,argv);
-       //if(ret<0) return ret;
-
        memset(moldyn,0,sizeof(t_moldyn));
 
        rand_init(&(moldyn->random),NULL,1);
@@ -78,6 +66,13 @@ int set_temperature(t_moldyn *moldyn,double t_ref) {
        return 0;
 }
 
+int set_pressure(t_moldyn *moldyn,double p_ref) {
+
+       moldyn->p_ref=p_ref;
+
+       return 0;
+}
+
 int set_pt_scale(t_moldyn *moldyn,u8 ptype,double ptc,u8 ttype,double ttc) {
 
        moldyn->pt_scale=(ptype|ttype);
@@ -93,16 +88,19 @@ int set_dim(t_moldyn *moldyn,double x,double y,double z,u8 visualize) {
        moldyn->dim.y=y;
        moldyn->dim.z=z;
 
+       moldyn->volume=x*y*z;
+
        if(visualize) {
                moldyn->vis.dim.x=x;
                moldyn->vis.dim.y=y;
                moldyn->vis.dim.z=z;
        }
 
-       printf("[moldyn] dimensions in A:\n");
+       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");
 
        return 0;
@@ -227,6 +225,10 @@ int moldyn_log_shutdown(t_moldyn *moldyn) {
        return 0;
 }
 
+/*
+ * creating lattice functions
+ */
+
 int create_lattice(t_moldyn *moldyn,u8 type,double lc,int element,double mass,
                    u8 attr,u8 bnum,int a,int b,int c) {
 
@@ -285,6 +287,90 @@ int create_lattice(t_moldyn *moldyn,u8 type,double lc,int element,double mass,
        return ret;
 }
 
+/* fcc lattice init */
+int fcc_init(int a,int b,int c,double lc,t_atom *atom,t_3dvec *origin) {
+
+       int count;
+       int i,j;
+       t_3dvec o,r,n;
+       t_3dvec basis[3];
+       double help[3];
+       double x,y,z;
+
+       x=a*lc;
+       y=b*lc;
+       z=c*lc;
+
+       if(origin) v3_copy(&o,origin);
+       else v3_zero(&o);
+
+       /* construct the basis */
+       for(i=0;i<3;i++) {
+               for(j=0;j<3;j++) {
+                       if(i!=j) help[j]=0.5*lc;
+                       else help[j]=.0;
+               }
+               v3_set(&basis[i],help);
+       }
+
+       v3_zero(&r);
+       count=0;
+       
+       /* fill up the room */
+       r.x=o.x;
+       while(r.x<x) {
+               r.y=o.y;
+               while(r.y<y) {
+                       r.z=o.z;
+                       while(r.z<z) {
+                               v3_copy(&(atom[count].r),&r);
+                               atom[count].element=1;
+                               count+=1;
+                               for(i=0;i<3;i++) {
+                                       v3_add(&n,&r,&basis[i]);
+                                       if((n.x<x+o.x)&&
+                                          (n.y<y+o.y)&&
+                                          (n.z<z+o.z)) {
+                                               v3_copy(&(atom[count].r),&n);
+                                               count+=1;
+                                       }
+                               }
+                               r.z+=lc;        
+                       }
+                       r.y+=lc;
+               }
+               r.x+=lc;
+       }
+
+       /* coordinate transformation */
+       help[0]=x/2.0;
+       help[1]=y/2.0;
+       help[2]=z/2.0;
+       v3_set(&n,help);
+       for(i=0;i<count;i++)
+               v3_sub(&(atom[i].r),&(atom[i].r),&n);
+               
+       return count;
+}
+
+int diamond_init(int a,int b,int c,double lc,t_atom *atom,t_3dvec *origin) {
+
+       int count;
+       t_3dvec o;
+
+       count=fcc_init(a,b,c,lc,atom,origin);
+
+       o.x=0.25*lc;
+       o.y=0.25*lc;
+       o.z=0.25*lc;
+
+       if(origin) v3_add(&o,&o,origin);
+
+       count+=fcc_init(a,b,c,lc,&atom[count],&o);
+
+       return count;
+}
+
 int add_atom(t_moldyn *moldyn,int element,double mass,u8 bnum,u8 attr,
              t_3dvec *r,t_3dvec *v) {
 
@@ -390,7 +476,7 @@ int scale_velocity(t_moldyn *moldyn,u8 equi_init) {
                        count+=1;
                }
        }
-       if(count!=0) moldyn->t=(2.0*e)/(3.0*count*K_BOLTZMANN);
+       if(count!=0) moldyn->t=e/(1.5*count*K_BOLTZMANN);
        else return 0;  /* no atoms involved in scaling! */
        
        /* (temporary) hack for e,t = 0 */
@@ -423,6 +509,57 @@ int scale_velocity(t_moldyn *moldyn,u8 equi_init) {
        return 0;
 }
 
+int scale_volume(t_moldyn *moldyn) {
+
+       t_atom *atom;
+       t_3dvec *dim,*vdim;
+       double virial,scale;
+       t_linkcell *lc;
+       int i;
+
+       atom=moldyn->atom;
+       dim=&(moldyn->dim);
+       vdim=&(moldyn->vis.dim);
+       lc=&(moldyn->lc);
+
+       for(i=0;i<moldyn->count;i++)
+               virial+=v3_norm(&(atom[i].virial));
+
+printf("%f\n",virial);
+       /* get pressure from virial */
+       moldyn->p=moldyn->count*K_BOLTZMANN*moldyn->t-ONE_THIRD*virial;
+       moldyn->p/=moldyn->volume;
+printf("%f\n",moldyn->p/(ATM));
+
+       /* scale factor */
+       if(moldyn->pt_scale&P_SCALE_BERENDSEN)
+               scale=3*sqrt(1-(moldyn->p_ref-moldyn->p)/moldyn->p_tc);
+       else 
+               /* should actually never be used */
+               scale=pow(moldyn->p/moldyn->p_ref,1.0/3.0);
+
+printf("scale = %f\n",scale);
+       /* actual scaling */
+       dim->x*=scale;
+       dim->y*=scale;
+       dim->z*=scale;
+       if(vdim->x) vdim->x=dim->x;
+       if(vdim->y) vdim->y=dim->y;
+       if(vdim->z) vdim->z=dim->z;
+       moldyn->volume*=(scale*scale*scale);
+
+       /* check whether we need a new linkcell init */
+       if((dim->x/moldyn->cutoff!=lc->nx)||
+          (dim->y/moldyn->cutoff!=lc->ny)||
+          (dim->z/moldyn->cutoff!=lc->nx)) {
+               link_cell_shutdown(moldyn);
+               link_cell_init(moldyn);
+       }
+
+       return 0;
+
+}
+
 double get_e_kin(t_moldyn *moldyn) {
 
        int i;
@@ -490,9 +627,6 @@ int link_cell_init(t_moldyn *moldyn) {
 
        t_linkcell *lc;
        int i;
-       int fd;
-
-       fd=open("/dev/null",O_WRONLY);
 
        lc=&(moldyn->lc);
 
@@ -510,8 +644,7 @@ int link_cell_init(t_moldyn *moldyn) {
        printf("[moldyn] initializing linked cells (%d)\n",lc->cells);
 
        for(i=0;i<lc->cells;i++)
-               //list_init(&(lc->subcell[i]),1);
-               list_init(&(lc->subcell[i]),fd);
+               list_init_f(&(lc->subcell[i]));
 
        link_cell_update(moldyn);
        
@@ -521,26 +654,30 @@ int link_cell_init(t_moldyn *moldyn) {
 int link_cell_update(t_moldyn *moldyn) {
 
        int count,i,j,k;
-       int nx,ny,nz;
+       int nx,ny;
        t_atom *atom;
        t_linkcell *lc;
+       double x,y,z;
 
        atom=moldyn->atom;
        lc=&(moldyn->lc);
 
        nx=lc->nx;
        ny=lc->ny;
-       nz=lc->nz;
+
+       x=moldyn->dim.x/2;
+       y=moldyn->dim.y/2;
+       z=moldyn->dim.z/2;
 
        for(i=0;i<lc->cells;i++)
-               list_destroy(&(moldyn->lc.subcell[i]));
+               list_destroy_f(&(lc->subcell[i]));
        
        for(count=0;count<moldyn->count;count++) {
-               i=(atom[count].r.x+(moldyn->dim.x/2))/lc->x;
-               j=(atom[count].r.y+(moldyn->dim.y/2))/lc->y;
-               k=(atom[count].r.z+(moldyn->dim.z/2))/lc->z;
-               list_add_immediate_ptr(&(moldyn->lc.subcell[i+j*nx+k*nx*ny]),
-                                      &(atom[count]));
+               i=((atom[count].r.x+(moldyn->dim.x/2))/lc->x);
+               j=((atom[count].r.y+(moldyn->dim.y/2))/lc->y);
+               k=((atom[count].r.z+(moldyn->dim.z/2))/lc->z);
+               list_add_immediate_f(&(moldyn->lc.subcell[i+j*nx+k*nx*ny]),
+                                    &(atom[count]));
        }
 
        return 0;
@@ -610,7 +747,9 @@ int link_cell_shutdown(t_moldyn *moldyn) {
        lc=&(moldyn->lc);
 
        for(i=0;i<lc->nx*lc->ny*lc->nz;i++)
-               list_shutdown(&(moldyn->lc.subcell[i]));
+               list_destroy_f(&(moldyn->lc.subcell[i]));
+
+       free(lc->subcell);
 
        return 0;
 }
@@ -724,6 +863,8 @@ int moldyn_integrate(t_moldyn *moldyn) {
                /* p/t scaling */
                if(moldyn->pt_scale&(T_SCALE_BERENDSEN|T_SCALE_DIRECT))
                        scale_velocity(moldyn,FALSE);
+               if(moldyn->pt_scale&(P_SCALE_BERENDSEN|P_SCALE_DIRECT))
+                       scale_volume(moldyn);
 
                /* check for log & visualization */
                if(e) {
@@ -802,16 +943,13 @@ int velocity_verlet(t_moldyn *moldyn) {
                v3_add(&(atom[i].r),&(atom[i].r),&delta);
                v3_scale(&delta,&(atom[i].f),0.5*tau_square/atom[i].mass);
                v3_add(&(atom[i].r),&(atom[i].r),&delta);
-//if(i==5) printf("v: %f %f %f\n",atom[i].r.x,(atom[i].r.x+moldyn->dim.x/2)/moldyn->lc.x,2*atom[i].r.x/moldyn->dim.x);
                check_per_bound(moldyn,&(atom[i].r));
-//if(i==5) printf("n: %f %f %f\n",atom[i].r.x,(atom[i].r.x+moldyn->dim.x/2)/moldyn->lc.x,2*atom[i].r.x/moldyn->dim.x);
 
                /* velocities */
                v3_scale(&delta,&(atom[i].f),0.5*tau/atom[i].mass);
                v3_add(&(atom[i].v),&(atom[i].v),&delta);
        }
 
-//moldyn_bc_check(moldyn);
        /* neighbour list update */
        link_cell_update(moldyn);
 
@@ -853,13 +991,16 @@ int potential_force_calc(t_moldyn *moldyn) {
 
        /* reset energy */
        moldyn->energy=0.0;
-
+       
        /* get energy and force of every atom */
        for(i=0;i<count;i++) {
 
                /* reset force */
                v3_zero(&(itom[i].f));
 
+               /* reset viral of atom i */
+               v3_zero(&(itom[i].virial));
+
                /* single particle potential/force */
                if(itom[i].attr&ATOM_ATTR_1BP)
                        moldyn->func1b(moldyn,&(itom[i]));
@@ -880,7 +1021,7 @@ int potential_force_calc(t_moldyn *moldyn) {
                for(j=0;j<27;j++) {
 
                        this=&(neighbour_i[j]);
-                       list_reset(this);
+                       list_reset_f(this);
 
                        if(this->start==NULL)
                                continue;
@@ -915,7 +1056,7 @@ int potential_force_calc(t_moldyn *moldyn) {
                                for(k=0;k<27;k++) {
 
                                        that=&(neighbour_i2[k]);
-                                       list_reset(that);
+                                       list_reset_f(that);
                                        
                                        if(that->start==NULL)
                                                continue;
@@ -941,7 +1082,7 @@ int potential_force_calc(t_moldyn *moldyn) {
                                                               ktom,
                                                               bc_ik|bc_ij);
 
-                                       } while(list_next(that)!=\
+                                       } while(list_next_f(that)!=\
                                                L_NO_NEXT_ELEMENT);
 
                                }
@@ -953,7 +1094,7 @@ int potential_force_calc(t_moldyn *moldyn) {
                                                            jtom,bc_ij);
                                }
                                        
-                       } while(list_next(this)!=L_NO_NEXT_ELEMENT);
+                       } while(list_next_f(this)!=L_NO_NEXT_ELEMENT);
                
                }
 
@@ -966,7 +1107,7 @@ int potential_force_calc(t_moldyn *moldyn) {
  * periodic boundayr checking
  */
 
-int check_per_bound(t_moldyn *moldyn,t_3dvec *a) {
+inline int check_per_bound(t_moldyn *moldyn,t_3dvec *a) {
        
        double x,y,z;
        t_3dvec *dim;
@@ -1627,6 +1768,7 @@ int tersoff_mult_3bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,t_atom *ak,u8 bc) {
                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 ^ */
+
        }
 
        return 0;
@@ -1655,6 +1797,7 @@ x=dim->x/2;
                        printf("FATAL: atom %d: x: %.20f (%.20f)\n",
                               i,atom[i].r.x,dim->x/2);
                        printf("diagnostic:\n");
+                       printf("-----------\natom.r.x:\n");
                        for(j=0;j<8;j++) {
                                memcpy(&byte,(u8 *)(&(atom[i].r.x))+j,1);
                                for(k=0;k<8;k++)
@@ -1662,7 +1805,7 @@ x=dim->x/2;
                                        ((byte)&(1<<k))?1:0,
                                        (k==7)?'\n':'|');
                        }
-                       printf("---------------\n");
+                       printf("---------------\nx=dim.x/2:\n");
                        for(j=0;j<8;j++) {
                                memcpy(&byte,(u8 *)(&x)+j,1);
                                for(k=0;k<8;k++)
@@ -1670,8 +1813,8 @@ x=dim->x/2;
                                        ((byte)&(1<<k))?1:0,
                                        (k==7)?'\n':'|');
                        }
-                       if(atom[i].r.x==x) printf("hier gleich!\n");
-                       else printf("hier NICHT gleich!\n");
+                       if(atom[i].r.x==x) printf("the same!\n");
+                       else printf("different!\n");
                }
                if(atom[i].r.y>=dim->y/2||-atom[i].r.y>dim->y/2)
                        printf("FATAL: atom %d: y: %.20f (%.20f)\n",
@@ -1683,4 +1826,3 @@ x=dim->x/2;
 
        return 0;
 }
-