added harmonic potntial + bugfixes + boundings
[physik/posic.git] / moldyn.c
index ecba8ba..72a672a 100644 (file)
--- a/moldyn.c
+++ b/moldyn.c
@@ -14,6 +14,7 @@
 #include "math/math.h"
 #include "init/init.h"
 #include "random/random.h"
+#include "visual/visual.h"
 
 
 int create_lattice(unsigned char type,int element,double mass,double lc,
@@ -147,6 +148,21 @@ double get_e_kin(t_atom *atom,int count) {
        return e;
 }
 
+double get_e_pot(t_moldyn *moldyn) {
+
+       return(moldyn->potential(moldyn));
+}
+
+double get_total_energy(t_moldyn *moldyn) {
+
+       double e;
+
+       e=get_e_kin(moldyn->atom,moldyn->count);
+       e+=get_e_pot(moldyn);
+
+       return e;
+}
+
 t_3dvec get_total_p(t_atom *atom, int count) {
 
        t_3dvec p,p_total;
@@ -161,7 +177,168 @@ t_3dvec get_total_p(t_atom *atom, int count) {
        return p_total;
 }
 
-double potential_lennard_jones_2(t_moldyn *moldyn,void *ptr) {
+double estimate_time_step(t_moldyn *moldyn,double nn_dist,double t) {
+
+       double tau;
+
+       tau=0.05*nn_dist/(sqrt(3.0*K_BOLTZMANN*t/moldyn->atom[0].mass));
+       tau*=1.0E-9;
+       if(tau<moldyn->tau)
+               printf("[moldyn] warning: time step  (%f > %.15f)\n",
+                      moldyn->tau,tau);
+
+       return tau;     
+}
+
+
+/*
+ *
+ * 'integration of newtons equation' - algorithms
+ *
+ */
+
+/* start the integration */
+
+int moldyn_integrate(t_moldyn *moldyn) {
+
+       int i;
+       int write;
+
+       write=moldyn->write;
+
+       /* calculate initial forces */
+       moldyn->force(moldyn);
+
+       for(i=0;i<moldyn->time_steps;i++) {
+               /* integration step */
+               moldyn->integrate(moldyn);
+
+               /* check for visualiziation */
+               if(!(i%write)) {
+                       visual_atoms(moldyn->visual,i*moldyn->tau,
+                                    moldyn->atom,moldyn->count);
+               }
+       }
+
+       return 0;
+}
+
+/* velocity verlet */
+
+int velocity_verlet(t_moldyn *moldyn) {
+
+       int i,count;
+       double tau,tau_square;
+       t_3dvec delta;
+       t_atom *atom;
+
+       atom=moldyn->atom;
+       count=moldyn->count;
+       tau=moldyn->tau;
+
+       tau_square=tau*tau;
+
+       for(i=0;i<count;i++) {
+               /* new positions */
+               v3_scale(&delta,&(atom[i].v),tau);
+               v3_add(&(atom[i].r),&(atom[i].r),&delta);
+               v3_scale(&delta,&(atom[i].f),0.5*tau_square/atom[i].mass);
+               v3_add(&(atom[i].r),&(atom[i].r),&delta);
+               v3_per_bound(&(atom[i].r),&(moldyn->dim));
+
+               /* velocities */
+               v3_scale(&delta,&(atom[i].f),0.5*tau/atom[i].mass);
+               v3_add(&(atom[i].v),&(atom[i].v),&delta);
+       }
+
+       /* forces depending on chosen potential */
+       moldyn->force(moldyn);
+
+       for(i=0;i<count;i++) {
+               /* again velocities */
+               v3_scale(&delta,&(atom[i].f),0.5*tau/atom[i].mass);
+               v3_add(&(atom[i].v),&(atom[i].v),&delta);
+       }
+
+       return 0;
+}
+
+
+/*
+ *
+ * potentials & corresponding forces
+ * 
+ */
+
+/* harmonic oscillator potential and force */
+
+double potential_harmonic_oscillator(t_moldyn *moldyn) {
+
+       t_ho_params *params;
+       t_atom *atom;
+       int i,j;
+       int count;
+       t_3dvec distance;
+       double d,u;
+       double sc,equi_dist;
+
+       params=moldyn->pot_params;
+       atom=moldyn->atom;
+       sc=params->spring_constant;
+       equi_dist=params->equilibrium_distance;
+       count=moldyn->count;
+
+       u=0.0;
+       for(i=0;i<count;i++) {
+               for(j=0;j<i;j++) {
+                       v3_sub(&distance,&(atom[i].r),&(atom[j].r));
+                       d=v3_norm(&distance);
+                       u+=(0.5*sc*(d-equi_dist)*(d-equi_dist));
+               }
+       }
+
+       return u;
+}
+
+int force_harmonic_oscillator(t_moldyn *moldyn) {
+
+       t_ho_params *params;
+       int i,j,count;
+       t_atom *atom;
+       t_3dvec distance;
+       t_3dvec force;
+       double d;
+       double sc,equi_dist;
+
+       atom=moldyn->atom;      
+       count=moldyn->count;
+       params=moldyn->pot_params;
+       sc=params->spring_constant;
+       equi_dist=params->equilibrium_distance;
+
+       for(i=0;i<count;i++) v3_zero(&(atom[i].f));
+
+       for(i=0;i<count;i++) {
+               for(j=0;j<i;j++) {
+                       v3_sub(&distance,&(atom[i].r),&(atom[j].r));
+                       v3_per_bound(&distance,&(moldyn->dim));
+                       d=v3_norm(&distance);
+                       if(d<=moldyn->cutoff) {
+                               v3_scale(&force,&distance,
+                                        (-sc*(1.0-(equi_dist/d))));
+                               v3_add(&(atom[i].f),&(atom[i].f),&force);
+                               v3_sub(&(atom[j].f),&(atom[j].f),&force);
+                       }
+               }
+       }
+
+       return 0;
+}
+
+
+/* lennard jones potential & force for one sort of atoms */
+double potential_lennard_jones(t_moldyn *moldyn) {
 
        t_lj_params *params;
        t_atom *atom;
@@ -172,7 +349,7 @@ double potential_lennard_jones_2(t_moldyn *moldyn,void *ptr) {
        double u;
        double eps,sig6,sig12;
 
-       params=ptr;
+       params=moldyn->pot_params;
        atom=moldyn->atom;
        count=moldyn->count;
        eps=params->epsilon;
@@ -183,7 +360,7 @@ double potential_lennard_jones_2(t_moldyn *moldyn,void *ptr) {
        for(i=0;i<count;i++) {
                for(j=0;j<i;j++) {
                        v3_sub(&distance,&(atom[j].r),&(atom[i].r));
-                       d=v3_absolute_square(&distance);        /* 1/r^2 */
+                       d=1.0/v3_absolute_square(&distance);    /* 1/r^2 */
                        help=d*d;                               /* 1/r^4 */
                        help*=d;                                /* 1/r^6 */
                        d=help*help;                            /* 1/r^12 */
@@ -194,4 +371,47 @@ double potential_lennard_jones_2(t_moldyn *moldyn,void *ptr) {
        return u;
 }
 
+int force_lennard_jones(t_moldyn *moldyn) {
+
+       t_lj_params *params;
+       int i,j,count;
+       t_atom *atom;
+       t_3dvec distance;
+       t_3dvec force;
+       double d,h1,h2;
+       double eps,sig6,sig12;
+
+       atom=moldyn->atom;      
+       count=moldyn->count;
+       params=moldyn->pot_params;
+       eps=params->epsilon;
+       sig6=params->sigma6;
+       sig12=params->sigma12;
+
+       for(i=0;i<count;i++) v3_zero(&(atom[i].f));
+
+       for(i=0;i<count;i++) {
+               for(j=0;j<i;j++) {
+                       v3_sub(&distance,&(atom[j].r),&(atom[i].r));
+                       v3_per_bound(&distance,&(moldyn->dim));
+                       d=v3_absolute_square(&distance);
+                       if(d<=moldyn->cutoff_square) {
+                               h1=1.0/d;                       /* 1/r^2 */
+                               d=h1*h1;                        /* 1/r^4 */
+                               h2=d*d;                         /* 1/r^8 */
+                               h1*=d;                          /* 1/r^6 */
+                               h1*=h2;                         /* 1/r^14 */
+                               h1*=sig12;
+                               h2*=sig6;
+                               d=12.0*h1-6.0*h2;
+                               d*=eps;
+                               v3_scale(&force,&distance,d);
+                               v3_add(&(atom[j].f),&(atom[j].f),&force);
+                               v3_sub(&(atom[i].f),&(atom[i].f),&force);
+                       }
+               }
+       }
+
+       return 0;
+}