X-Git-Url: https://www.hackdaworld.org/gitweb/?a=blobdiff_plain;f=moldyn.c;h=0d5027c57df699447bcdf61a2c2b516235c2fa0d;hb=91e4a00285261865ffce4b9553d153b562c80ee6;hp=9db5cd9053fea64ce0cc5bd09cc667caa360bd4a;hpb=9f6af2cd82a72451741b68ca333f94c6c1d2eec5;p=physik%2Fposic.git diff --git a/moldyn.c b/moldyn.c index 9db5cd9..0d5027c 100644 --- a/moldyn.c +++ b/moldyn.c @@ -16,6 +16,7 @@ #include #include "moldyn.h" +#include "report/report.h" int moldyn_init(t_moldyn *moldyn,int argc,char **argv) { @@ -72,7 +73,7 @@ int set_temperature(t_moldyn *moldyn,double t_ref) { moldyn->t_ref=t_ref; - printf("[moldyn] temperature: %f\n",moldyn->t_ref); + printf("[moldyn] temperature [K]: %f\n",moldyn->t_ref); return 0; } @@ -81,7 +82,7 @@ int set_pressure(t_moldyn *moldyn,double p_ref) { moldyn->p_ref=p_ref; - printf("[moldyn] pressure: %f\n",moldyn->p_ref); + printf("[moldyn] pressure [atm]: %f\n",moldyn->p_ref/ATM); return 0; } @@ -121,12 +122,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?"yes":"no"); + printf(" delta volume (pressure calc): %f\n",moldyn->dv); return 0; } @@ -196,6 +200,14 @@ 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) { @@ -244,6 +256,28 @@ int moldyn_set_log(t_moldyn *moldyn,u8 type,int timer) { } 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("unknown log type: %02x\n",type); return -1; @@ -254,9 +288,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; @@ -279,6 +327,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; @@ -294,10 +343,19 @@ int create_lattice(t_moldyn *moldyn,u8 type,double lc,int element,double mass, v3_zero(&origin); switch(type) { + case CUBIC: + set_nn_dist(moldyn,lc); + origin.x=0.5*lc; + origin.y=0.5*lc; + origin.z=0.5*lc; + ret=cubic_init(a,b,c,lc,atom,&origin); + break; case FCC: - ret=fcc_init(a,b,c,lc,atom,&origin); + set_nn_dist(moldyn,0.5*sqrt(2.0)*lc); + ret=fcc_init(a,b,c,lc,atom,NULL); break; case DIAMOND: + set_nn_dist(moldyn,0.25*sqrt(3.0)*lc); ret=diamond_init(a,b,c,lc,atom,&origin); break; default: @@ -329,6 +387,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; - - 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); + moldyn->t=(2.0*moldyn->ekin)/(3.0*K_BOLTZMANN*moldyn->count); return moldyn->t; } @@ -577,27 +665,127 @@ 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; - t_atom *atom; - double p1,p2,p=0; - + double v; + t_virial *virial; + + /* + * P = 1/(3V) sum_i ( p_i^2 / 2m + f_i r_i ) + * + * virial = f_i r_i + */ + + v=0.0; for(i=0;icount;i++) { - + virial=&(moldyn->atom[i].virial); + v+=(virial->xx+virial->yy+virial->zz); + } + + /* assume up to date kinetic energy */ + moldyn->p=2.0*moldyn->ekin+v; + moldyn->p/=(3.0*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; } - p1=(moldyn->count*K_BOLTZMANN*moldyn->t-ONE_THIRD*moldyn->vt1); - p1/=moldyn->volume; + /* save unscaled potential energy + atom/dim configuration */ + u=moldyn->energy; + memcpy(store,moldyn->atom,moldyn->count*sizeof(t_atom)); + dim=moldyn->dim; - p2=(moldyn->count*K_BOLTZMANN*moldyn->t-ONE_THIRD*moldyn->vt2); - p2/=moldyn->volume; + /* 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,QUIET); + potential_force_calc(moldyn); + tp->x=(moldyn->energy-u)/moldyn->dv; + p=tp->x*tp->x; - printf("compare pressures: %f %f\n",p1/ATM,p2/ATM); + /* restore atomic configuration + dim */ + memcpy(moldyn->atom,store,moldyn->count*sizeof(t_atom)); + moldyn->dim=dim; - return moldyn->p; -} + /* 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,QUIET); + 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,QUIET); + 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,QUIET); + 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,QUIET); + + return sqrt(p); +} double get_pressure(t_moldyn *moldyn) { @@ -605,63 +793,78 @@ double get_pressure(t_moldyn *moldyn) { } +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; t_3dvec *dim,*vdim; - double scale,v; - t_virial virial; + double scale; t_linkcell *lc; - int i; - atom=moldyn->atom; - dim=&(moldyn->dim); vdim=&(moldyn->vis.dim); + dim=&(moldyn->dim); lc=&(moldyn->lc); - memset(&virial,0,sizeof(t_virial)); + /* scaling factor */ + if(moldyn->pt_scale&P_SCALE_BERENDSEN) { + scale=1.0-(moldyn->p_ref-moldyn->p)/moldyn->p_tc; + scale=pow(scale,ONE_THIRD); + } + else { + scale=pow(moldyn->p/moldyn->p_ref,ONE_THIRD); + } +moldyn->debug=scale; - for(i=0;icount;i++) { - virial.xx+=atom[i].virial.xx; - virial.yy+=atom[i].virial.yy; - virial.zz+=atom[i].virial.zz; - virial.xy+=atom[i].virial.xy; - virial.xz+=atom[i].virial.xz; - virial.yz+=atom[i].virial.yz; + /* scale the atoms and dimensions */ + scale_atoms(moldyn,scale,TRUE,TRUE,TRUE); + scale_dim(moldyn,scale,TRUE,TRUE,TRUE); + + /* visualize dimensions */ + if(vdim->x!=0) { + vdim->x=dim->x; + vdim->y=dim->y; + vdim->z=dim->z; } - /* just a guess so far ... */ - v=virial.xx+virial.yy+virial.zz; - -printf("%f\n",v); - /* get pressure from virial */ - moldyn->p=moldyn->count*K_BOLTZMANN*moldyn->t+ONE_THIRD*v; - moldyn->p/=moldyn->volume; -printf("%f | %f\n",moldyn->p/(ATM),moldyn->p_ref/ATM); - - /* scale factor */ - if(moldyn->pt_scale&P_SCALE_BERENDSEN) - scale=3*sqrt(1-(moldyn->p_ref-moldyn->p)/moldyn->p_tc); - else - /* should actually never be used */ - scale=pow(moldyn->p/moldyn->p_ref,1.0/3.0); - -printf("scale = %f\n",scale); - /* actual scaling */ - dim->x*=scale; - dim->y*=scale; - dim->z*=scale; - if(vdim->x) vdim->x=dim->x; - if(vdim->y) vdim->y=dim->y; - if(vdim->z) vdim->z=dim->z; - moldyn->volume*=(scale*scale*scale); - - /* check whether we need a new linkcell init */ - if((dim->x/moldyn->cutoff!=lc->nx)|| - (dim->y/moldyn->cutoff!=lc->ny)|| - (dim->z/moldyn->cutoff!=lc->nx)) { + /* recalculate scaled volume */ + moldyn->volume=dim->x*dim->y*dim->z; + + /* adjust/reinit linkcell */ + if(((int)(dim->x/moldyn->cutoff)!=lc->nx)|| + ((int)(dim->y/moldyn->cutoff)!=lc->ny)|| + ((int)(dim->z/moldyn->cutoff)!=lc->nx)) { link_cell_shutdown(moldyn); - link_cell_init(moldyn); + link_cell_init(moldyn,QUIET); + } else { + lc->x*=scale; + lc->y*=scale; + lc->z*=scale; } return 0; @@ -726,7 +929,7 @@ double estimate_time_step(t_moldyn *moldyn,double nn_dist) { /* linked list / cell method */ -int link_cell_init(t_moldyn *moldyn) { +int link_cell_init(t_moldyn *moldyn,u8 vol) { t_linkcell *lc; int i; @@ -747,7 +950,7 @@ int link_cell_init(t_moldyn *moldyn) { if(lc->cells<27) printf("[moldyn] FATAL: less then 27 subcells!\n"); - printf("[moldyn] initializing linked cells (%d)\n",lc->cells); + if(vol) printf("[moldyn] initializing linked cells (%d)\n",lc->cells); for(i=0;icells;i++) list_init_f(&(lc->subcell[i])); @@ -918,12 +1121,13 @@ int moldyn_integrate(t_moldyn *moldyn) { int fd; char dir[128]; double ds; + double energy_scale; sched=&(moldyn->schedule); atom=moldyn->atom; /* initialize linked cell method */ - link_cell_init(moldyn); + link_cell_init(moldyn,VERBOSE); /* logging & visualization */ e=moldyn->ewrite; @@ -935,6 +1139,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); @@ -973,6 +1180,12 @@ int moldyn_integrate(t_moldyn *moldyn) { /* integration step */ moldyn->integrate(moldyn); + /* calculate kinetic energy, temperature and pressure */ + update_e_kin(moldyn); + temperature_calc(moldyn); + pressure_calc(moldyn); + //thermodynamic_pressure_calc(moldyn); + /* p/t scaling */ if(moldyn->pt_scale&(T_SCALE_BERENDSEN|T_SCALE_DIRECT)) scale_velocity(moldyn,FALSE); @@ -980,21 +1193,13 @@ int moldyn_integrate(t_moldyn *moldyn) { scale_volume(moldyn); /* check for log & visualization */ -//double ax; -//double ao; -//double av; if(e) { if(!(i%e)) -//ao=sqrt(0.1/M_SI); -//ax=((0.28-0.25)*sqrt(3)*LC_SI/2)*cos(ao*i); -//av=ao*(0.28-0.25)*sqrt(3)*LC_SI/2*sin(ao*i); - update_e_kin(moldyn); dprintf(moldyn->efd, "%f %f %f %f\n", - moldyn->time,moldyn->ekin, - moldyn->energy, - get_total_energy(moldyn)); -//moldyn->atom[0].r.x,ax,av*av*M_SI,0.1*ax*ax,av*av*M_SI+0.1*ax*ax); + moldyn->time,moldyn->ekin/energy_scale, + moldyn->energy/energy_scale, + get_total_energy(moldyn)/energy_scale); } if(m) { if(!(i%m)) { @@ -1021,8 +1226,9 @@ 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, T: %f, P: %f V: %f", + sched->count,i, + moldyn->t,moldyn->p/ATM,moldyn->volume); fflush(stdout); } } @@ -1115,27 +1321,29 @@ int potential_force_calc(t_moldyn *moldyn) { /* reset energy */ moldyn->energy=0.0; - moldyn->vt2=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; - moldyn->vt1=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])); @@ -1234,6 +1442,7 @@ int potential_force_calc(t_moldyn *moldyn) { } } + #ifdef DEBUG printf("\n\n"); #endif @@ -1241,14 +1450,6 @@ printf("\n\n"); printf("\n\n"); #endif - moldyn->vt2=0.0; - for(i=0;ivt2-=v3_scalar_product(&(itom[i].r),&(itom[i].f)); - -//printf("compare: vt1: %f vt2: %f\n",moldyn->vt1,moldyn->vt2); - -//pressure_calc(moldyn); - return 0; } @@ -1258,12 +1459,12 @@ printf("\n\n"); 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; + 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; } @@ -1371,11 +1572,10 @@ int lennard_jones(t_moldyn *moldyn,t_atom *ai,t_atom *aj,u8 bc) { 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_scale(&force,&force,-1.0); /* 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 */ - moldyn->vt1-=v3_scalar_product(&force,&distance); } return 0;