]> hackdaworld.org Git - physik/posic.git/commitdiff
add another way of calculating tersoff + small moldyn mods
authorhackbard <hackbard>
Fri, 27 Apr 2007 16:39:13 +0000 (16:39 +0000)
committerhackbard <hackbard>
Fri, 27 Apr 2007 16:39:13 +0000 (16:39 +0000)
Makefile
moldyn.c
moldyn.h
potentials/tersoff.c
potentials/tersoff.h
potentials/tersoff_orig.c [new file with mode: 0644]
potentials/tersoff_orig.h [new file with mode: 0644]
report/report.h
sic.c

index 3e31459bd7ab9004a79c9e9a1f21a5c096fbdf4b..70fcb8bf3b8acd3fe97c0bcc9a69257c58c8c5d0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -8,10 +8,11 @@ CFLAGS+=-g
 #CFLAGS+=-DVDEBUG
 LDFLAGS=-lm
 
-SOURCE=moldyn.c visual/visual.c random/random.c
+SOURCE=moldyn.c visual/visual.c random/random.c list/list.c
 
-POT_SRC=potentials/tersoff.c potentials/lennard_jones.c
-POT_SRC+= potentials/harmonic_oscillator.c
+POT_SRC=potentials/tersoff.c
+#POT_SRC=potentials/tersoff_orig.c
+POT_SRC+= potentials/lennard_jones.c potentials/harmonic_oscillator.c
 
 all: sic
 
index 9a62b9f7c93d5142f5b15d57d099f4ba160604ce..4d736179550d68c7402e89b4412dec3dfc9d40bb 100644 (file)
--- a/moldyn.c
+++ b/moldyn.c
@@ -82,7 +82,7 @@ int set_pressure(t_moldyn *moldyn,double p_ref) {
 
        moldyn->p_ref=p_ref;
 
-       printf("[moldyn] pressure [atm]: %f\n",moldyn->p_ref/ATM);
+       printf("[moldyn] pressure [bar]: %f\n",moldyn->p_ref/BAR);
 
        return 0;
 }
@@ -176,16 +176,37 @@ int set_potential2b(t_moldyn *moldyn,pf_func2b func) {
        return 0;
 }
 
-int set_potential2b_post(t_moldyn *moldyn,pf_func2b_post func) {
+int set_potential3b_j1(t_moldyn *moldyn,pf_func2b func) {
 
-       moldyn->func2b_post=func;
+       moldyn->func3b_j1=func;
 
        return 0;
 }
 
-int set_potential3b(t_moldyn *moldyn,pf_func3b func) {
+int set_potential3b_j2(t_moldyn *moldyn,pf_func2b func) {
 
-       moldyn->func3b=func;
+       moldyn->func3b_j2=func;
+
+       return 0;
+}
+
+int set_potential3b_j3(t_moldyn *moldyn,pf_func2b func) {
+
+       moldyn->func3b_j3=func;
+
+       return 0;
+}
+
+int set_potential3b_k1(t_moldyn *moldyn,pf_func3b func) {
+
+       moldyn->func3b_k1=func;
+
+       return 0;
+}
+
+int set_potential3b_k2(t_moldyn *moldyn,pf_func3b func) {
+
+       moldyn->func3b_k2=func;
 
        return 0;
 }
@@ -294,6 +315,7 @@ int moldyn_set_log(t_moldyn *moldyn,u8 type,int timer) {
                                perror("[moldyn] report fd open");      
                                return moldyn->rfd;
                        }
+                       printf("report -> ");
                        if(moldyn->efd) {
                                snprintf(filename,127,"%s/e_plot.scr",
                                         moldyn->vlsdir);
@@ -306,6 +328,7 @@ int moldyn_set_log(t_moldyn *moldyn,u8 type,int timer) {
                                }
                                dprintf(moldyn->epfd,e_plot_script);
                                close(moldyn->epfd);
+                               printf("energy ");
                        }
                        if(moldyn->pfd) {
                                snprintf(filename,127,"%s/pressure_plot.scr",
@@ -319,6 +342,7 @@ int moldyn_set_log(t_moldyn *moldyn,u8 type,int timer) {
                                }
                                dprintf(moldyn->ppfd,pressure_plot_script);
                                close(moldyn->ppfd);
+                               printf("pressure ");
                        }
                        if(moldyn->tfd) {
                                snprintf(filename,127,"%s/temperature_plot.scr",
@@ -332,9 +356,11 @@ int moldyn_set_log(t_moldyn *moldyn,u8 type,int timer) {
                                }
                                dprintf(moldyn->tpfd,temperature_plot_script);
                                close(moldyn->tpfd);
+                               printf("temperature ");
                        }
                        dprintf(moldyn->rfd,report_start,
                                moldyn->rauthor,moldyn->rtitle);
+                       printf("\n");
                        break;
                default:
                        printf("unknown log type: %02x\n",type);
@@ -672,6 +698,8 @@ double temperature_calc(t_moldyn *moldyn) {
        /* assume up to date kinetic energy, which is 3/2 N k_B T */
 
        moldyn->t=(2.0*moldyn->ekin)/(3.0*K_BOLTZMANN*moldyn->count);
+       moldyn->t_sum+=moldyn->t;
+       moldyn->mean_t=moldyn->t_sum/moldyn->total_steps;
 
        return moldyn->t;
 }
@@ -769,6 +797,16 @@ double pressure_calc(t_moldyn *moldyn) {
        /* assume up to date kinetic energy */
        moldyn->p=2.0*moldyn->ekin+v;
        moldyn->p/=(3.0*moldyn->volume);
+       moldyn->p_sum+=moldyn->p;
+       moldyn->mean_p=moldyn->p_sum/moldyn->total_steps;
+
+       /* pressure from 'absolute coordinates' virial */
+       virial=&(moldyn->virial);
+       v=virial->xx+virial->yy+virial->zz;
+       moldyn->gp=2.0*moldyn->ekin+v;
+       moldyn->gp/=(3.0*moldyn->volume);
+       moldyn->gp_sum+=moldyn->gp;
+       moldyn->mean_gp=moldyn->gp_sum/moldyn->total_steps;
 
        return moldyn->p;
 }      
@@ -788,7 +826,7 @@ double thermodynamic_pressure_calc(t_moldyn *moldyn) {
         * dV: dx,y,z = 0.001 x,y,z
         */
 
-       scale=1.00001;
+       scale=1.00000000000001;
 printf("\n\nP-DEBUG:\n");
 
        tp=&(moldyn->tp);
@@ -806,13 +844,12 @@ printf("\n\nP-DEBUG:\n");
        /* derivative with respect to x direction */
        scale_dim(moldyn,scale,TRUE,0,0);
        scale_atoms(moldyn,scale,TRUE,0,0);
-       dv=0.00001*moldyn->dim.x*moldyn->dim.y*moldyn->dim.z;
+       dv=0.00000000000001*moldyn->dim.x*moldyn->dim.y*moldyn->dim.z;
        link_cell_shutdown(moldyn);
        link_cell_init(moldyn,QUIET);
        potential_force_calc(moldyn);
        tp->x=(moldyn->energy-u)/dv;
        p=tp->x*tp->x;
-printf("e: %f eV de: %f eV dV: %f A^3\n",moldyn->energy/moldyn->count/EV,(moldyn->energy-u)/moldyn->count/EV,dv);
 
        /* restore atomic configuration + dim */
        memcpy(moldyn->atom,store,moldyn->count*sizeof(t_atom));
@@ -821,7 +858,7 @@ printf("e: %f eV de: %f eV dV: %f A^3\n",moldyn->energy/moldyn->count/EV,(moldyn
        /* derivative with respect to y direction */
        scale_dim(moldyn,scale,0,TRUE,0);
        scale_atoms(moldyn,scale,0,TRUE,0);
-       dv=0.00001*moldyn->dim.y*moldyn->dim.x*moldyn->dim.z;
+       dv=0.00000000000001*moldyn->dim.y*moldyn->dim.x*moldyn->dim.z;
        link_cell_shutdown(moldyn);
        link_cell_init(moldyn,QUIET);
        potential_force_calc(moldyn);
@@ -835,7 +872,7 @@ printf("e: %f eV de: %f eV dV: %f A^3\n",moldyn->energy/moldyn->count/EV,(moldyn
        /* derivative with respect to z direction */
        scale_dim(moldyn,scale,0,0,TRUE);
        scale_atoms(moldyn,scale,0,0,TRUE);
-       dv=0.00001*moldyn->dim.z*moldyn->dim.x*moldyn->dim.y;
+       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);
@@ -939,7 +976,7 @@ moldyn->debug=scale;
 
 }
 
-double get_e_kin(t_moldyn *moldyn) {
+double e_kin_calc(t_moldyn *moldyn) {
 
        int i;
        t_atom *atom;
@@ -953,11 +990,6 @@ double get_e_kin(t_moldyn *moldyn) {
        return moldyn->ekin;
 }
 
-double update_e_kin(t_moldyn *moldyn) {
-
-       return(get_e_kin(moldyn));
-}
-
 double get_total_energy(t_moldyn *moldyn) {
 
        return(moldyn->ekin+moldyn->energy);
@@ -1018,7 +1050,12 @@ int link_cell_init(t_moldyn *moldyn,u8 vol) {
        if(lc->cells<27)
                printf("[moldyn] FATAL: less then 27 subcells!\n");
 
-       if(vol) printf("[moldyn] initializing linked cells (%d)\n",lc->cells);
+       if(vol) {
+               printf("[moldyn] initializing linked cells (%d)\n",lc->cells);
+               printf("  x: %d x %f A\n",lc->nx,lc->x);
+               printf("  y: %d x %f A\n",lc->ny,lc->y);
+               printf("  z: %d x %f A\n",lc->nz,lc->z);
+       }
 
        for(i=0;i<lc->cells;i++)
                list_init_f(&(lc->subcell[i]));
@@ -1053,7 +1090,7 @@ int link_cell_update(t_moldyn *moldyn) {
                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]),
+               list_add_immediate_f(&(lc->subcell[i+j*nx+k*nx*ny]),
                                     &(atom[count]));
        }
 
@@ -1229,6 +1266,7 @@ int moldyn_integrate(t_moldyn *moldyn) {
 
        /* zero absolute time */
        moldyn->time=0.0;
+       moldyn->total_steps=0;
 
        /* debugging, ignore */
        moldyn->debug=0;
@@ -1252,10 +1290,11 @@ int moldyn_integrate(t_moldyn *moldyn) {
                moldyn->integrate(moldyn);
 
                /* calculate kinetic energy, temperature and pressure */
-               update_e_kin(moldyn);
+               e_kin_calc(moldyn);
                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);
 
                /* p/t scaling */
                if(moldyn->pt_scale&(T_SCALE_BERENDSEN|T_SCALE_DIRECT))
@@ -1284,13 +1323,16 @@ int moldyn_integrate(t_moldyn *moldyn) {
                if(p) {
                        if(!(i%p)) {
                                dprintf(moldyn->pfd,
-                                       "%f %f\n",moldyn->time,moldyn->p/ATM);
+                                       "%f %f %f %f %f\n",moldyn->time,
+                                        moldyn->p/BAR,moldyn->mean_p/BAR,
+                                        moldyn->gp/BAR,moldyn->mean_gp/BAR);
                        }
                }
                if(t) {
                        if(!(i%t)) {
                                dprintf(moldyn->tfd,
-                                       "%f %f\n",moldyn->time,moldyn->t);
+                                       "%f %f %f\n",
+                                       moldyn->time,moldyn->t,moldyn->mean_t);
                        }
                }
                if(s) {
@@ -1316,14 +1358,18 @@ int moldyn_integrate(t_moldyn *moldyn) {
 
                /* display progress */
                if(!(i%10)) {
-                       printf("\rsched: %d, steps: %d, T: %f, P: %f V: %f",
+                       printf("\rsched: %d, steps: %d, T: %f, P: %f %f V: %f",
                               sched->count,i,
-                              moldyn->t,moldyn->p/ATM,moldyn->volume);
+                              moldyn->mean_t,
+                              moldyn->mean_p/BAR,
+                              moldyn->mean_gp/BAR,
+                              moldyn->volume);
                        fflush(stdout);
                }
 
                /* increase absolute time */
                moldyn->time+=moldyn->tau;
+               moldyn->total_steps+=1;
 
        }
 
@@ -1410,6 +1456,9 @@ int potential_force_calc(t_moldyn *moldyn) {
        /* reset energy */
        moldyn->energy=0.0;
 
+       /* reset global virial */
+       memset(&(moldyn->virial),0,sizeof(t_virial));
+
        /* reset force, site energy and virial of every atom */
        for(i=0;i<count;i++) {
 
@@ -1430,7 +1479,9 @@ int potential_force_calc(t_moldyn *moldyn) {
 
        }
 
-       /* get energy,force and virial of every atom */
+       /* get energy, force and virial of every atom */
+
+       /* first (and only) loop over atoms i */
        for(i=0;i<count;i++) {
 
                /* single particle potential/force */
@@ -1450,6 +1501,45 @@ int potential_force_calc(t_moldyn *moldyn) {
 
                dnlc=lc->dnlc;
 
+               /* first loop over atoms j */
+               if(moldyn->func2b) {
+                       for(j=0;j<27;j++) {
+
+                               this=&(neighbour_i[j]);
+                               list_reset_f(this);
+
+                               if(this->start==NULL)
+                                       continue;
+
+                               bc_ij=(j<dnlc)?0:1;
+
+                               do {
+                                       jtom=this->current->data;
+
+                                       if(jtom==&(itom[i]))
+                                               continue;
+
+                                       if((jtom->attr&ATOM_ATTR_2BP)&
+                                          (itom[i].attr&ATOM_ATTR_2BP)) {
+                                               moldyn->func2b(moldyn,
+                                                              &(itom[i]),
+                                                              jtom,
+                                                              bc_ij);
+                                       }
+                               } while(list_next_f(this)!=L_NO_NEXT_ELEMENT);
+
+                       }
+               }
+
+               /* 3 body potential/force */
+
+               if(!(itom[i].attr&ATOM_ATTR_3BP))
+                       continue;
+
+               /* copy the neighbour lists */
+               memcpy(neighbour_i2,neighbour_i,27*sizeof(t_list));
+
+               /* second loop over atoms j */
                for(j=0;j<27;j++) {
 
                        this=&(neighbour_i[j]);
@@ -1466,25 +1556,70 @@ int potential_force_calc(t_moldyn *moldyn) {
                                if(jtom==&(itom[i]))
                                        continue;
 
-                               if((jtom->attr&ATOM_ATTR_2BP)&
-                                  (itom[i].attr&ATOM_ATTR_2BP)) {
-                                       moldyn->func2b(moldyn,
-                                                      &(itom[i]),
-                                                      jtom,
-                                                      bc_ij);
-                               }
+                               if(!(jtom->attr&ATOM_ATTR_3BP))
+                                       continue;
 
-                               /* 3 body potential/force */
+                               /* reset 3bp run */
+                               moldyn->run3bp=1;
 
-                               if(!(itom[i].attr&ATOM_ATTR_3BP)||
-                                  !(jtom->attr&ATOM_ATTR_3BP))
+                               if(moldyn->func3b_j1)
+                                       moldyn->func3b_j1(moldyn,
+                                                         &(itom[i]),
+                                                         jtom,
+                                                         bc_ij);
+
+                               /* in first j loop, 3bp run can be skipped */
+                               if(!(moldyn->run3bp))
                                        continue;
+                       
+                               /* first loop over atoms k */
+                               if(moldyn->func3b_k1) {
+
+                               for(k=0;k<27;k++) {
+
+                                       that=&(neighbour_i2[k]);
+                                       list_reset_f(that);
+                                       
+                                       if(that->start==NULL)
+                                               continue;
+
+                                       bc_ik=(k<dnlc)?0:1;
 
-                               /* copy the neighbour lists */
-                               memcpy(neighbour_i2,neighbour_i,
-                                      27*sizeof(t_list));
+                                       do {
+
+                                               ktom=that->current->data;
+
+                                               if(!(ktom->attr&ATOM_ATTR_3BP))
+                                                       continue;
+
+                                               if(ktom==jtom)
+                                                       continue;
+
+                                               if(ktom==&(itom[i]))
+                                                       continue;
+
+                                               moldyn->func3b_k1(moldyn,
+                                                                 &(itom[i]),
+                                                                 jtom,
+                                                                 ktom,
+                                                                 bc_ik|bc_ij);
+
+                                       } while(list_next_f(that)!=\
+                                               L_NO_NEXT_ELEMENT);
+
+                               }
+
+                               }
+
+                               if(moldyn->func3b_j2)
+                                       moldyn->func3b_j2(moldyn,
+                                                         &(itom[i]),
+                                                         jtom,
+                                                         bc_ij);
+
+                               /* second loop over atoms k */
+                               if(moldyn->func3b_k2) {
 
-                               /* get neighbours of i */
                                for(k=0;k<27;k++) {
 
                                        that=&(neighbour_i2[k]);
@@ -1508,37 +1643,53 @@ int potential_force_calc(t_moldyn *moldyn) {
                                                if(ktom==&(itom[i]))
                                                        continue;
 
-                                               moldyn->func3b(moldyn,
-                                                              &(itom[i]),
-                                                              jtom,
-                                                              ktom,
-                                                              bc_ik|bc_ij);
+                                               moldyn->func3b_k2(moldyn,
+                                                                 &(itom[i]),
+                                                                 jtom,
+                                                                 ktom,
+                                                                 bc_ik|bc_ij);
 
                                        } while(list_next_f(that)!=\
                                                L_NO_NEXT_ELEMENT);
 
                                }
+                               
+                               }
 
                                /* 2bp post function */
-                               if(moldyn->func2b_post) {
-                                       moldyn->func2b_post(moldyn,
-                                                           &(itom[i]),
-                                                           jtom,bc_ij);
+                               if(moldyn->func3b_j3) {
+                                       moldyn->func3b_j3(moldyn,
+                                                         &(itom[i]),
+                                                         jtom,bc_ij);
                                }
                                        
                        } while(list_next_f(this)!=L_NO_NEXT_ELEMENT);
                
                }
+               
+#ifdef DEBUG
+       //printf("\n\n");
+#endif
+#ifdef VDEBUG
+       printf("\n\n");
+#endif
 
        }
 
 #ifdef DEBUG
-printf("\n\n");
-#endif
-#ifdef VDEBUG
-printf("\n\n");
+       printf("\nATOM 0: %f %f %f\n\n",itom->f.x,itom->f.y,itom->f.z);
 #endif
 
+       /* calculate global virial */
+       for(i=0;i<count;i++) {
+               moldyn->virial.xx+=moldyn->atom[i].r.x*moldyn->atom[i].f.x;
+               moldyn->virial.yy+=moldyn->atom[i].r.y*moldyn->atom[i].f.y;
+               moldyn->virial.zz+=moldyn->atom[i].r.z*moldyn->atom[i].f.z;
+               moldyn->virial.xy+=moldyn->atom[i].r.y*moldyn->atom[i].f.x;
+               moldyn->virial.xz+=moldyn->atom[i].r.z*moldyn->atom[i].f.x;
+               moldyn->virial.yz+=moldyn->atom[i].r.z*moldyn->atom[i].f.y;
+       }
+
        return 0;
 }
 
index 85a4950cc513c9cde9b7dc0cb66f9d49503e3b8f..5b12048f908f55b3a987475dc8b352f8714ed844 100644 (file)
--- a/moldyn.h
+++ b/moldyn.h
@@ -85,11 +85,15 @@ typedef struct s_moldyn {
        /* potential force function and parameter pointers */
        int (*func1b)(struct s_moldyn *moldyn,t_atom *ai);
        int (*func2b)(struct s_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc);
-       int (*func2b_post)(struct s_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc);
-       int (*func3b)(struct s_moldyn *moldyn,t_atom *ai,t_atom *aj,t_atom *ak,
-                     u8 bck);
+       int (*func3b_j1)(struct s_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc);
+       int (*func3b_j2)(struct s_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc);
+       int (*func3b_j3)(struct s_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc);
+       int (*func3b_k1)(struct s_moldyn *moldyn,
+                        t_atom *ai,t_atom *aj,t_atom *ak,u8 bck);
+       int (*func3b_k2)(struct s_moldyn *moldyn,
+                        t_atom *ai,t_atom *aj,t_atom *ak,u8 bck);
        void *pot_params;
-       //int (*potential_force_function)(struct s_moldyn *moldyn);
+       unsigned char run3bp;
 
        double cutoff;          /* cutoff radius */
        double cutoff_square;   /* square of the cutoff radius */
@@ -99,9 +103,18 @@ typedef struct s_moldyn {
 
        double t_ref;           /* reference temperature */
        double t;               /* actual temperature */
+       double t_sum;           /* sum over all t */
+       double mean_t;          /* mean value of t */
+
+       t_virial virial;        /* global virial (absolute coordinates) */
+       double gp;              /* pressure computed from global virial */
+       double gp_sum;          /* sum over all gp */
+       double mean_gp;         /* mean value of gp */
 
        double p_ref;           /* reference pressure */
        double p;               /* actual pressure (computed by virial) */
+       double p_sum;           /* sum over all p */
+       double mean_p;          /* mean value of p */
        t_3dvec tp;             /* thermodynamic pressure dU/dV */
        double dv;              /* dV for thermodynamic pressure calc */
 
@@ -121,7 +134,7 @@ typedef struct s_moldyn {
        double tau;             /* delta t */
        double time;            /* absolute time */
        double tau_square;      /* delta t squared */
-       double elapsed;         /* total elapsed time */
+       int total_steps;        /* total steps */
 
        double energy;          /* potential energy */
        double ekin;            /* kinetic energy */
@@ -175,7 +188,7 @@ typedef struct s_moldyn {
 #define P_SCALE_DIRECT                 0x08    /* direct p control */
 
 /*
- * default values
+ * default values & units
  *
  * - length unit: 1 A (1 A = 1e-10 m)
  * - time unit: 1 fs (1 fs = 1e-15 s)
@@ -191,7 +204,9 @@ typedef struct s_moldyn {
 #define KILOGRAM                       (1.0/AMU)               /* amu */
 #define NEWTON (METER*KILOGRAM/(SECOND*SECOND))        /* A amu / fs^2 */
 #define PASCAL (NEWTON/(METER*METER))                  /* N / A^2 */
-#define ATM    ((1.0133e5*PASCAL))                     /* N / A^2 */
+#define BAR    ((1.0e5*PASCAL))                        /* N / A^2 */
+#define K_BOLTZMANN    (1.380650524e-23*METER*NEWTON)  /* NA/K */
+#define EV             (1.6021765314e-19*METER*NEWTON) /* NA */
 
 #define MOLDYN_TEMP                    273.0
 #define MOLDYN_TAU                     1.0
@@ -220,17 +235,12 @@ typedef struct s_moldyn {
 #define QUIET                          0
 
 /*
- *
- * phsical values / constants
- *
+ * potential related phsical values / constants
  *
  */
 
 #define ONE_THIRD              (1.0/3.0)
 
-#define K_BOLTZMANN            (1.380650524e-23*METER*NEWTON)  /* NA/K */
-#define EV                     (1.6021765314e-19*METER*NEWTON) /* NA */
-
 #define C                      0x06
 #define M_C                    12.011                          /* amu */
 
@@ -284,10 +294,9 @@ typedef struct s_moldyn {
  *
  */
 
-typedef int (*pf_func1b)(t_moldyn *,t_atom *ai);
-typedef int (*pf_func2b)(t_moldyn *,t_atom *,t_atom *,u8 bc);
-typedef int (*pf_func2b_post)(t_moldyn *,t_atom *,t_atom *,u8 bc);
-typedef int (*pf_func3b)(t_moldyn *,t_atom *,t_atom *,t_atom *,u8 bc);
+typedef int (*pf_func1b)(t_moldyn *,t_atom *);
+typedef int (*pf_func2b)(t_moldyn *,t_atom *,t_atom *,u8);
+typedef int (*pf_func3b)(t_moldyn *,t_atom *,t_atom *,t_atom *,u8);
 
 int moldyn_init(t_moldyn *moldyn,int argc,char **argv);
 int moldyn_shutdown(t_moldyn *moldyn);
@@ -302,8 +311,11 @@ int set_nn_dist(t_moldyn *moldyn,double dist);
 int set_pbc(t_moldyn *moldyn,u8 x,u8 y,u8 z);
 int set_potential1b(t_moldyn *moldyn,pf_func1b func);
 int set_potential2b(t_moldyn *moldyn,pf_func2b func);
-int set_potential2b_post(t_moldyn *moldyn,pf_func2b_post func);
-int set_potential3b(t_moldyn *moldyn,pf_func3b func);
+int set_potential3b_j1(t_moldyn *moldyn,pf_func2b func);
+int set_potential3b_j2(t_moldyn *moldyn,pf_func2b func);
+int set_potential3b_j3(t_moldyn *moldyn,pf_func2b func);
+int set_potential3b_k1(t_moldyn *moldyn,pf_func3b func);
+int set_potential3b_k2(t_moldyn *moldyn,pf_func3b func);
 int set_potential_params(t_moldyn *moldyn,void *params);
 
 int moldyn_set_log_dir(t_moldyn *moldyn,char *dir);
@@ -331,8 +343,7 @@ int scale_volume(t_moldyn *moldyn);
 int scale_dim(t_moldyn *moldyn,double scale,u8 x,u8 y,u8 z);
 int scale_atoms(t_moldyn *moldyn,double scale,u8 x,u8 y,u8 z);
 
-double get_e_kin(t_moldyn *moldyn);
-double update_e_kin(t_moldyn *moldyn);
+double e_kin_calc(t_moldyn *moldyn);
 double get_total_energy(t_moldyn *moldyn);
 t_3dvec get_total_p(t_moldyn *moldyn);
 
index 16f771c7be4b614f10c6fd70b9476fb0bfd5e23f..531d292131121ad5acb7b1ce2a4a0c551199b34a 100644 (file)
@@ -85,10 +85,9 @@ int tersoff_mult_1bp(t_moldyn *moldyn,t_atom *ai) {
 int tersoff_mult_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) {
 
        t_tersoff_mult_params *params;
-       t_tersoff_exchange *exchange;
        t_3dvec dist_ij,force;
        double d_ij,d_ij2;
-       double A,B,R,S,S2,lambda,mu;
+       double A,R,S,S2,lambda;
        double f_r,df_r;
        double f_c,df_c;
        int brand;
@@ -96,31 +95,10 @@ int tersoff_mult_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) {
        double arg;
 
        /* use newtons third law */
-       //if(ai<aj) return 0;
+       if(ai<aj) return 0;
 
        params=moldyn->pot_params;
        brand=aj->brand;
-       exchange=&(params->exchange);
-
-       /* clear 3bp and 2bp post run */
-       exchange->run3bp=0;
-       exchange->run2bp_post=0;
-
-       /* reset S > r > R mark */
-       exchange->d_ij_between_rs=0;
-       
-       /*
-        * calc of 2bp contribution of V_ij and dV_ij/ji
-        *
-        * for Vij and dV_ij we need:
-        * - f_c_ij, df_c_ij
-        * - f_r_ij, df_r_ij
-        *
-        * for dV_ji we need:
-        * - f_c_ji = f_c_ij, df_c_ji = df_c_ij
-        * - f_r_ji = f_r_ij; df_r_ji = df_r_ij
-        *
-        */
 
        /* determine cutoff square */
        if(brand==ai->brand)
@@ -128,71 +106,41 @@ int tersoff_mult_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) {
        else
                S2=params->S2mixed;
 
-       /* dist_ij, d_ij */
+       /* dist_ij, d_ij2 */
        v3_sub(&dist_ij,&(aj->r),&(ai->r));
        if(bc) check_per_bound(moldyn,&dist_ij);
        d_ij2=v3_absolute_square(&dist_ij);
 
        /* if d_ij2 > S2 => no force & potential energy contribution */
-       if(d_ij2>S2)
+       if(d_ij2>S2) {
                return 0;
+       }
 
        /* now we will need the distance */
-       //d_ij=v3_norm(&dist_ij);
        d_ij=sqrt(d_ij2);
 
-       /* save for use in 3bp */
-       exchange->d_ij=d_ij;
-       exchange->d_ij2=d_ij2;
-       exchange->dist_ij=dist_ij;
-
        /* more constants */
-       exchange->beta_j=&(params->beta[brand]);
-       exchange->n_j=&(params->n[brand]);
-       exchange->c_j=&(params->c[brand]);
-       exchange->d_j=&(params->d[brand]);
-       exchange->h_j=&(params->h[brand]);
        if(brand==ai->brand) {
                S=params->S[brand];
                R=params->R[brand];
                A=params->A[brand];
-               B=params->B[brand];
                lambda=params->lambda[brand];
-               mu=params->mu[brand];
-               exchange->chi=1.0;
-               exchange->betajnj=exchange->betaini;
-               exchange->cj2=exchange->ci2;
-               exchange->dj2=exchange->di2;
-               exchange->cj2dj2=exchange->ci2di2;
        }
        else {
                S=params->Smixed;
                R=params->Rmixed;
                A=params->Amixed;
-               B=params->Bmixed;
                lambda=params->lambda_m;
-               mu=params->mu_m;
-               params->exchange.chi=params->chi;
-               exchange->betajnj=pow(*(exchange->beta_j),*(exchange->n_j));
-               exchange->cj2=params->c[brand]*params->c[brand];
-               exchange->dj2=params->d[brand]*params->d[brand];
-               exchange->cj2dj2=exchange->cj2/exchange->dj2;
        }
 
-       /* f_r_ij = f_r_ji, df_r_ij = df_r_ji */
+       /* f_r_ij, df_r_ij */
        f_r=A*exp(-lambda*d_ij);
        df_r=lambda*f_r/d_ij;
 
-       /* f_a, df_a calc (again, same for ij and ji) | save for later use! */
-       exchange->f_a=-B*exp(-mu*d_ij);
-       exchange->df_a=mu*exchange->f_a/d_ij;
-
-       /* f_c, df_c calc (again, same for ij and ji) */
+       /* f_c, df_c */
        if(d_ij<R) {
-               /* f_c = 1, df_c = 0 */
                f_c=1.0;
                df_c=0.0;
-               /* two body contribution (ij, ji) */
                v3_scale(&force,&dist_ij,-df_r);
        }
        else {
@@ -200,18 +148,27 @@ int tersoff_mult_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) {
                arg=M_PI*(d_ij-R)/s_r;
                f_c=0.5+0.5*cos(arg);
                df_c=0.5*sin(arg)*(M_PI/(s_r*d_ij));
-               /* two body contribution (ij, ji) */
                v3_scale(&force,&dist_ij,-df_c*f_r-df_r*f_c);
-               /* tell 3bp that S > r > R */
-               exchange->d_ij_between_rs=1;
        }
 
-       /* add forces of 2bp (ij, ji) contribution
-        * dVij = dVji and we sum up both: no 1/2) */
+       /* add forces */
        v3_add(&(ai->f),&(ai->f),&force);
+       v3_sub(&(aj->f),&(aj->f),&force);
+
+#ifdef DEBUG
+       if((ai==&(moldyn->atom[0]))|(aj==&(moldyn->atom[0]))) {
+               printf("force 2bp: [%d %d]\n",ai->tag,aj->tag);
+               printf("adding %f %f %f\n",force.x,force.y,force.z);
+               if(ai==&(moldyn->atom[0]))
+                       printf("total i: %f %f %f\n",ai->f.x,ai->f.y,ai->f.z);
+               if(aj==&(moldyn->atom[0]))
+                       printf("total j: %f %f %f\n",aj->f.x,aj->f.y,aj->f.z);
+       }
+#endif
 
        /* virial */
-       virial_calc(ai,&force,&dist_ij);
+       //virial_calc(ai,&force,&dist_ij);
+       //virial_calc(aj,&force,&dist_ij);
        //ai->virial.xx-=force.x*dist_ij.x;
        //ai->virial.yy-=force.y*dist_ij.y;
        //ai->virial.zz-=force.z*dist_ij.z;
@@ -219,270 +176,86 @@ int tersoff_mult_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) {
        //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.x,ai->f.x);
-       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 ... */
-       moldyn->energy+=(0.5*f_r*f_c);
-
-       /* save for use in 3bp */
-       exchange->f_c=f_c;
-       exchange->df_c=df_c;
-
-       /* enable the run of 3bp function and 2bp post processing */
-       exchange->run3bp=1;
-       exchange->run2bp_post=1;
-
-       /* reset 3bp sums */
-       exchange->zeta_ij=0.0;
-       exchange->zeta_ji=0.0;
-       v3_zero(&(exchange->dzeta_ij));
-       v3_zero(&(exchange->dzeta_ji));
+       /* energy 2bp contribution */
+       moldyn->energy+=f_r*f_c;
 
        return 0;
 }
 
-/* tersoff 2 body post part */
-
-int tersoff_mult_post_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) {
-
-       /*
-        * here we have to allow for the 3bp sums
-        *
-        * that is:
-        * - zeta_ij, dzeta_ij
-        * - zeta_ji, dzeta_ji
-        *
-        * to compute the 3bp contribution to:
-        * - Vij, dVij
-        * - dVji
-        *
-        */
+/* tersoff 3 body potential function (first ij loop) */
+int tersoff_mult_3bp_j1(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) {
 
        t_tersoff_mult_params *params;
        t_tersoff_exchange *exchange;
-
-       t_3dvec force,temp;
-       t_3dvec *dist_ij;
-       double b,db,tmp;
-       double f_c,df_c,f_a,df_a;
-       double chi,ni,betaini,nj,betajnj;
-       double zeta;
+       unsigned char brand;
+       double S2;
+       t_3dvec dist_ij;
+       double d_ij2,d_ij;
 
        params=moldyn->pot_params;
        exchange=&(params->exchange);
 
-       /* we do not run if f_c_ij was detected to be 0! */
-       if(!(exchange->run2bp_post))
-               return 0;
-
-       f_c=exchange->f_c;
-       df_c=exchange->df_c;
-       f_a=exchange->f_a;
-       df_a=exchange->df_a;
-       betaini=exchange->betaini;
-       betajnj=exchange->betajnj;
-       ni=*(exchange->n_i);
-       nj=*(exchange->n_j);
-       chi=exchange->chi;
-       dist_ij=&(exchange->dist_ij);
-       
-       /* Vij and dVij */
-       zeta=exchange->zeta_ij;
-       if(zeta==0.0) {
-               moldyn->debug++;                /* just for debugging ... */
-               b=chi;
-               v3_scale(&force,dist_ij,df_a*b*f_c);
-       }
-       else {
-               tmp=betaini*pow(zeta,ni-1.0);           /* beta^n * zeta^n-1 */
-               b=(1+zeta*tmp);                         /* 1 + beta^n zeta^n */
-               db=chi*pow(b,-1.0/(2*ni)-1);            /* x(...)^(-1/2n - 1) */
-               b=db*b;                                 /* b_ij */
-               db*=-0.5*tmp;                           /* db_ij */
-               v3_scale(&force,&(exchange->dzeta_ij),f_a*db);
-               v3_scale(&temp,dist_ij,df_a*b);
-               v3_add(&force,&force,&temp);
-               v3_scale(&force,&force,f_c);
-       }
-       v3_scale(&temp,dist_ij,df_c*b*f_a);
-       v3_add(&force,&force,&temp);
-       v3_scale(&force,&force,-0.5);
-
-       /* add force */
-       v3_add(&(ai->f),&(ai->f),&force);
+       /* reset zeta sum */
+       exchange->zeta_ij=0.0;
 
-       /* virial */
-       virial_calc(ai,&force,dist_ij);
-       //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;
+       /*
+        * set ij depending values
+        */
 
-#ifdef DEBUG
-if(ai==&(moldyn->atom[0])) {
-       printf("dVij (3bp) contrib:\n");
-       printf("%f | %f\n",force.x,ai->f.x);
-       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
+       brand=ai->brand;
+       
+       if(brand==aj->brand)
+               S2=params->S2[brand];
+       else
+               S2=params->S2mixed;
 
-       /* add energy of 3bp sum */
-       moldyn->energy+=(0.5*f_c*b*f_a);
+       /* dist_ij, d_ij2 */
+       v3_sub(&dist_ij,&(aj->r),&(ai->r));
+       if(bc) check_per_bound(moldyn,&dist_ij);
+       d_ij2=v3_absolute_square(&dist_ij);
 
-       /* dVji */
-       zeta=exchange->zeta_ji;
-       if(zeta==0.0) {
-               moldyn->debug++;
-               b=chi;
-               v3_scale(&force,dist_ij,df_a*b*f_c);
-       }
-       else {
-               tmp=betajnj*pow(zeta,nj-1.0);           /* beta^n * zeta^n-1 */
-               b=(1+zeta*tmp);                         /* 1 + beta^n zeta^n */
-               db=chi*pow(b,-1.0/(2*nj)-1);            /* x(...)^(-1/2n - 1) */
-               b=db*b;                                 /* b_ij */
-               db*=-0.5*tmp;                           /* db_ij */
-               v3_scale(&force,&(exchange->dzeta_ji),f_a*db);
-               v3_scale(&temp,dist_ij,df_a*b);
-               v3_add(&force,&force,&temp);
-               v3_scale(&force,&force,f_c);
+       /* if d_ij2 > S2 => no force & potential energy contribution */
+       if(d_ij2>S2) {
+               moldyn->run3bp=0;
+               return 0;
        }
-       v3_scale(&temp,dist_ij,df_c*b*f_a);
-       v3_add(&force,&force,&temp);
-       v3_scale(&force,&force,-0.5);
 
-       /* add force */
-       v3_add(&(ai->f),&(ai->f),&force);
-
-       /* virial - plus sign, as dist_ij = - dist_ji - (really??) */
-// TEST ... with a minus instead
-       virial_calc(ai,&force,dist_ij);
-       //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;
+       /* d_ij */
+       d_ij=sqrt(d_ij2);
 
-#ifdef DEBUG
-if(ai==&(moldyn->atom[0])) {
-       printf("dVji (3bp) contrib:\n");
-       printf("%f | %f\n",force.x,ai->f.x);
-       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
+       /* store values */
+       exchange->dist_ij=dist_ij;
+       exchange->d_ij2=d_ij2;
+       exchange->d_ij=d_ij;
 
+       /* reset k counter for first k loop */
+       exchange->kcount=0;
+               
        return 0;
 }
 
-/* tersoff 3 body part */
-
-int tersoff_mult_3bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,t_atom *ak,u8 bc) {
+/* tersoff 3 body potential function (first k loop) */
+int tersoff_mult_3bp_k1(t_moldyn *moldyn,
+                        t_atom *ai,t_atom *aj,t_atom *ak,u8 bc) {
 
        t_tersoff_mult_params *params;
        t_tersoff_exchange *exchange;
-       t_3dvec dist_ij,dist_ik,dist_jk;
-       t_3dvec temp1,temp2;
-       t_3dvec *dzeta;
-       double R,S,S2,s_r;
-       double B,mu;
-       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;
-       double f_c_jk;
-       double n,c,d,h;
-       double c2,d2,c2d2;
-       double cos_theta,d_costheta1,d_costheta2;
-       double h_cos,d2_h_cos2;
-       double frac,g,zeta,chi;
-       double tmp;
-       int brand;
+       unsigned char brand;
+       double R,S,S2;
+       t_3dvec dist_ij,dist_ik;
+       double d_ik2,d_ik,d_ij;
+       double cos_theta,h_cos,d2_h_cos2,frac,g,dg,s_r,arg;
+       double f_c_ik,df_c_ik;
+       int kcount;
 
        params=moldyn->pot_params;
        exchange=&(params->exchange);
+       kcount=exchange->kcount;
 
-       if(!(exchange->run3bp))
-               return 0;
-
-       /*
-        * calc of 3bp contribution of V_ij and dV_ij/ji/jk &
-        * 2bp contribution of dV_jk
-        *
-        * for Vij and dV_ij we still need:
-        * - b_ij, db_ij (zeta_ij)
-        *   - f_c_ik, df_c_ik, constants_i, cos_theta_ijk, d_costheta_ijk
-        *
-        * for dV_ji we still need:
-        * - b_ji, db_ji (zeta_ji)
-        *   - f_c_jk, d_c_jk, constants_j, cos_theta_jik, d_costheta_jik
-        *
-        * for dV_jk we need:
-        * - f_c_jk
-        * - f_a_jk
-        * - db_jk (zeta_jk)
-        *   - f_c_ji, df_c_ji, constants_j, cos_theta_jki, d_costheta_jki
-        *
-        */
-
-       /*
-        * get exchange data 
-        */
-
-       /* 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;
-       df_c=exchange->df_c;
-
-       /*
-        * calculate unknown values now ...
-        */
-
-       /* V_ij and dV_ij stuff (in b_ij there is f_c_ik) */
-
-       /* dist_ik, d_ik */
-       v3_sub(&dist_ik,&(ak->r),&(ai->r));
-       if(bc) check_per_bound(moldyn,&dist_ik);
-       d_ik2=v3_absolute_square(&dist_ik);
+       if(kcount>TERSOFF_MAXN) {
+               printf("FATAL: neighbours = %d\n",kcount);
+               printf("  -> %d %d %d\n",ai->tag,aj->tag,ak->tag);
+       }
 
        /* ik constants */
        brand=ai->brand;
@@ -497,215 +270,298 @@ int tersoff_mult_3bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,t_atom *ak,u8 bc) {
                S2=params->S2mixed;
        }
 
-       /* zeta_ij/dzeta_ij contribution only for 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);
-               c=*(exchange->c_i);
-               d=*(exchange->d_i);
-               h=*(exchange->h_i);
-               c2=exchange->ci2;
-               d2=exchange->di2;
-               c2d2=exchange->ci2di2;
-
-               /* cosine of theta_ijk by scalaproduct */
-               rr=v3_scalar_product(&dist_ij,&dist_ik);
-               dd=d_ij*d_ik;
-               cos_theta=rr/dd;
-
-               /* d_costheta */
-               tmp=1.0/dd;
-               d_costheta1=cos_theta/d_ij2-tmp;
-               d_costheta2=cos_theta/d_ik2-tmp;
-
-               /* some usefull values */
-               h_cos=(h-cos_theta);
-               d2_h_cos2=d2+(h_cos*h_cos);
-               frac=c2/(d2_h_cos2);
-
-               /* g(cos_theta) */
-               g=1.0+c2d2-frac;
-
-               /* d_costheta_ij and dg(cos_theta) - needed in any case! */
-               v3_scale(&temp1,&dist_ij,d_costheta1);
-               v3_scale(&temp2,&dist_ik,d_costheta2);
-               v3_add(&temp1,&temp1,&temp2);
-               v3_scale(&temp1,&temp1,-2.0*frac*h_cos/d2_h_cos2); /* dg */
-
-               /* f_c_ik & df_c_ik + {d,}zeta contribution */
-               dzeta=&(exchange->dzeta_ij);
-               if(d_ik<R) {
-                       /* {d,}f_c_ik */
-                       // => f_c_ik=1.0;
-                       // => df_c_ik=0.0; of course we do not set this!
-
-                       /* zeta_ij */
-                       exchange->zeta_ij+=g;
-
-                       /* dzeta_ij */
-                       v3_add(dzeta,dzeta,&temp1);
-               }
-               else {
-                       /* {d,}f_c_ik */
-                       s_r=S-R;
-                       arg=M_PI*(d_ik-R)/s_r;
-                       f_c_ik=0.5+0.5*cos(arg);
-                       df_c_ik=0.5*sin(arg)*(M_PI/(s_r*d_ik));
-
-                       /* zeta_ij */
-                       exchange->zeta_ij+=f_c_ik*g;
-
-                       /* dzeta_ij */
-                       v3_scale(&temp1,&temp1,f_c_ik);
-                       v3_scale(&temp2,&dist_ik,g*df_c_ik);
-                       v3_add(&temp1,&temp1,&temp2);
-                       v3_add(dzeta,dzeta,&temp1);
-               }
+       /* dist_ik, d_ik2 */
+       v3_sub(&dist_ik,&(ak->r),&(ai->r));
+       if(bc) check_per_bound(moldyn,&dist_ik);
+       d_ik2=v3_absolute_square(&dist_ik);
+
+       /* store data for second k loop */
+       exchange->dist_ik[kcount]=dist_ik;
+       exchange->d_ik2[kcount]=d_ik2;
+
+       /* return if not within cutoff */
+       if(d_ik2>S2) {
+               exchange->kcount++;
+               return 0;
+       }
+
+       /* d_ik */
+       d_ik=sqrt(d_ik2);
+
+       /* dist_ij, d_ij */
+       dist_ij=exchange->dist_ij;
+       d_ij=exchange->d_ij;
+
+       /* cos theta */
+       cos_theta=v3_scalar_product(&dist_ij,&dist_ik)/(d_ij*d_ik);
+
+       /* g_ijk */
+       h_cos=*(exchange->h_i)-cos_theta;
+       d2_h_cos2=exchange->di2+(h_cos*h_cos);
+       frac=exchange->ci2/d2_h_cos2;
+       g=1.0+exchange->ci2di2-frac;
+       dg=-2.0*frac*h_cos/d2_h_cos2;
+
+       /* zeta sum += f_c_ik * g_ijk */
+       if(d_ik<=R) {
+               exchange->zeta_ij+=g;
+               f_c_ik=1.0;
+               df_c_ik=0.0;
+       }
+       else {
+               s_r=S-R;
+               arg=M_PI*(d_ik-R)/s_r;
+               f_c_ik=0.5+0.5*cos(arg);
+               df_c_ik=0.5*sin(arg)*(M_PI/(s_r*d_ik));
+               exchange->zeta_ij+=f_c_ik*g;
        }
 
-       /* dV_ji stuff (in b_ji there is f_c_jk) + dV_jk stuff! */
+       /* store even more data for second k loop */
+       exchange->g[kcount]=g;
+       exchange->dg[kcount]=dg;
+       exchange->d_ik[kcount]=d_ik;
+       exchange->cos_theta[kcount]=cos_theta;
+       exchange->f_c_ik[kcount]=f_c_ik;
+       exchange->df_c_ik[kcount]=df_c_ik;
 
-       /* dist_jk, d_jk */
-       v3_sub(&dist_jk,&(ak->r),&(aj->r));
-       if(bc) check_per_bound(moldyn,&dist_jk);
-       d_jk2=v3_absolute_square(&dist_jk);
+       /* increase k counter */
+       exchange->kcount++;
+
+       return 0;
+}
+
+int tersoff_mult_3bp_j2(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) {
+
+       t_tersoff_mult_params *params;
+       t_tersoff_exchange *exchange;
+       t_3dvec force;
+       double f_a,df_a,b,db,f_c,df_c;
+       double mu,B,chi;
+       double d_ij;
+       unsigned char brand;
+       double ni,tmp;
+       double S,R,s_r,arg;
+
+       params=moldyn->pot_params;
+       exchange=&(params->exchange);
 
-       /* jk constants */
        brand=aj->brand;
-       if(brand==ak->brand) {
-               R=params->R[brand];
+       if(brand==ai->brand) {
                S=params->S[brand];
-               S2=params->S2[brand];
+               R=params->R[brand];
                B=params->B[brand];
                mu=params->mu[brand];
                chi=1.0;
        }
        else {
-               R=params->Rmixed;
                S=params->Smixed;
-               S2=params->S2mixed;
+               R=params->Rmixed;
                B=params->Bmixed;
                mu=params->mu_m;
                chi=params->chi;
        }
 
-       /* zeta_ji/dzeta_ji contribution only for d_jk < S_jk */
-       if(d_jk2<S2) {
-
-               /* now we need d_ik */
-               d_jk=sqrt(d_jk2);
-
-               /* constants_j from exchange data */
-               n=*(exchange->n_j);
-               c=*(exchange->c_j);
-               d=*(exchange->d_j);
-               h=*(exchange->h_j);
-               c2=exchange->cj2;
-               d2=exchange->dj2;
-               c2d2=exchange->cj2dj2;
-
-               /* cosine of theta_jik by scalaproduct */
-               rr=-v3_scalar_product(&dist_ij,&dist_jk); /* -1, as ij -> ji */
-               dd=d_ij*d_jk;
-               cos_theta=rr/dd;
-
-               /* d_costheta */
-               d_costheta1=1.0/dd;
-               d_costheta2=cos_theta/d_ij2;
-
-               /* some usefull values */
-               h_cos=(h-cos_theta);
-               d2_h_cos2=d2+(h_cos*h_cos);
-               frac=c2/(d2_h_cos2);
-
-               /* g(cos_theta) */
-               g=1.0+c2d2-frac;
-
-               /* 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_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_copy(&temp2,&temp1);
-
-               /* f_c_jk + {d,}zeta contribution (df_c_jk = 0) */
-               dzeta=&(exchange->dzeta_ji);
-               if(d_jk<R) {
-                       /* f_c_jk */
-                       f_c_jk=1.0;
-
-                       /* zeta_ji */
-                       exchange->zeta_ji+=g;
-
-                       /* dzeta_ji */
-                       v3_add(dzeta,dzeta,&temp1);
-               }
-               else {
-                       /* f_c_jk */
-                       s_r=S-R;
-                       arg=M_PI*(d_jk-R)/s_r;
-                       f_c_jk=0.5+0.5*cos(arg);
-
-                       /* zeta_ji */
-                       exchange->zeta_ji+=f_c_jk*g;
-
-                       /* dzeta_ji */
-                       v3_scale(&temp1,&temp1,f_c_jk);
-                       v3_add(dzeta,dzeta,&temp1);
-               }
-
-               /* dV_jk stuff | add force contribution on atom i immediately */
-               if(exchange->d_ij_between_rs) {
-                       zeta=f_c*g;
-                       v3_scale(&temp1,&temp2,f_c);
-                       v3_scale(&temp2,&dist_ij,df_c*g);
-                       v3_add(&temp2,&temp2,&temp1); /* -> dzeta_jk in temp2 */
-               }
-               else {
-                       zeta=g;
-                       // dzeta_jk is simply dg, which is stored in temp2
-               }
-               /* betajnj * zeta_jk ^ nj-1 */
-               tmp=exchange->betajnj*pow(zeta,(n-1.0));
-               tmp=-chi/2.0*pow((1+tmp*zeta),(-1.0/(2.0*n)-1))*tmp;
-               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;
+       d_ij=exchange->d_ij;
+
+       /* f_c, df_c */
+       if(d_ij<R) {
+               f_c=1.0;
+               df_c=0.0;
+       }
+       else {
+               s_r=S-R;
+               arg=M_PI*(d_ij-R)/s_r;
+               f_c=0.5+0.5*cos(arg);
+               df_c=0.5*sin(arg)*(M_PI/(s_r*d_ij));
+       }
+
+       /* f_a, df_a */
+       f_a=-B*exp(-mu*d_ij);
+       df_a=mu*f_a/d_ij;
+
+       /* b, db */
+       if(exchange->zeta_ij==0.0) {
+               b=chi;
+               db=0.0;
+       }
+       else {
+               ni=*(exchange->n_i);
+               tmp=exchange->betaini*pow(exchange->zeta_ij,ni-1.0);
+               b=(1.0+exchange->zeta_ij*tmp);
+               db=chi*pow(b,-1.0/(2*ni)-1.0);
+               b=db*b;
+               db*=-0.5*tmp;
+       }
+
+       /* force contribution */
+       v3_scale(&force,&(exchange->dist_ij),df_a*f_c+f_a*df_c);
+       v3_scale(&force,&force,-0.5*b);
+       v3_add(&(ai->f),&(ai->f),&force);
+       v3_sub(&(aj->f),&(aj->f),&force);
 
 #ifdef DEBUG
-if(ai==&(moldyn->atom[0])) {
-       printf("dVjk (3bp) contrib:\n");
-       printf("%f | %f\n",temp2.x,ai->f.x);
-       printf("%f | %f\n",temp2.y,ai->f.y);
-       printf("%f | %f\n",temp2.z,ai->f.z);
-}
+       if((ai==&(moldyn->atom[0]))|(aj==&(moldyn->atom[0]))) {
+               printf("force 3bp (j2): [%d %d sum]\n",ai->tag,aj->tag);
+               printf("adding %f %f %f\n",force.x,force.y,force.z);
+               if(ai==&(moldyn->atom[0]))
+                       printf("total i: %f %f %f\n",ai->f.x,ai->f.y,ai->f.z);
+               if(aj==&(moldyn->atom[0]))
+                       printf("total j: %f %f %f\n",aj->f.x,aj->f.y,aj->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);
+
+       /* virial */
+       //virial_calc(ai,&force,&(exchange->dist_ij));
+       //virial_calc(aj,&force,&(exchange->dist_ij));
+
+       /* dzeta prefactor = - 0.5 f_c f_a db */
+       exchange->pre_dzeta=-0.5*f_a*f_c*db;
+
+       /* energy contribution */
+       moldyn->energy+=0.5*f_c*b*f_a;
+
+       /* reset k counter for second k loop */
+       exchange->kcount=0;
+               
+       return 0;
 }
+
+/* tersoff 3 body potential function (second k loop) */
+int tersoff_mult_3bp_k2(t_moldyn *moldyn,
+                        t_atom *ai,t_atom *aj,t_atom *ak,u8 bc) {
+
+       t_tersoff_mult_params *params;
+       t_tersoff_exchange *exchange;
+       int kcount;
+       t_3dvec dist_ik,dist_ij;
+       double d_ik2,d_ik,d_ij2,d_ij;
+       unsigned char brand;
+       double S2;
+       double g,dg,cos_theta;
+       double pre_dzeta;
+       double f_c_ik,df_c_ik;
+       double dijdik_inv,fcdg,dfcg;
+       t_3dvec dcosdri,dcosdrj,dcosdrk;
+       t_3dvec force,tmp;
+
+       params=moldyn->pot_params;
+       exchange=&(params->exchange);
+       kcount=exchange->kcount;
+
+       if(kcount>TERSOFF_MAXN)
+               printf("FATAL: neighbours!\n");
+
+       /* d_ik2 */
+       d_ik2=exchange->d_ik2[kcount];
+
+       brand=ak->brand;
+       if(brand==ai->brand)
+               S2=params->S2[brand];
+       else
+               S2=params->S2mixed;
+
+       /* return if d_ik > S */
+       if(d_ik2>S2) {
+               exchange->kcount++;
+               return 0;
+       }
+
+       /* prefactor dzeta */
+       pre_dzeta=exchange->pre_dzeta;
+
+       /* dist_ik, d_ik */
+       dist_ik=exchange->dist_ik[kcount];
+       d_ik=exchange->d_ik[kcount];
+
+       /* f_c_ik, df_c_ik */
+       f_c_ik=exchange->f_c_ik[kcount];
+       df_c_ik=exchange->df_c_ik[kcount];
+
+       /* dist_ij, d_ij2, d_ij */
+       dist_ij=exchange->dist_ij;
+       d_ij2=exchange->d_ij2;
+       d_ij=exchange->d_ij;
+
+       /* g, dg, cos_theta */
+       g=exchange->g[kcount];
+       dg=exchange->dg[kcount];
+       cos_theta=exchange->cos_theta[kcount];
+
+       /* cos_theta derivatives wrt i,j,k */
+       dijdik_inv=1.0/(d_ij*d_ik);
+       v3_scale(&dcosdrj,&dist_ik,dijdik_inv);
+       v3_scale(&tmp,&dist_ij,-cos_theta/d_ij2);
+       v3_add(&dcosdrj,&dcosdrj,&tmp);
+       v3_scale(&dcosdrk,&dist_ij,dijdik_inv);
+       v3_scale(&tmp,&dist_ik,-cos_theta/d_ik2);
+       v3_add(&dcosdrk,&dcosdrk,&tmp);
+       v3_add(&dcosdri,&dcosdrj,&dcosdrk);
+       v3_scale(&dcosdri,&dcosdri,-1.0);
+
+       /* f_c_ik * dg, df_c_ik * g */
+       fcdg=f_c_ik*dg;
+       dfcg=df_c_ik*g;
+
+       /* derivative wrt i */
+       v3_scale(&force,&dist_ik,dfcg);
+       v3_scale(&tmp,&dcosdri,fcdg);
+       v3_add(&force,&force,&tmp);
+       v3_scale(&force,&force,pre_dzeta);
+
+       /* force contribution */
+       v3_add(&(ai->f),&(ai->f),&force);
+       
+#ifdef DEBUG
+       if(ai==&(moldyn->atom[0])) {
+               printf("force 3bp (k2): [%d %d %d]\n",ai->tag,aj->tag,ak->tag);
+               printf("adding %f %f %f\n",force.x,force.y,force.z);
+               printf("total i: %f %f %f\n",ai->f.x,ai->f.y,ai->f.z);
+       }
+#endif
+
+       /* virial */
+       //virial_calc(ai,&force,&dist_ij);
+
+       /* derivatice wrt j */
+       v3_scale(&force,&dcosdrj,fcdg*pre_dzeta);
+
+       /* force contribution */
+       v3_add(&(aj->f),&(aj->f),&force);
+
+#ifdef DEBUG
+       if(aj==&(moldyn->atom[0])) {
+               printf("force 3bp (k2): [%d %d %d]\n",ai->tag,aj->tag,ak->tag);
+               printf("adding %f %f %f\n",force.x,force.y,force.z);
+               printf("total j: %f %f %f\n",aj->f.x,aj->f.y,aj->f.z);
+       }
 #endif
 
+       /* virial */
+       //virial_calc(aj,&force,&dist_ij);
+
+       /* derivative wrt k */
+       v3_scale(&force,&dist_ik,dfcg);
+       v3_scale(&tmp,&dcosdrk,fcdg);
+       v3_add(&force,&force,&tmp);
+       v3_scale(&force,&force,pre_dzeta);
+
+       /* force contribution */
+       v3_add(&(ak->f),&(ak->f),&force);
+
+#ifdef DEBUG
+       if(ak==&(moldyn->atom[0])) {
+               printf("force 3bp (k2): [%d %d %d]\n",ai->tag,aj->tag,ak->tag);
+               printf("adding %f %f %f\n",force.x,force.y,force.z);
+               printf("total k: %f %f %f\n",ak->f.x,ak->f.y,ak->f.z);
        }
+#endif
+
+       /* virial */
+       virial_calc(ak,&force,&dist_ik);
+       
+       /* increase k counter */
+       exchange->kcount++;     
 
        return 0;
-}
 
+}
index a04ed0246c15eee1d531b7b23ccd95d1ed4ed90a..52e848f787b522feb6204c6e4d158bc12d629bbf 100644 (file)
@@ -8,45 +8,41 @@
 #ifndef TERSOFF_H
 #define TERSOFF_H
 
+#define TERSOFF_MAXN   16*27
+
 /* tersoff exchange type */
 typedef struct s_tersoff_echange {
-       double f_c,df_c;
-       double f_a,df_a;
 
        t_3dvec dist_ij;
        double d_ij2;
        double d_ij;
 
-       double chi;
+       t_3dvec dist_ik[TERSOFF_MAXN];
+       double d_ik2[TERSOFF_MAXN];
+       double d_ik[TERSOFF_MAXN];
+
+       double f_c_ik[TERSOFF_MAXN];
+       double df_c_ik[TERSOFF_MAXN];
+
+       double g[TERSOFF_MAXN];
+       double dg[TERSOFF_MAXN];
+       double cos_theta[TERSOFF_MAXN];
 
        double *beta_i;
-       double *beta_j;
        double *n_i;
-       double *n_j;
        double *c_i;
-       double *c_j;
        double *d_i;
-       double *d_j;
        double *h_i;
-       double *h_j;
 
        double ci2;
-       double cj2;
        double di2;
-       double dj2;
        double ci2di2;
-       double cj2dj2;
        double betaini;
-       double betajnj;
-
-       u8 run3bp;
-       u8 run2bp_post;
-       u8 d_ij_between_rs;
 
        double zeta_ij;
-       double zeta_ji;
-       t_3dvec dzeta_ij;
-       t_3dvec dzeta_ji;
+       double pre_dzeta;
+
+       int kcount;
 } t_tersoff_exchange;
 
 /* tersoff mult (2!) potential parameters */
@@ -81,7 +77,11 @@ typedef struct s_tersoff_mult_params {
 int tersoff_mult_complete_params(t_tersoff_mult_params *p);
 int tersoff_mult_1bp(t_moldyn *moldyn,t_atom *ai);
 int tersoff_mult_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc);
-int tersoff_mult_post_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc);
-int tersoff_mult_3bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,t_atom *ak,u8 bc);
+int tersoff_mult_3bp_j1(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc);
+int tersoff_mult_3bp_k1(t_moldyn *moldyn,
+                        t_atom *ai,t_atom *aj,t_atom *ak,u8 bc);
+int tersoff_mult_3bp_j2(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc);
+int tersoff_mult_3bp_k2(t_moldyn *moldyn,
+                        t_atom *ai,t_atom *aj,t_atom *ak,u8 bc);
 
 #endif
diff --git a/potentials/tersoff_orig.c b/potentials/tersoff_orig.c
new file mode 100644 (file)
index 0000000..90121f2
--- /dev/null
@@ -0,0 +1,707 @@
+/*
+ * tersoff_orig.c - tersoff potential
+ *
+ * author: Frank Zirkelbach <frank.zirkelbach@physik.uni-augsburg.de>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "../moldyn.h"
+#include "../math/math.h"
+#include "tersoff_orig.h"
+
+/* create mixed terms from parameters and set them */
+int tersoff_mult_complete_params(t_tersoff_mult_params *p) {
+
+       printf("[moldyn] tersoff parameter completion\n");
+       p->S2[0]=p->S[0]*p->S[0];
+       p->S2[1]=p->S[1]*p->S[1];
+       p->Smixed=sqrt(p->S[0]*p->S[1]);
+       p->S2mixed=p->Smixed*p->Smixed;
+       p->Rmixed=sqrt(p->R[0]*p->R[1]);
+       p->Amixed=sqrt(p->A[0]*p->A[1]);
+       p->Bmixed=sqrt(p->B[0]*p->B[1]);
+       p->lambda_m=0.5*(p->lambda[0]+p->lambda[1]);
+       p->mu_m=0.5*(p->mu[0]+p->mu[1]);
+
+       printf("[moldyn] tersoff mult parameter info:\n");
+       printf("  S (A)  | %f | %f | %f\n",p->S[0],p->S[1],p->Smixed);
+       printf("  R (A)  | %f | %f | %f\n",p->R[0],p->R[1],p->Rmixed);
+       printf("  A (eV) | %f | %f | %f\n",p->A[0]/EV,p->A[1]/EV,p->Amixed/EV);
+       printf("  B (eV) | %f | %f | %f\n",p->B[0]/EV,p->B[1]/EV,p->Bmixed/EV);
+       printf("  lambda | %f | %f | %f\n",p->lambda[0],p->lambda[1],
+                                         p->lambda_m);
+       printf("  mu     | %f | %f | %f\n",p->mu[0],p->mu[1],p->mu_m);
+       printf("  beta   | %.10f | %.10f\n",p->beta[0],p->beta[1]);
+       printf("  n      | %f | %f\n",p->n[0],p->n[1]);
+       printf("  c      | %f | %f\n",p->c[0],p->c[1]);
+       printf("  d      | %f | %f\n",p->d[0],p->d[1]);
+       printf("  h      | %f | %f\n",p->h[0],p->h[1]);
+       printf("  chi    | %f \n",p->chi);
+
+       return 0;
+}
+
+/* tersoff 1 body part */
+int tersoff_mult_1bp(t_moldyn *moldyn,t_atom *ai) {
+
+       int brand;
+       t_tersoff_mult_params *params;
+       t_tersoff_exchange *exchange;
+       
+       brand=ai->brand;
+       params=moldyn->pot_params;
+       exchange=&(params->exchange);
+
+       /*
+        * simple: point constant parameters only depending on atom i to
+        *         their right values
+        */
+
+       exchange->beta_i=&(params->beta[brand]);
+       exchange->n_i=&(params->n[brand]);
+       exchange->c_i=&(params->c[brand]);
+       exchange->d_i=&(params->d[brand]);
+       exchange->h_i=&(params->h[brand]);
+
+       exchange->betaini=pow(*(exchange->beta_i),*(exchange->n_i));
+       exchange->ci2=params->c[brand]*params->c[brand];
+       exchange->di2=params->d[brand]*params->d[brand];
+       exchange->ci2di2=exchange->ci2/exchange->di2;
+
+       return 0;
+}
+       
+/* tersoff 2 body part */
+int tersoff_mult_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) {
+
+       t_tersoff_mult_params *params;
+       t_tersoff_exchange *exchange;
+       t_3dvec dist_ij,force;
+       double d_ij,d_ij2;
+       double A,B,R,S,S2,lambda,mu;
+       double f_r,df_r;
+       double f_c,df_c;
+       int brand;
+       double s_r;
+       double arg;
+
+       /* use newtons third law */
+       //if(ai<aj) return 0;
+
+       params=moldyn->pot_params;
+       brand=aj->brand;
+       exchange=&(params->exchange);
+
+       /* clear 3bp and 2bp post run */
+       exchange->run3bp=0;
+       exchange->run2bp_post=0;
+
+       /* reset S > r > R mark */
+       exchange->d_ij_between_rs=0;
+       
+       /*
+        * calc of 2bp contribution of V_ij and dV_ij/ji
+        *
+        * for Vij and dV_ij we need:
+        * - f_c_ij, df_c_ij
+        * - f_r_ij, df_r_ij
+        *
+        * for dV_ji we need:
+        * - f_c_ji = f_c_ij, df_c_ji = df_c_ij
+        * - f_r_ji = f_r_ij; df_r_ji = df_r_ij
+        *
+        */
+
+       /* determine cutoff square */
+       if(brand==ai->brand)
+               S2=params->S2[brand];
+       else
+               S2=params->S2mixed;
+
+       /* dist_ij, d_ij */
+       v3_sub(&dist_ij,&(aj->r),&(ai->r));
+       if(bc) check_per_bound(moldyn,&dist_ij);
+       d_ij2=v3_absolute_square(&dist_ij);
+
+       /* if d_ij2 > S2 => no force & potential energy contribution */
+       if(d_ij2>S2)
+               return 0;
+
+       /* now we will need the distance */
+       //d_ij=v3_norm(&dist_ij);
+       d_ij=sqrt(d_ij2);
+
+       /* save for use in 3bp */
+       exchange->d_ij=d_ij;
+       exchange->d_ij2=d_ij2;
+       exchange->dist_ij=dist_ij;
+
+       /* more constants */
+       exchange->beta_j=&(params->beta[brand]);
+       exchange->n_j=&(params->n[brand]);
+       exchange->c_j=&(params->c[brand]);
+       exchange->d_j=&(params->d[brand]);
+       exchange->h_j=&(params->h[brand]);
+       if(brand==ai->brand) {
+               S=params->S[brand];
+               R=params->R[brand];
+               A=params->A[brand];
+               B=params->B[brand];
+               lambda=params->lambda[brand];
+               mu=params->mu[brand];
+               exchange->chi=1.0;
+               exchange->betajnj=exchange->betaini;
+               exchange->cj2=exchange->ci2;
+               exchange->dj2=exchange->di2;
+               exchange->cj2dj2=exchange->ci2di2;
+       }
+       else {
+               S=params->Smixed;
+               R=params->Rmixed;
+               A=params->Amixed;
+               B=params->Bmixed;
+               lambda=params->lambda_m;
+               mu=params->mu_m;
+               exchange->chi=params->chi;
+               exchange->betajnj=pow(*(exchange->beta_j),*(exchange->n_j));
+               exchange->cj2=params->c[brand]*params->c[brand];
+               exchange->dj2=params->d[brand]*params->d[brand];
+               exchange->cj2dj2=exchange->cj2/exchange->dj2;
+       }
+
+       /* f_r_ij = f_r_ji, df_r_ij = df_r_ji */
+       f_r=A*exp(-lambda*d_ij);
+       df_r=lambda*f_r/d_ij;
+
+       /* f_a, df_a calc (again, same for ij and ji) | save for later use! */
+       exchange->f_a=-B*exp(-mu*d_ij);
+       exchange->df_a=mu*exchange->f_a/d_ij;
+
+       /* f_c, df_c calc (again, same for ij and ji) */
+       if(d_ij<R) {
+               /* f_c = 1, df_c = 0 */
+               f_c=1.0;
+               df_c=0.0;
+               /* two body contribution (ij, ji) */
+               v3_scale(&force,&dist_ij,-df_r);
+       }
+       else {
+               s_r=S-R;
+               arg=M_PI*(d_ij-R)/s_r;
+               f_c=0.5+0.5*cos(arg);
+               df_c=0.5*sin(arg)*(M_PI/(s_r*d_ij));
+               /* two body contribution (ij, ji) */
+               v3_scale(&force,&dist_ij,-df_c*f_r-df_r*f_c);
+               /* tell 3bp that S > r > R */
+               exchange->d_ij_between_rs=1;
+       }
+
+       /* 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 */
+       virial_calc(ai,&force,&dist_ij);
+       //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: [%d %d]\n",ai->tag,aj->tag);
+       printf("adding %f %f %f\n",force.x,force.y,force.z);
+       printf("total i: %f %f %f\n",ai->f.x,ai->f.y,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 ... */
+       moldyn->energy+=(0.5*f_r*f_c);
+
+       /* save for use in 3bp */
+       exchange->f_c=f_c;
+       exchange->df_c=df_c;
+
+       /* enable the run of 3bp function and 2bp post processing */
+       exchange->run3bp=1;
+       exchange->run2bp_post=1;
+
+       /* reset 3bp sums */
+       exchange->zeta_ij=0.0;
+       exchange->zeta_ji=0.0;
+       v3_zero(&(exchange->dzeta_ij));
+       v3_zero(&(exchange->dzeta_ji));
+
+       return 0;
+}
+
+/* tersoff 2 body post part */
+
+int tersoff_mult_post_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) {
+
+       /*
+        * here we have to allow for the 3bp sums
+        *
+        * that is:
+        * - zeta_ij, dzeta_ij
+        * - zeta_ji, dzeta_ji
+        *
+        * to compute the 3bp contribution to:
+        * - Vij, dVij
+        * - dVji
+        *
+        */
+
+       t_tersoff_mult_params *params;
+       t_tersoff_exchange *exchange;
+
+       t_3dvec force,temp;
+       t_3dvec *dist_ij;
+       double b,db,tmp;
+       double f_c,df_c,f_a,df_a;
+       double chi,ni,betaini,nj,betajnj;
+       double zeta;
+
+       params=moldyn->pot_params;
+       exchange=&(params->exchange);
+
+       /* we do not run if f_c_ij was detected to be 0! */
+       if(!(exchange->run2bp_post))
+               return 0;
+
+       f_c=exchange->f_c;
+       df_c=exchange->df_c;
+       f_a=exchange->f_a;
+       df_a=exchange->df_a;
+       betaini=exchange->betaini;
+       betajnj=exchange->betajnj;
+       ni=*(exchange->n_i);
+       nj=*(exchange->n_j);
+       chi=exchange->chi;
+       dist_ij=&(exchange->dist_ij);
+       
+       /* Vij and dVij */
+       zeta=exchange->zeta_ij;
+       if(zeta==0.0) {
+               moldyn->debug++;                /* just for debugging ... */
+               b=chi;
+               v3_scale(&force,dist_ij,df_a*b*f_c);
+       }
+       else {
+               tmp=betaini*pow(zeta,ni-1.0);           /* beta^n * zeta^n-1 */
+               b=(1+zeta*tmp);                         /* 1 + beta^n zeta^n */
+               db=chi*pow(b,-1.0/(2*ni)-1);            /* x(...)^(-1/2n - 1) */
+               b=db*b;                                 /* b_ij */
+               db*=-0.5*tmp;                           /* db_ij */
+               v3_scale(&force,&(exchange->dzeta_ij),f_a*db);
+               v3_scale(&temp,dist_ij,df_a*b);
+               v3_add(&force,&force,&temp);
+               v3_scale(&force,&force,f_c);
+       }
+       v3_scale(&temp,dist_ij,df_c*b*f_a);
+       v3_add(&force,&force,&temp);
+       v3_scale(&force,&force,-0.5);
+
+       /* add force */
+       v3_add(&(ai->f),&(ai->f),&force);
+
+       /* virial */
+       virial_calc(ai,&force,dist_ij);
+       //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: [%d %d sum]\n",ai->tag,aj->tag);
+       printf("adding %f %f %f\n",force.x,force.y,force.z);
+       printf("total i: %f %f %f\n",ai->f.x,ai->f.y,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 */
+       moldyn->energy+=(0.5*f_c*b*f_a);
+
+       /* dVji */
+       zeta=exchange->zeta_ji;
+       if(zeta==0.0) {
+               moldyn->debug++;
+               b=chi;
+               v3_scale(&force,dist_ij,df_a*b*f_c);
+       }
+       else {
+               tmp=betajnj*pow(zeta,nj-1.0);           /* beta^n * zeta^n-1 */
+               b=(1+zeta*tmp);                         /* 1 + beta^n zeta^n */
+               db=chi*pow(b,-1.0/(2*nj)-1);            /* x(...)^(-1/2n - 1) */
+               b=db*b;                                 /* b_ij */
+               db*=-0.5*tmp;                           /* db_ij */
+               v3_scale(&force,&(exchange->dzeta_ji),f_a*db);
+               v3_scale(&temp,dist_ij,df_a*b);
+               v3_add(&force,&force,&temp);
+               v3_scale(&force,&force,f_c);
+       }
+       v3_scale(&temp,dist_ij,df_c*b*f_a);
+       v3_add(&force,&force,&temp);
+       v3_scale(&force,&force,-0.5);
+
+       /* add force */
+       v3_add(&(ai->f),&(ai->f),&force);
+
+       /* virial - plus sign, as dist_ij = - dist_ji - (really??) */
+// TEST ... with a minus instead
+       virial_calc(ai,&force,dist_ij);
+       //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: [%d %d sum]\n",ai->tag,aj->tag);
+       printf("adding %f %f %f\n",force.x,force.y,force.z);
+       printf("total i: %f %f %f\n",ai->f.x,ai->f.y,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;
+}
+
+/* tersoff 3 body part */
+
+int tersoff_mult_3bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,t_atom *ak,u8 bc) {
+
+       t_tersoff_mult_params *params;
+       t_tersoff_exchange *exchange;
+       t_3dvec dist_ij,dist_ik,dist_jk;
+       t_3dvec temp1,temp2;
+       t_3dvec *dzeta;
+       double R,S,S2,s_r;
+       double B,mu;
+       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;
+       double f_c_jk;
+       double n,c,d,h;
+       double c2,d2,c2d2;
+       double cos_theta,d_costheta1,d_costheta2;
+       double h_cos,d2_h_cos2;
+       double frac,g,zeta,chi;
+       double tmp;
+       int brand;
+
+       params=moldyn->pot_params;
+       exchange=&(params->exchange);
+
+       if(!(exchange->run3bp))
+               return 0;
+
+       /*
+        * calc of 3bp contribution of V_ij and dV_ij/ji/jk &
+        * 2bp contribution of dV_jk
+        *
+        * for Vij and dV_ij we still need:
+        * - b_ij, db_ij (zeta_ij)
+        *   - f_c_ik, df_c_ik, constants_i, cos_theta_ijk, d_costheta_ijk
+        *
+        * for dV_ji we still need:
+        * - b_ji, db_ji (zeta_ji)
+        *   - f_c_jk, d_c_jk, constants_j, cos_theta_jik, d_costheta_jik
+        *
+        * for dV_jk we need:
+        * - f_c_jk
+        * - f_a_jk
+        * - db_jk (zeta_jk)
+        *   - f_c_ji, df_c_ji, constants_j, cos_theta_jki, d_costheta_jki
+        *
+        */
+
+       /*
+        * get exchange data 
+        */
+
+       /* 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;
+       df_c=exchange->df_c;
+
+       /*
+        * calculate unknown values now ...
+        */
+
+       /* V_ij and dV_ij stuff (in b_ij there is f_c_ik) */
+
+       /* dist_ik, d_ik */
+       v3_sub(&dist_ik,&(ak->r),&(ai->r));
+       if(bc) check_per_bound(moldyn,&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_ik2<S2) {
+
+               /* now we need d_ik */
+               d_ik=sqrt(d_ik2);
+
+               /* get constants_i from exchange data */
+               n=*(exchange->n_i);
+               c=*(exchange->c_i);
+               d=*(exchange->d_i);
+               h=*(exchange->h_i);
+               c2=exchange->ci2;
+               d2=exchange->di2;
+               c2d2=exchange->ci2di2;
+
+               /* cosine of theta_ijk by scalaproduct */
+               rr=v3_scalar_product(&dist_ij,&dist_ik);
+               dd=d_ij*d_ik;
+               cos_theta=rr/dd;
+
+               /* d_costheta */
+               tmp=1.0/dd;
+               d_costheta1=cos_theta/d_ij2-tmp;
+               d_costheta2=cos_theta/d_ik2-tmp;
+
+               /* some usefull values */
+               h_cos=(h-cos_theta);
+               d2_h_cos2=d2+(h_cos*h_cos);
+               frac=c2/(d2_h_cos2);
+
+               /* g(cos_theta) */
+               g=1.0+c2d2-frac;
+
+               /* d_costheta_ij and dg(cos_theta) - needed in any case! */
+               v3_scale(&temp1,&dist_ij,d_costheta1);
+               v3_scale(&temp2,&dist_ik,d_costheta2);
+               v3_add(&temp1,&temp1,&temp2);
+               v3_scale(&temp1,&temp1,-2.0*frac*h_cos/d2_h_cos2); /* dg */
+
+               /* f_c_ik & df_c_ik + {d,}zeta contribution */
+               dzeta=&(exchange->dzeta_ij);
+               if(d_ik<R) {
+                       /* {d,}f_c_ik */
+                       // => f_c_ik=1.0;
+                       // => df_c_ik=0.0; of course we do not set this!
+
+                       /* zeta_ij */
+                       exchange->zeta_ij+=g;
+
+                       /* dzeta_ij */
+                       v3_add(dzeta,dzeta,&temp1);
+               }
+               else {
+                       /* {d,}f_c_ik */
+                       s_r=S-R;
+                       arg=M_PI*(d_ik-R)/s_r;
+                       f_c_ik=0.5+0.5*cos(arg);
+                       df_c_ik=0.5*sin(arg)*(M_PI/(s_r*d_ik));
+
+                       /* zeta_ij */
+                       exchange->zeta_ij+=f_c_ik*g;
+
+                       /* dzeta_ij */
+                       v3_scale(&temp1,&temp1,f_c_ik);
+                       v3_scale(&temp2,&dist_ik,g*df_c_ik);
+                       v3_add(&temp1,&temp1,&temp2);
+                       v3_add(dzeta,dzeta,&temp1);
+               }
+       }
+
+       /* dV_ji stuff (in b_ji there is f_c_jk) + dV_jk stuff! */
+
+       /* dist_jk, d_jk */
+       v3_sub(&dist_jk,&(ak->r),&(aj->r));
+       if(bc) check_per_bound(moldyn,&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_jk2<S2) {
+
+               /* now we need d_ik */
+               d_jk=sqrt(d_jk2);
+
+               /* constants_j from exchange data */
+               n=*(exchange->n_j);
+               c=*(exchange->c_j);
+               d=*(exchange->d_j);
+               h=*(exchange->h_j);
+               c2=exchange->cj2;
+               d2=exchange->dj2;
+               c2d2=exchange->cj2dj2;
+
+               /* cosine of theta_jik by scalaproduct */
+               rr=-v3_scalar_product(&dist_ij,&dist_jk); /* -1, as ij -> ji */
+               dd=d_ij*d_jk;
+               cos_theta=rr/dd;
+
+               /* d_costheta */
+               d_costheta1=1.0/dd;
+               d_costheta2=cos_theta/d_ij2;
+
+               /* some usefull values */
+               h_cos=(h-cos_theta);
+               d2_h_cos2=d2+(h_cos*h_cos);
+               frac=c2/(d2_h_cos2);
+
+               /* g(cos_theta) */
+               g=1.0+c2d2-frac;
+
+               /* 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_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_copy(&temp2,&temp1);
+
+               /* f_c_jk + {d,}zeta contribution (df_c_jk = 0) */
+               dzeta=&(exchange->dzeta_ji);
+               if(d_jk<R) {
+                       /* f_c_jk */
+                       f_c_jk=1.0;
+
+                       /* zeta_ji */
+                       exchange->zeta_ji+=g;
+
+                       /* dzeta_ji */
+                       v3_add(dzeta,dzeta,&temp1);
+               }
+               else {
+                       /* f_c_jk */
+                       s_r=S-R;
+                       arg=M_PI*(d_jk-R)/s_r;
+                       f_c_jk=0.5+0.5*cos(arg);
+
+                       /* zeta_ji */
+                       exchange->zeta_ji+=f_c_jk*g;
+
+                       /* dzeta_ji */
+                       v3_scale(&temp1,&temp1,f_c_jk);
+                       v3_add(dzeta,dzeta,&temp1);
+               }
+
+               /* dV_jk stuff | add force contribution on atom i immediately */
+               if(exchange->d_ij_between_rs) {
+                       zeta=f_c*g;
+                       v3_scale(&temp1,&temp2,f_c);
+                       v3_scale(&temp2,&dist_ij,df_c*g);
+                       v3_add(&temp2,&temp2,&temp1); /* -> dzeta_jk in temp2 */
+               }
+               else {
+                       zeta=g;
+                       // dzeta_jk is simply dg, which is stored in temp2
+               }
+               /* betajnj * zeta_jk ^ nj-1 */
+               tmp=exchange->betajnj*pow(zeta,(n-1.0));
+               tmp=-chi/2.0*pow((1+tmp*zeta),(-1.0/(2.0*n)-1))*tmp;
+               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: [%d %d %d]\n",ai->tag,aj->tag,ak->tag);
+       printf("adding %f %f %f\n",temp2.x,temp2.y,temp2.z);
+       printf("total i: %f %f %f\n",ai->f.x,ai->f.y,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
+
+       }
+
+       return 0;
+}
+
diff --git a/potentials/tersoff_orig.h b/potentials/tersoff_orig.h
new file mode 100644 (file)
index 0000000..d5d4a66
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * tersoff_orig.h - tersoff potential header file
+ *
+ * author: Frank Zirkelbach <frank.zirkelbach@physik.uni-augsburg.de>
+ *
+ */
+
+#ifndef TERSOFF_H
+#define TERSOFF_H
+
+/* tersoff exchange type */
+typedef struct s_tersoff_echange {
+       double f_c,df_c;
+       double f_a,df_a;
+
+       t_3dvec dist_ij;
+       double d_ij2;
+       double d_ij;
+
+       double chi;
+
+       double *beta_i;
+       double *beta_j;
+       double *n_i;
+       double *n_j;
+       double *c_i;
+       double *c_j;
+       double *d_i;
+       double *d_j;
+       double *h_i;
+       double *h_j;
+
+       double ci2;
+       double cj2;
+       double di2;
+       double dj2;
+       double ci2di2;
+       double cj2dj2;
+       double betaini;
+       double betajnj;
+
+       u8 run3bp;
+       u8 run2bp_post;
+       u8 d_ij_between_rs;
+
+       double zeta_ij;
+       double zeta_ji;
+       t_3dvec dzeta_ij;
+       t_3dvec dzeta_ji;
+} t_tersoff_exchange;
+
+/* tersoff mult (2!) potential parameters */
+typedef struct s_tersoff_mult_params {
+       double S[2];            /* tersoff cutoff radii */
+       double S2[2];           /* tersoff cutoff radii squared */
+       double R[2];            /* tersoff cutoff radii */
+       double Smixed;          /* mixed S radius */
+       double S2mixed;         /* mixed S radius squared */
+       double Rmixed;          /* mixed R radius */
+       double A[2];            /* factor of tersoff attractive part */
+       double B[2];            /* factor of tersoff repulsive part */
+       double Amixed;          /* mixed A factor */
+       double Bmixed;          /* mixed B factor */
+       double lambda[2];       /* tersoff lambda */
+       double lambda_m;        /* mixed lambda */
+       double mu[2];           /* tersoff mu */
+       double mu_m;            /* mixed mu */
+
+       double chi;
+
+       double beta[2];
+       double n[2];
+       double c[2];
+       double d[2];
+       double h[2];
+
+       t_tersoff_exchange exchange;    /* exchange between 2bp and 3bp calc */
+} t_tersoff_mult_params;
+
+/* function prototypes */
+int tersoff_mult_complete_params(t_tersoff_mult_params *p);
+int tersoff_mult_1bp(t_moldyn *moldyn,t_atom *ai);
+int tersoff_mult_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc);
+int tersoff_mult_post_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc);
+int tersoff_mult_3bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,t_atom *ak,u8 bc);
+
+#endif
index 4fe42f77819c782a38881d10c9ac348af56183c9..bd4ce88a4198c647886938d36c6f3788ee66dc72 100644 (file)
@@ -87,10 +87,10 @@ set xtic auto \n\
 set ytic auto \n\
 set title 'Pressure vs. time' \n\
 set xlabel 'Time [fs]' \n\
-set ylabel 'Pressure [atm]' \n\
+set ylabel 'Pressure [bar]' \n\
 set terminal postscript eps enhanced color solid lw 1 'Helvetica' 14 \n\
 set output 'pressure.eps' \n\
-plot \"pressure\" using 1:2 title 'Pressure' with lines \
+plot \"pressure\" using 1:2 title 'P' with lines , \"pressure\" using 1:3 title '<P>' with lines , \"pressure\" using 1:4 title 'P (global virial)' with lines , \"pressure\" using 1:5 title '<P (global virial)>' with lines \
 ";
 
 static char temperature_plot_script[]="\
@@ -104,7 +104,7 @@ set xlabel 'Time [fs]' \n\
 set ylabel 'Temperature [K]' \n\
 set terminal postscript eps enhanced color solid lw 1 'Helvetica' 14 \n\
 set output 'temperature.eps' \n\
-plot \"temperature\" using 1:2 title 'Temperature' with lines \
+plot \"temperature\" using 1:2 title 'T' with lines , \"temperature\" using 1:3 title '<T>' with lines \
 ";
 
 #endif
diff --git a/sic.c b/sic.c
index 682d89ee6fcd46d96b1cb341b6c4b8d708a61a85..a78f3a0a9396318d91ddf5d3662eaeb2215e7ea9 100644 (file)
--- a/sic.c
+++ b/sic.c
 #include "potentials/harmonic_oscillator.h"
 #include "potentials/lennard_jones.h"
 #include "potentials/tersoff.h"
+//#include "potentials/tersoff_orig.h"
 
-#define INJECT         20
-#define NR_ATOMS       20      
+#define INJECT         1
+#define NR_ATOMS       4
 
 int hook(void *moldyn,void *hook_params) {
 
@@ -97,8 +98,13 @@ int main(int argc,char **argv) {
        /* choose potential */
        set_potential1b(&md,tersoff_mult_1bp);
        set_potential2b(&md,tersoff_mult_2bp);
-       set_potential2b_post(&md,tersoff_mult_post_2bp);
-       set_potential3b(&md,tersoff_mult_3bp);
+       //set_potential3b_j1(&md,tersoff_mult_2bp);
+       //set_potential3b_k1(&md,tersoff_mult_3bp);
+       //set_potential3b_j3(&md,tersoff_mult_post_2bp);
+       set_potential3b_j1(&md,tersoff_mult_3bp_j1);
+       set_potential3b_k1(&md,tersoff_mult_3bp_k1);
+       set_potential3b_j2(&md,tersoff_mult_3bp_j2);
+       set_potential3b_k2(&md,tersoff_mult_3bp_k2);
        //set_potential2b(&md,lennard_jones);
        //set_potential2b(&md,harmonic_oscillator);
        set_potential_params(&md,&tp);
@@ -198,7 +204,7 @@ int main(int argc,char **argv) {
 
        /* set temperature & pressure */
        set_temperature(&md,atof(argv[2])+273.0);
-       set_pressure(&md,ATM);
+       set_pressure(&md,BAR);
 
        /* set p/t scaling */
        //set_pt_scale(&md,P_SCALE_BERENDSEN,0.001,
@@ -211,14 +217,14 @@ int main(int argc,char **argv) {
 
        /* create the simulation schedule */
        /* initial configuration */
-       moldyn_add_schedule(&md,500,1.0);
+       moldyn_add_schedule(&md,10000,1.0);
        /* adding atoms */
-       for(inject=0;inject<INJECT;inject++) {
-               /* injecting atom and run with enabled t scaling */
-               moldyn_add_schedule(&md,400,1.0);
-               /* continue running with disabled t scaling */
-               moldyn_add_schedule(&md,100,1.0);
-       }
+       //for(inject=0;inject<INJECT;inject++) {
+       //      /* injecting atom and run with enabled t scaling */
+       //      moldyn_add_schedule(&md,900,1.0);
+       //      /* continue running with disabled t scaling */
+       //      moldyn_add_schedule(&md,1100,1.0);
+       //}
 
        /* schedule hook function */
        moldyn_set_schedule_hook(&md,&hook,NULL);
@@ -226,9 +232,9 @@ int main(int argc,char **argv) {
        /* activate logging */
        moldyn_set_log_dir(&md,argv[1]);
        moldyn_set_report(&md,"Frank Zirkelbach","Test 1");
-       moldyn_set_log(&md,LOG_TOTAL_ENERGY,10);
-       moldyn_set_log(&md,LOG_TEMPERATURE,10);
-       moldyn_set_log(&md,LOG_PRESSURE,10);
+       moldyn_set_log(&md,LOG_TOTAL_ENERGY,1);
+       moldyn_set_log(&md,LOG_TEMPERATURE,1);
+       moldyn_set_log(&md,LOG_PRESSURE,1);
        moldyn_set_log(&md,VISUAL_STEP,100);
        moldyn_set_log(&md,SAVE_STEP,100);
        moldyn_set_log(&md,CREATE_REPORT,0);