X-Git-Url: https://hackdaworld.org/gitweb/?a=blobdiff_plain;f=moldyn.c;h=817a72788b45f2572258873aaa8ca64cace0397f;hb=f3e4193447ac49a8953515910d4b4e6ce2c7608b;hp=c21f59f516df771c5153db16232bd844db6064a8;hpb=115ab83cedba54af2d165b8900781b98c5326b55;p=physik%2Fposic.git diff --git a/moldyn.c b/moldyn.c index c21f59f..817a727 100644 --- a/moldyn.c +++ b/moldyn.c @@ -19,6 +19,8 @@ int moldyn_init(t_moldyn *moldyn,int argc,char **argv) { + printf("[moldyn] init\n"); + memset(moldyn,0,sizeof(t_moldyn)); rand_init(&(moldyn->random),NULL,1); @@ -30,6 +32,7 @@ int moldyn_init(t_moldyn *moldyn,int argc,char **argv) { int moldyn_shutdown(t_moldyn *moldyn) { printf("[moldyn] shutdown\n"); + moldyn_log_shutdown(moldyn); link_cell_shutdown(moldyn); rand_close(&(moldyn->random)); @@ -40,12 +43,16 @@ int moldyn_shutdown(t_moldyn *moldyn) { int set_int_alg(t_moldyn *moldyn,u8 algo) { + printf("[moldyn] integration algorithm: "); + switch(algo) { case MOLDYN_INTEGRATE_VERLET: moldyn->integrate=velocity_verlet; + printf("velocity verlet\n"); break; default: printf("unknown integration algorithm: %02x\n",algo); + printf("unknown\n"); return -1; } @@ -56,6 +63,8 @@ int set_cutoff(t_moldyn *moldyn,double cutoff) { moldyn->cutoff=cutoff; + printf("[moldyn] cutoff [A]: %f\n",moldyn->cutoff); + return 0; } @@ -63,6 +72,8 @@ int set_temperature(t_moldyn *moldyn,double t_ref) { moldyn->t_ref=t_ref; + printf("[moldyn] temperature: %f\n",moldyn->t_ref); + return 0; } @@ -70,6 +81,8 @@ int set_pressure(t_moldyn *moldyn,double p_ref) { moldyn->p_ref=p_ref; + printf("[moldyn] pressure: %f\n",moldyn->p_ref); + return 0; } @@ -79,6 +92,18 @@ int set_pt_scale(t_moldyn *moldyn,u8 ptype,double ptc,u8 ttype,double ttc) { moldyn->t_tc=ttc; moldyn->p_tc=ptc; + printf("[moldyn] p/t scaling:\n"); + + printf(" p: %s",ptype?"yes":"no "); + if(ptype) + printf(" | type: %02x | factor: %f",ptype,ptc); + printf("\n"); + + printf(" t: %s",ttype?"yes":"no "); + if(ttype) + printf(" | type: %02x | factor: %f",ttype,ttc); + printf("\n"); + return 0; } @@ -96,12 +121,15 @@ int set_dim(t_moldyn *moldyn,double x,double y,double z,u8 visualize) { moldyn->vis.dim.z=z; } + moldyn->dv=0.000001*moldyn->volume; + printf("[moldyn] dimensions in A and A^3 respectively:\n"); printf(" x: %f\n",moldyn->dim.x); printf(" y: %f\n",moldyn->dim.y); printf(" z: %f\n",moldyn->dim.z); printf(" volume: %f\n",moldyn->volume); - printf(" visualize simulation box: %s\n",visualize?"on":"off"); + printf(" visualize simulation box: %s\n",visualize?"yes":"no"); + printf(" delta volume (pressure calc): %f\n",moldyn->dv); return 0; } @@ -115,6 +143,8 @@ int set_nn_dist(t_moldyn *moldyn,double dist) { int set_pbc(t_moldyn *moldyn,u8 x,u8 y,u8 z) { + printf("[moldyn] periodic boundary conditions:\n"); + if(x) moldyn->status|=MOLDYN_STAT_PBX; @@ -124,6 +154,10 @@ int set_pbc(t_moldyn *moldyn,u8 x,u8 y,u8 z) { if(z) moldyn->status|=MOLDYN_STAT_PBZ; + printf(" x: %s\n",x?"yes":"no"); + printf(" y: %s\n",y?"yes":"no"); + printf(" z: %s\n",z?"yes":"no"); + return 0; } @@ -165,12 +199,22 @@ int moldyn_set_log_dir(t_moldyn *moldyn,char *dir) { return 0; } + +int moldyn_set_report(t_moldyn *moldyn,char *author,char *title) { + + strncpy(moldyn->rauthor,author,63); + strncpy(moldyn->rtitle,title,63); + + return 0; +} int moldyn_set_log(t_moldyn *moldyn,u8 type,int timer) { char filename[128]; int ret; + printf("[moldyn] set log: "); + switch(type) { case LOG_TOTAL_ENERGY: moldyn->ewrite=timer; @@ -183,6 +227,7 @@ int moldyn_set_log(t_moldyn *moldyn,u8 type,int timer) { return moldyn->efd; } dprintf(moldyn->efd,"# total energy log file\n"); + printf("total energy (%d)\n",timer); break; case LOG_TOTAL_MOMENTUM: moldyn->mwrite=timer; @@ -195,9 +240,11 @@ int moldyn_set_log(t_moldyn *moldyn,u8 type,int timer) { return moldyn->mfd; } dprintf(moldyn->efd,"# total momentum log file\n"); + printf("total momentum (%d)\n",timer); break; case SAVE_STEP: moldyn->swrite=timer; + printf("save file (%d)\n",timer); break; case VISUAL_STEP: moldyn->vwrite=timer; @@ -206,9 +253,32 @@ int moldyn_set_log(t_moldyn *moldyn,u8 type,int timer) { printf("[moldyn] visual init failure\n"); return ret; } + printf("visual file (%d)\n",timer); + break; + case CREATE_REPORT: + snprintf(filename,127,"%s/report.tex",moldyn->vlsdir); + moldyn->rfd=open(filename, + O_WRONLY|O_CREAT|O_EXCL, + S_IRUSR|S_IWUSR); + if(moldyn->rfd<0) { + perror("[moldyn] report fd open"); + return moldyn->rfd; + } + snprintf(filename,127,"%s/plot.scr",moldyn->vlsdir); + moldyn->pfd=open(filename, + O_WRONLY|O_CREAT|O_EXCL, + S_IRUSR|S_IWUSR); + if(moldyn->pfd<0) { + perror("[moldyn] plot fd open"); + return moldyn->pfd; + } + dprintf(moldyn->rfd,report_start, + moldyn->rauthor,moldyn->rtitle); + dprintf(moldyn->pfd,plot_script); + close(moldyn->pfd); break; default: - printf("[moldyn] unknown log mechanism: %02x\n",type); + printf("unknown log type: %02x\n",type); return -1; } @@ -217,9 +287,23 @@ int moldyn_set_log(t_moldyn *moldyn,u8 type,int timer) { int moldyn_log_shutdown(t_moldyn *moldyn) { + char sc[256]; + printf("[moldyn] log shutdown\n"); if(moldyn->efd) close(moldyn->efd); if(moldyn->mfd) close(moldyn->mfd); + if(moldyn->rfd) { + dprintf(moldyn->rfd,report_end); + close(moldyn->rfd); + snprintf(sc,255,"cd %s && gnuplot plot.scr",moldyn->vlsdir); + system(sc); + snprintf(sc,255,"cd %s && pdflatex report",moldyn->vlsdir); + system(sc); + snprintf(sc,255,"cd %s && pdflatex report",moldyn->vlsdir); + system(sc); + snprintf(sc,255,"cd %s && dvipdf report",moldyn->vlsdir); + system(sc); + } if(&(moldyn->vis)) visual_tini(&(moldyn->vis)); return 0; @@ -242,6 +326,7 @@ int create_lattice(t_moldyn *moldyn,u8 type,double lc,int element,double mass, count=moldyn->count; /* how many atoms do we expect */ + if(type==CUBIC) new*=1; if(type==FCC) new*=4; if(type==DIAMOND) new*=8; @@ -257,8 +342,11 @@ int create_lattice(t_moldyn *moldyn,u8 type,double lc,int element,double mass, v3_zero(&origin); switch(type) { + case CUBIC: + ret=cubic_init(a,b,c,lc,atom,NULL); + break; case FCC: - ret=fcc_init(a,b,c,lc,atom,&origin); + ret=fcc_init(a,b,c,lc,atom,NULL); break; case DIAMOND: ret=diamond_init(a,b,c,lc,atom,&origin); @@ -292,6 +380,44 @@ int create_lattice(t_moldyn *moldyn,u8 type,double lc,int element,double mass, return ret; } +/* cubic init */ +int cubic_init(int a,int b,int c,double lc,t_atom *atom,t_3dvec *origin) { + + int count; + t_3dvec r; + int i,j,k; + t_3dvec o; + + count=0; + if(origin) + v3_copy(&o,origin); + else + v3_zero(&o); + + r.x=o.x; + for(i=0;iatom; random=&(moldyn->random); + printf("[moldyn] thermal init (equi init: %s)\n",equi_init?"yes":"no"); + /* gaussian distribution of velocities */ v3_zero(&p_total); for(i=0;icount;i++) { @@ -460,6 +588,29 @@ int thermal_init(t_moldyn *moldyn,u8 equi_init) { return 0; } +double temperature_calc(t_moldyn *moldyn) { + + double double_ekin; + int i; + t_atom *atom; + + atom=moldyn->atom; + + double_ekin=0; + for(i=0;icount;i++) + double_ekin+=atom[i].mass*v3_absolute_square(&(atom[i].v)); + + /* kinetic energy = 3/2 N k_B T */ + moldyn->t=double_ekin/(3.0*K_BOLTZMANN*moldyn->count); + + return moldyn->t; +} + +double get_temperature(t_moldyn *moldyn) { + + return moldyn->t; +} + int scale_velocity(t_moldyn *moldyn,u8 equi_init) { int i; @@ -478,10 +629,11 @@ int scale_velocity(t_moldyn *moldyn,u8 equi_init) { count=0; for(i=0;icount;i++) { if((equi_init&TRUE)||(atom[i].attr&ATOM_ATTR_HB)) { - e+=0.5*atom[i].mass*v3_absolute_square(&(atom[i].v)); + e+=atom[i].mass*v3_absolute_square(&(atom[i].v)); count+=1; } } + e*=0.5; if(count!=0) moldyn->t=e/(1.5*count*K_BOLTZMANN); else return 0; /* no atoms involved in scaling! */ @@ -515,6 +667,157 @@ int scale_velocity(t_moldyn *moldyn,u8 equi_init) { return 0; } +double ideal_gas_law_pressure(t_moldyn *moldyn) { + + double p; + + p=moldyn->count*moldyn->t*K_BOLTZMANN/moldyn->volume; + + return p; +} + +double pressure_calc(t_moldyn *moldyn) { + + int i; + double v; + t_virial *virial; + + v=0.0; + for(i=0;icount;i++) { + virial=&(moldyn->atom[i].virial); + v+=(virial->xx+virial->yy+virial->zz); + } + v*=ONE_THIRD; +printf("kieck mal: %f %f %f\n",v,moldyn->count*K_BOLTZMANN*moldyn->t,v/moldyn->count); + + moldyn->p=moldyn->count*K_BOLTZMANN*moldyn->t+v; + moldyn->p/=moldyn->volume; + + return moldyn->p; +} + +double thermodynamic_pressure_calc(t_moldyn *moldyn) { + + t_3dvec dim,*tp; + double u,p; + double scale; + t_atom *store; + + tp=&(moldyn->tp); + store=malloc(moldyn->count*sizeof(t_atom)); + if(store==NULL) { + printf("[moldyn] allocating store mem failed\n"); + return -1; + } + + /* save unscaled potential energy + atom/dim configuration */ + u=moldyn->energy; + memcpy(store,moldyn->atom,moldyn->count*sizeof(t_atom)); + dim=moldyn->dim; + + /* derivative with respect to x direction */ + scale=1.0+moldyn->dv/(moldyn->dim.y*moldyn->dim.z); + scale_dim(moldyn,scale,TRUE,0,0); + scale_atoms(moldyn,scale,TRUE,0,0); + link_cell_shutdown(moldyn); + link_cell_init(moldyn); + potential_force_calc(moldyn); + tp->x=(moldyn->energy-u)/moldyn->dv; + p=tp->x*tp->x; + + /* restore atomic configuration + dim */ + memcpy(moldyn->atom,store,moldyn->count*sizeof(t_atom)); + moldyn->dim=dim; + + /* derivative with respect to y direction */ + scale=1.0+moldyn->dv/(moldyn->dim.x*moldyn->dim.z); + scale_dim(moldyn,scale,0,TRUE,0); + scale_atoms(moldyn,scale,0,TRUE,0); + link_cell_shutdown(moldyn); + link_cell_init(moldyn); + potential_force_calc(moldyn); + tp->y=(moldyn->energy-u)/moldyn->dv; + p+=tp->y*tp->y; + + /* restore atomic configuration + dim */ + memcpy(moldyn->atom,store,moldyn->count*sizeof(t_atom)); + moldyn->dim=dim; + + /* derivative with respect to z direction */ + scale=1.0+moldyn->dv/(moldyn->dim.x*moldyn->dim.y); + scale_dim(moldyn,scale,0,0,TRUE); + scale_atoms(moldyn,scale,0,0,TRUE); + link_cell_shutdown(moldyn); + link_cell_init(moldyn); + potential_force_calc(moldyn); + tp->z=(moldyn->energy-u)/moldyn->dv; + p+=tp->z*tp->z; + + /* restore atomic configuration + dim */ + memcpy(moldyn->atom,store,moldyn->count*sizeof(t_atom)); + moldyn->dim=dim; + + printf("dU/dV komp addiert = %f %f %f\n",tp->x,tp->y,tp->z); + + scale=1.0+pow(moldyn->dv/moldyn->volume,ONE_THIRD); + +printf("debug: %f %f\n",moldyn->atom[0].r.x,moldyn->dim.x); + scale_dim(moldyn,scale,1,1,1); + scale_atoms(moldyn,scale,1,1,1); + link_cell_shutdown(moldyn); + link_cell_init(moldyn); + potential_force_calc(moldyn); +printf("debug: %f %f\n",moldyn->atom[0].r.x,moldyn->dim.x); + + printf("dU/dV einfach = %f\n",((moldyn->energy-u)/moldyn->dv)/ATM); + + /* restore atomic configuration + dim */ + memcpy(moldyn->atom,store,moldyn->count*sizeof(t_atom)); + moldyn->dim=dim; + + /* restore energy */ + moldyn->energy=u; + + link_cell_shutdown(moldyn); + link_cell_init(moldyn); + + return sqrt(p); +} + +double get_pressure(t_moldyn *moldyn) { + + return moldyn->p; + +} + +int scale_dim(t_moldyn *moldyn,double scale,u8 x,u8 y,u8 z) { + + t_3dvec *dim; + + dim=&(moldyn->dim); + + if(x) dim->x*=scale; + if(y) dim->y*=scale; + if(z) dim->z*=scale; + + return 0; +} + +int scale_atoms(t_moldyn *moldyn,double scale,u8 x,u8 y,u8 z) { + + int i; + t_3dvec *r; + + for(i=0;icount;i++) { + r=&(moldyn->atom[i].r); + if(x) r->x*=scale; + if(y) r->y*=scale; + if(z) r->z*=scale; + } + + return 0; +} + int scale_volume(t_moldyn *moldyn) { t_atom *atom; @@ -592,11 +895,6 @@ double get_e_kin(t_moldyn *moldyn) { return moldyn->ekin; } -double get_e_pot(t_moldyn *moldyn) { - - return moldyn->energy; -} - double update_e_kin(t_moldyn *moldyn) { return(get_e_kin(moldyn)); @@ -659,6 +957,9 @@ int link_cell_init(t_moldyn *moldyn) { lc->cells=lc->nx*lc->ny*lc->nz; lc->subcell=malloc(lc->cells*sizeof(t_list)); + if(lc->cells<27) + printf("[moldyn] FATAL: less then 27 subcells!\n"); + printf("[moldyn] initializing linked cells (%d)\n",lc->cells); for(i=0;icells;i++) @@ -797,10 +1098,14 @@ int moldyn_add_schedule(t_moldyn *moldyn,int runs,double tau) { schedule->tau=ptr; schedule->tau[count-1]=tau; + printf("[moldyn] schedule added:\n"); + printf(" number: %d | runs: %d | tau: %f\n",count-1,runs,tau); + + return 0; } -int moldyn_set_schedule_hook(t_moldyn *moldyn,void *hook,void *hook_params) { +int moldyn_set_schedule_hook(t_moldyn *moldyn,set_hook hook,void *hook_params) { moldyn->schedule.hook=hook; moldyn->schedule.hook_params=hook_params; @@ -826,6 +1131,7 @@ int moldyn_integrate(t_moldyn *moldyn) { int fd; char dir[128]; double ds; + double energy_scale; sched=&(moldyn->schedule); atom=moldyn->atom; @@ -843,6 +1149,9 @@ int moldyn_integrate(t_moldyn *moldyn) { moldyn->tau_square=moldyn->tau*moldyn->tau; moldyn->cutoff_square=moldyn->cutoff*moldyn->cutoff; + /* energy scaling factor */ + energy_scale=moldyn->count*EV; + /* calculate initial forces */ potential_force_calc(moldyn); @@ -863,6 +1172,9 @@ int moldyn_integrate(t_moldyn *moldyn) { /* debugging, ignore */ moldyn->debug=0; + /* tell the world */ + printf("[moldyn] integration start, go get a coffee ...\n"); + /* executing the schedule */ for(sched->count=0;sched->counttotal_sched;sched->count++) { @@ -884,14 +1196,19 @@ int moldyn_integrate(t_moldyn *moldyn) { if(moldyn->pt_scale&(P_SCALE_BERENDSEN|P_SCALE_DIRECT)) scale_volume(moldyn); + temperature_calc(moldyn); + pressure_calc(moldyn); + //thermodynamic_pressure_calc(moldyn); + /* check for log & visualization */ if(e) { if(!(i%e)) + update_e_kin(moldyn); dprintf(moldyn->efd, "%f %f %f %f\n", - moldyn->time,update_e_kin(moldyn), - moldyn->energy, - get_total_energy(moldyn)); + moldyn->time,moldyn->ekin/energy_scale, + moldyn->energy/energy_scale, + get_total_energy(moldyn)/energy_scale); } if(m) { if(!(i%m)) { @@ -918,8 +1235,8 @@ int moldyn_integrate(t_moldyn *moldyn) { if(!(i%v)) { visual_atoms(&(moldyn->vis),moldyn->time, moldyn->atom,moldyn->count); - printf("\rsched: %d, steps: %d, debug: %d", - sched->count,i,moldyn->debug); + printf("\rsched: %d, steps: %d, debug: %f | %f", + sched->count,i,moldyn->p/ATM,moldyn->debug/ATM); fflush(stdout); } } @@ -946,7 +1263,7 @@ int moldyn_integrate(t_moldyn *moldyn) { int velocity_verlet(t_moldyn *moldyn) { int i,count; - double tau,tau_square; + double tau,tau_square,h; t_3dvec delta; t_atom *atom; @@ -957,14 +1274,15 @@ int velocity_verlet(t_moldyn *moldyn) { for(i=0;ienergy=0.0; - - /* get energy and force of every atom */ + + /* reset force, site energy and virial of every atom */ for(i=0;ixx=0.0; virial->yy=0.0; virial->zz=0.0; virial->xy=0.0; virial->xz=0.0; virial->yz=0.0; - + /* reset site energy */ itom[i].e=0.0; + } + + /* get energy,force and virial of every atom */ + for(i=0;ifunc1b(moldyn,&(itom[i])); @@ -1127,6 +1450,7 @@ int potential_force_calc(t_moldyn *moldyn) { } } + #ifdef DEBUG printf("\n\n"); #endif @@ -1137,6 +1461,22 @@ printf("\n\n"); return 0; } +/* + * virial calculation + */ + +inline int virial_calc(t_atom *a,t_3dvec *f,t_3dvec *d) { + + a->virial.xx+=f->x*d->x; + a->virial.yy+=f->y*d->y; + a->virial.zz+=f->z*d->z; + a->virial.xy+=f->x*d->y; + a->virial.xz+=f->x*d->z; + a->virial.yz+=f->y*d->z; + + return 0; +} + /* * periodic boundayr checking */ @@ -1179,23 +1519,29 @@ int harmonic_oscillator(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) { t_ho_params *params; t_3dvec force,distance; - double d; + double d,f; double sc,equi_dist; params=moldyn->pot2b_params; sc=params->spring_constant; equi_dist=params->equilibrium_distance; + if(air),&(ai->r)); if(bc) check_per_bound(moldyn,&distance); d=v3_norm(&distance); if(d<=moldyn->cutoff) { - /* energy is 1/2 (d-d0)^2, but we will add this twice ... */ - moldyn->energy+=(0.25*sc*(d-equi_dist)*(d-equi_dist)); + moldyn->energy+=(0.5*sc*(d-equi_dist)*(d-equi_dist)); /* f = -grad E; grad r_ij = -1 1/r_ij distance */ - v3_scale(&force,&distance,sc*(1.0-(equi_dist/d))); + f=sc*(1.0-equi_dist/d); + v3_scale(&force,&distance,f); v3_add(&(ai->f),&(ai->f),&force); + virial_calc(ai,&force,&distance); + virial_calc(aj,&force,&distance); /* f and d signe switched */ + v3_scale(&force,&distance,-f); + v3_add(&(aj->f),&(aj->f),&force); } return 0; @@ -1215,6 +1561,8 @@ int lennard_jones(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) { sig6=params->sigma6; sig12=params->sigma12; + if(air),&(ai->r)); if(bc) check_per_bound(moldyn,&distance); d=v3_absolute_square(&distance); /* 1/r^2 */ @@ -1223,16 +1571,19 @@ int lennard_jones(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) { h2=d*d; /* 1/r^4 */ h2*=d; /* 1/r^6 */ h1=h2*h2; /* 1/r^12 */ - /* energy is eps*..., but we will add this twice ... */ - moldyn->energy+=0.5*eps*(sig12*h1-sig6*h2); + moldyn->energy+=(eps*(sig12*h1-sig6*h2)-params->uc); h2*=d; /* 1/r^8 */ h1*=d; /* 1/r^14 */ h2*=6*sig6; h1*=12*sig12; d=+h1-h2; d*=eps; + v3_scale(&force,&distance,d); + v3_add(&(aj->f),&(aj->f),&force); v3_scale(&force,&distance,-1.0*d); /* f = - grad E */ v3_add(&(ai->f),&(ai->f),&force); + virial_calc(ai,&force,&distance); + virial_calc(aj,&force,&distance); /* f and d signe switched */ } return 0; @@ -1526,7 +1877,6 @@ int tersoff_mult_post_2bp(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) { zeta=exchange->zeta_ij; if(zeta==0.0) { moldyn->debug++; /* just for debugging ... */ - db=0.0; b=chi; v3_scale(&force,dist_ij,df_a*b*f_c); } @@ -1602,12 +1952,13 @@ if(ai==&(moldyn->atom[0])) { v3_add(&(ai->f),&(ai->f),&force); /* virial - plus sign, as dist_ij = - dist_ji - (really??) */ - 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; +// TEST ... with a minus instead + 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])) {