#include <time.h>
#include <math.h>
+#include <fpu_control.h>
+
+#ifdef PARALLEL
+#include <omp.h>
+#endif
+
#include "moldyn.h"
#include "report/report.h"
#include "potentials/tersoff.h"
#endif
+/* pse */
+#define PSE_NAME
+#define PSE_COL
+#include "pse.h"
+#undef PSE_NAME
+#undef PSE_COL
+
/*
* the moldyn functions
*/
printf("[moldyn] init\n");
+ /* only needed if compiled without -msse2 (float-store prob!) */
+ //fpu_set_rtd();
+
memset(moldyn,0,sizeof(t_moldyn));
moldyn->argc=argc;
}
moldyn->atom=ptr;
+#ifdef LOWMEM_LISTS
+ ptr=realloc(moldyn->lc.subcell->list,(count+1)*sizeof(int));
+ if(!ptr) {
+ perror("[moldyn] list realloc (add atom)");
+ return -1;
+ }
+ moldyn->lc.subcell->list=ptr;
+#endif
+
atom=moldyn->atom;
/* initialize new atom */
scale*=2.0;
else
if(moldyn->pt_scale&T_SCALE_BERENDSEN)
- scale=1.0+(scale-1.0)/moldyn->t_tc;
+ scale=1.0+(scale-1.0)*moldyn->tau/moldyn->t_tc;
scale=sqrt(scale);
/* velocity scaling */
/* scaling factor */
if(moldyn->pt_scale&P_SCALE_BERENDSEN) {
- scale=1.0-(moldyn->p_ref-moldyn->p)*moldyn->p_tc;
+ scale=1.0-(moldyn->p_ref-moldyn->p)*moldyn->p_tc*moldyn->tau;
scale=pow(scale,ONE_THIRD);
}
else {
int link_cell_init(t_moldyn *moldyn,u8 vol) {
t_linkcell *lc;
+#ifndef LOWMEM_LISTS
int i;
+#endif
lc=&(moldyn->lc);
#ifdef STATIC_LISTS
lc->subcell=malloc(lc->cells*sizeof(int*));
+#elif LOWMEM_LISTS
+ lc->subcell=malloc(sizeof(t_lowmem_list));
#else
lc->subcell=malloc(lc->cells*sizeof(t_list));
#endif
}
if(lc->cells<27)
- printf("[moldyn] FATAL: less then 27 subcells!\n");
+ printf("[moldyn] FATAL: less then 27 subcells! (%d)\n",
+ lc->cells);
if(vol) {
#ifdef STATIC_LISTS
printf("[moldyn] initializing 'static' linked cells (%d)\n",
lc->cells);
+#elif LOWMEM_LISTS
+ printf("[moldyn] initializing 'lowmem' linked cells (%d)\n",
+ lc->cells);
#else
printf("[moldyn] initializing 'dynamic' linked cells (%d)\n",
lc->cells);
i,lc->subcell[0],lc->subcell);
*/
}
+#elif LOWMEM_LISTS
+ lc->subcell->head=malloc(lc->cells*sizeof(int));
+ if(lc->subcell->head==NULL) {
+ perror("[moldyn] head init (malloc)");
+ return -1;
+ }
+ lc->subcell->list=malloc(moldyn->count*sizeof(int));
+ if(lc->subcell->list==NULL) {
+ perror("[moldyn] list init (malloc)");
+ return -1;
+ }
#else
for(i=0;i<lc->cells;i++)
list_init_f(&(lc->subcell[i]));
int link_cell_update(t_moldyn *moldyn) {
int count,i,j,k;
- int nx,ny;
+ int nx,nxy;
t_atom *atom;
t_linkcell *lc;
#ifdef STATIC_LISTS
int p;
+#elif LOWMEM_LISTS
+ int p;
#endif
atom=moldyn->atom;
lc=&(moldyn->lc);
nx=lc->nx;
- ny=lc->ny;
+ nxy=nx*lc->ny;
for(i=0;i<lc->cells;i++)
#ifdef STATIC_LISTS
- memset(lc->subcell[i],0,(MAX_ATOMS_PER_LIST+1)*sizeof(int));
+ memset(lc->subcell[i],-1,(MAX_ATOMS_PER_LIST+1)*sizeof(int));
+#elif LOWMEM_LISTS
+ lc->subcell->head[i]=-1;
#else
list_destroy_f(&(lc->subcell[i]));
#endif
#ifdef STATIC_LISTS
p=0;
- while(lc->subcell[i+j*nx+k*nx*ny][p]!=0)
+ while(lc->subcell[i+j*nx+k*nxy][p]!=-1)
p++;
if(p>=MAX_ATOMS_PER_LIST) {
return -1;
}
- lc->subcell[i+j*nx+k*nx*ny][p]=count;
+ lc->subcell[i+j*nx+k*nxy][p]=count;
+#elif LOWMEM_LISTS
+ p=i+j*nx+k*nxy;
+ lc->subcell->list[count]=lc->subcell->head[p];
+ lc->subcell->head[p]=count;
#else
- list_add_immediate_f(&(lc->subcell[i+j*nx+k*nx*ny]),
+ list_add_immediate_f(&(lc->subcell[i+j*nx+k*nxy]),
&(atom[count]));
/*
if(j==0&&k==0)
int link_cell_neighbour_index(t_moldyn *moldyn,int i,int j,int k,
#ifdef STATIC_LISTS
int **cell
+#elif LOWMEM_LISTS
+ int *cell
#else
t_list *cell
#endif
printf("[moldyn] WARNING: lcni %d/%d %d/%d %d/%d\n",
i,nx,j,ny,k,nz);
+#ifndef LOWMEM_LISTS
cell[0]=lc->subcell[i+j*nx+k*a];
+#else
+ cell[0]=lc->subcell->head[i+j*nx+k*a];
+#endif
for(ci=-1;ci<=1;ci++) {
bx=0;
x=i+ci;
}
if(!(ci|cj|ck)) continue;
if(bx|by|bz) {
+#ifndef LOWMEM_LISTS
cell[--count2]=lc->subcell[x+y*nx+z*a];
+#else
+ cell[--count2]=lc->subcell->head[x+y*nx+z*a];
+#endif
+
}
else {
+#ifndef LOWMEM_LISTS
cell[count1++]=lc->subcell[x+y*nx+z*a];
+#else
+ cell[count1++]=lc->subcell->head[x+y*nx+z*a];
+#endif
}
}
}
int link_cell_shutdown(t_moldyn *moldyn) {
+#ifndef LOWMEM_LISTS
int i;
+#endif
t_linkcell *lc;
lc=&(moldyn->lc);
+#if LOWMEM_LISTS
+ free(lc->subcell->head);
+ free(lc->subcell->list);
+
+#else
+
for(i=0;i<lc->cells;i++) {
#ifdef STATIC_LISTS
free(lc->subcell[i]);
list_destroy_f(&(lc->subcell[i]));
#endif
}
+#endif
free(lc->subcell);
}
/* display progress */
- //if(!(moldyn->total_steps%10)) {
+ if(!(moldyn->total_steps%10)) {
/* get current time */
gettimeofday(&t2,NULL);
/* copy over time */
t1=t2;
- //}
+ }
/* increase absolute time */
moldyn->time+=moldyn->tau;
link_cell_update(moldyn);
/* forces depending on chosen potential */
+#ifndef ALBE_FAST
potential_force_calc(moldyn);
+#else
+ albe_potential_force_calc(moldyn);
+#endif
for(i=0;i<count;i++) {
/* check whether fixed atom */
int *neighbour_i[27];
int p,q;
t_atom *atom;
+#elif LOWMEM_LISTS
+ int neighbour_i[27];
+ int p,q;
#else
t_list neighbour_i[27];
t_list neighbour_i2[27];
memset(&(moldyn->gvir),0,sizeof(t_virial));
/* reset force, site energy and virial of every atom */
+#ifdef PARALLEL
+ i=omp_get_thread_num();
+ #pragma omp parallel for private(virial)
+#endif
for(i=0;i<count;i++) {
/* reset force */
#ifdef STATIC_LISTS
p=0;
- while(neighbour_i[j][p]!=0) {
+ while(neighbour_i[j][p]!=-1) {
jtom=&(atom[neighbour_i[j][p]]);
p++;
+#elif LOWMEM_LISTS
+ p=neighbour_i[j];
- if(jtom==&(itom[i]))
- continue;
+ while(p!=-1) {
- if((jtom->attr&ATOM_ATTR_2BP)&
- (itom[i].attr&ATOM_ATTR_2BP)) {
- moldyn->func2b(moldyn,
- &(itom[i]),
- jtom,
- bc_ij);
- }
- }
+ jtom=&(itom[p]);
+ p=lc->subcell->list[p];
#else
this=&(neighbour_i[j]);
list_reset_f(this);
do {
jtom=this->current->data;
+#endif
if(jtom==&(itom[i]))
continue;
jtom,
bc_ij);
}
+#ifdef STATIC_LISTS
+ }
+#elif LOWMEM_LISTS
+ }
+#else
} while(list_next_f(this)!=L_NO_NEXT_ELEMENT);
#endif
/* copy the neighbour lists */
#ifdef STATIC_LISTS
/* no copy needed for static lists */
+#elif LOWMEM_LISTS
+ /* no copy needed for lowmem lists */
#else
memcpy(neighbour_i2,neighbour_i,27*sizeof(t_list));
#endif
#ifdef STATIC_LISTS
p=0;
- while(neighbour_i[j][p]!=0) {
+ while(neighbour_i[j][p]!=-1) {
jtom=&(atom[neighbour_i[j][p]]);
p++;
+#elif LOWMEM_LISTS
+ p=neighbour_i[j];
+
+ while(p!=-1) {
+
+ jtom=&(itom[p]);
+ p=lc->subcell->list[p];
#else
this=&(neighbour_i[j]);
list_reset_f(this);
#ifdef STATIC_LISTS
q=0;
- while(neighbour_i[j][q]!=0) {
+ while(neighbour_i[k][q]!=-1) {
ktom=&(atom[neighbour_i[k][q]]);
q++;
+#elif LOWMEM_LISTS
+ q=neighbour_i[k];
+
+ while(q!=-1) {
+
+ ktom=&(itom[q]);
+ q=lc->subcell->list[q];
#else
that=&(neighbour_i2[k]);
list_reset_f(that);
bc_ik|bc_ij);
#ifdef STATIC_LISTS
}
+#elif LOWMEM_LISTS
+ }
#else
} while(list_next_f(that)!=\
L_NO_NEXT_ELEMENT);
#ifdef STATIC_LISTS
q=0;
- while(neighbour_i[j][q]!=0) {
+ while(neighbour_i[k][q]!=-1) {
ktom=&(atom[neighbour_i[k][q]]);
q++;
+#elif LOWMEM_LISTS
+ q=neighbour_i[k];
+
+ while(q!=-1) {
+
+ ktom=&(itom[q]);
+ q=lc->subcell->list[q];
#else
that=&(neighbour_i2[k]);
list_reset_f(that);
#ifdef STATIC_LISTS
}
+#elif LOWMEM_LISTS
+ }
#else
} while(list_next_f(that)!=\
L_NO_NEXT_ELEMENT);
}
#ifdef STATIC_LISTS
}
+#elif LOWMEM_LISTS
+ }
#else
} while(list_next_f(this)!=L_NO_NEXT_ELEMENT);
#endif
#endif
/* some postprocessing */
+#ifdef PARALLEL
+ #pragma omp parallel for
+#endif
for(i=0;i<count;i++) {
/* calculate global virial */
moldyn->gvir.xx+=itom[i].r.x*itom[i].f.x;
/* check forces regarding the given timestep */
if(v3_norm(&(itom[i].f))>\
- 0.1*moldyn->nnd*itom[i].mass/moldyn->tau_square)
+ 0.1*moldyn->nnd*itom[i].mass/moldyn->tau_square)
printf("[moldyn] WARNING: pfc (high force: atom %d)\n",
i);
}
#ifdef STATIC_LISTS
int *neighbour[27];
int p;
+#elif LOWMEM_LISTS
+ int neighbour[27];
+ int p;
#else
t_list neighbour[27];
+ t_list *this;
#endif
u8 bc;
t_atom *itom,*jtom;
int i,j;
- t_list *this;
lc=&(moldyn->lc);
itom=moldyn->atom;
#ifdef STATIC_LISTS
p=0;
- while(neighbour[j][p]!=0) {
+ while(neighbour[j][p]!=-1) {
jtom=&(moldyn->atom[neighbour[j][p]]);
p++;
+#elif LOWMEM_LISTS
+ p=neighbour[j];
+
+ while(p!=-1) {
+
+ jtom=&(itom[p]);
+ p=lc->subcell->list[p];
#else
this=&(neighbour[j]);
list_reset_f(this);
#ifdef STATIC_LISTS
}
+#elif LOWMEM_LISTS
+ }
#else
} while(list_next_f(this)!=L_NO_NEXT_ELEMENT);
#endif
}
+/*
+ * function to find neighboured atoms
+ */
+
+int process_neighbours(t_moldyn *moldyn,void *data,t_atom *atom,
+ int (*process)(t_moldyn *moldyn,t_atom *atom,t_atom *natom,
+ void *data,u8 bc)) {
+
+ t_linkcell *lc;
+#ifdef STATIC_LISTS
+ int *neighbour[27];
+ int p;
+#elif LOWMEM_LISTS
+ int neighbour[27];
+ int p;
+#else
+ t_list neighbour[27];
+ t_list *this;
+#endif
+ u8 bc;
+ t_atom *natom;
+ int j;
+
+ lc=&(moldyn->lc);
+
+ /* neighbour indexing */
+ link_cell_neighbour_index(moldyn,
+ (atom->r.x+moldyn->dim.x/2)/lc->x,
+ (atom->r.y+moldyn->dim.y/2)/lc->x,
+ (atom->r.z+moldyn->dim.z/2)/lc->x,
+ neighbour);
+
+ for(j=0;j<27;j++) {
+
+ bc=(j<lc->dnlc)?0:1;
+
+#ifdef STATIC_LISTS
+ p=0;
+
+ while(neighbour[j][p]!=-1) {
+
+ natom=&(moldyn->atom[neighbour[j][p]]);
+ p++;
+#elif LOWMEM_LISTS
+ p=neighbour[j];
+
+ while(p!=-1) {
+
+ natom=&(moldyn->atom[p]);
+ p=lc->subcell->list[p];
+#else
+ this=&(neighbour[j]);
+ list_reset_f(this);
+
+ if(this->start==NULL)
+ continue;
+
+ do {
+
+ natom=this->current->data;
+#endif
+
+ /* process bond */
+ process(moldyn,atom,natom,data,bc);
+
+#ifdef STATIC_LISTS
+ }
+#elif LOWMEM_LISTS
+ }
+#else
+ } while(list_next_f(this)!=L_NO_NEXT_ELEMENT);
+#endif
+ }
+
+ return 0;
+
+}
+
/*
* post processing functions
*/
return 0;
}
+/*
+ * fpu cntrol functions
+ */
+
+// set rounding to double (eliminates -ffloat-store!)
+int fpu_set_rtd(void) {
+
+ fpu_control_t ctrl;
+
+ _FPU_GETCW(ctrl);
+
+ ctrl&=~_FPU_EXTENDED;
+ ctrl|=_FPU_DOUBLE;
+
+ _FPU_SETCW(ctrl);
+
+ return 0;
+}
+