void sum_lrforces(rvec f[],t_forcerec *fr,int start,int homenr) { /* Now add the forces from the PME calculation. Since this only produces * forces on the local atoms, this can be safely done after the * communication step. */ if (EEL_LR(fr->eeltype)) sum_forces(start,start+homenr,f,fr->f_pme); }
void do_force(FILE *fplog,t_commrec *cr, t_inputrec *inputrec, int step,t_nrnb *nrnb,gmx_wallcycle_t wcycle, gmx_localtop_t *top, gmx_groups_t *groups, matrix box,rvec x[],history_t *hist, rvec f[],rvec buf[], tensor vir_force, t_mdatoms *mdatoms, gmx_enerdata_t *enerd,t_fcdata *fcd, real lambda,t_graph *graph, t_forcerec *fr,gmx_vsite_t *vsite,rvec mu_tot, real t,FILE *field,gmx_edsam_t ed, int flags) { static rvec box_size; int cg0,cg1,i,j; int start,homenr; static double mu[2*DIM]; rvec mu_tot_AB[2]; bool bSepDVDL,bStateChanged,bNS,bFillGrid,bCalcCGCM,bBS,bDoForces; matrix boxs; real e,v,dvdl; t_pbc pbc; float cycles_ppdpme,cycles_pme,cycles_force; start = mdatoms->start; homenr = mdatoms->homenr; bSepDVDL = (fr->bSepDVDL && do_per_step(step,inputrec->nstlog)); clear_mat(vir_force); if (PARTDECOMP(cr)) { pd_cg_range(cr,&cg0,&cg1); } else { cg0 = 0; if (DOMAINDECOMP(cr)) cg1 = cr->dd->ncg_tot; else cg1 = top->cgs.nr; if (fr->n_tpi > 0) cg1--; } bStateChanged = (flags & GMX_FORCE_STATECHANGED); bNS = (flags & GMX_FORCE_NS); bFillGrid = (bNS && bStateChanged); bCalcCGCM = (bFillGrid && !DOMAINDECOMP(cr)); bDoForces = (flags & GMX_FORCE_FORCES); if (bStateChanged) { update_forcerec(fplog,fr,box); /* Calculate total (local) dipole moment in a temporary common array. * This makes it possible to sum them over nodes faster. */ calc_mu(start,homenr, x,mdatoms->chargeA,mdatoms->chargeB,mdatoms->nChargePerturbed, mu,mu+DIM); } if (fr->ePBC != epbcNONE) { /* Compute shift vectors every step, * because of pressure coupling or box deformation! */ if (DYNAMIC_BOX(*inputrec) && bStateChanged) calc_shifts(box,fr->shift_vec); if (bCalcCGCM) { put_charge_groups_in_box(fplog,cg0,cg1,fr->ePBC,box, &(top->cgs),x,fr->cg_cm); inc_nrnb(nrnb,eNR_CGCM,homenr); inc_nrnb(nrnb,eNR_RESETX,cg1-cg0); } else if (EI_ENERGY_MINIMIZATION(inputrec->eI) && graph) { unshift_self(graph,box,x); } } else if (bCalcCGCM) { calc_cgcm(fplog,cg0,cg1,&(top->cgs),x,fr->cg_cm); inc_nrnb(nrnb,eNR_CGCM,homenr); } if (bCalcCGCM) { if (PAR(cr)) { move_cgcm(fplog,cr,fr->cg_cm); } if (gmx_debug_at) pr_rvecs(debug,0,"cgcm",fr->cg_cm,top->cgs.nr); } #ifdef GMX_MPI if (!(cr->duty & DUTY_PME)) { /* Send particle coordinates to the pme nodes. * Since this is only implemented for domain decomposition * and domain decomposition does not use the graph, * we do not need to worry about shifting. */ wallcycle_start(wcycle,ewcPP_PMESENDX); GMX_MPE_LOG(ev_send_coordinates_start); bBS = (inputrec->nwall == 2); if (bBS) { copy_mat(box,boxs); svmul(inputrec->wall_ewald_zfac,boxs[ZZ],boxs[ZZ]); } gmx_pme_send_x(cr,bBS ? boxs : box,x,mdatoms->nChargePerturbed,lambda); GMX_MPE_LOG(ev_send_coordinates_finish); wallcycle_stop(wcycle,ewcPP_PMESENDX); } #endif /* GMX_MPI */ /* Communicate coordinates and sum dipole if necessary */ if (PAR(cr)) { wallcycle_start(wcycle,ewcMOVEX); if (DOMAINDECOMP(cr)) { dd_move_x(cr->dd,box,x,buf); } else { move_x(fplog,cr,GMX_LEFT,GMX_RIGHT,x,nrnb); } /* When we don't need the total dipole we sum it in global_stat */ if (NEED_MUTOT(*inputrec)) gmx_sumd(2*DIM,mu,cr); wallcycle_stop(wcycle,ewcMOVEX); } for(i=0; i<2; i++) for(j=0;j<DIM;j++) mu_tot_AB[i][j] = mu[i*DIM + j]; if (fr->efep == efepNO) copy_rvec(mu_tot_AB[0],mu_tot); else for(j=0; j<DIM; j++) mu_tot[j] = (1.0 - lambda)*mu_tot_AB[0][j] + lambda*mu_tot_AB[1][j]; /* Reset energies */ reset_energies(&(inputrec->opts),fr,bNS,enerd,MASTER(cr)); if (bNS) { wallcycle_start(wcycle,ewcNS); if (graph && bStateChanged) /* Calculate intramolecular shift vectors to make molecules whole */ mk_mshift(fplog,graph,fr->ePBC,box,x); /* Reset long range forces if necessary */ if (fr->bTwinRange) { clear_rvecs(fr->f_twin_n,fr->f_twin); clear_rvecs(SHIFTS,fr->fshift_twin); } /* Do the actual neighbour searching and if twin range electrostatics * also do the calculation of long range forces and energies. */ dvdl = 0; ns(fplog,fr,x,f,box,groups,&(inputrec->opts),top,mdatoms, cr,nrnb,step,lambda,&dvdl,&enerd->grpp,bFillGrid,bDoForces); if (bSepDVDL) fprintf(fplog,sepdvdlformat,"LR non-bonded",0,dvdl); enerd->dvdl_lr = dvdl; enerd->term[F_DVDL] += dvdl; wallcycle_stop(wcycle,ewcNS); } if (DOMAINDECOMP(cr)) { if (!(cr->duty & DUTY_PME)) { wallcycle_start(wcycle,ewcPPDURINGPME); dd_force_flop_start(cr->dd,nrnb); } } /* Start the force cycle counter. * This counter is stopped in do_forcelow_level. * No parallel communication should occur while this counter is running, * since that will interfere with the dynamic load balancing. */ wallcycle_start(wcycle,ewcFORCE); if (bDoForces) { /* Reset PME/Ewald forces if necessary */ if (fr->bF_NoVirSum) { GMX_BARRIER(cr->mpi_comm_mygroup); if (fr->bDomDec) clear_rvecs(fr->f_novirsum_n,fr->f_novirsum); else clear_rvecs(homenr,fr->f_novirsum+start); GMX_BARRIER(cr->mpi_comm_mygroup); } /* Copy long range forces into normal buffers */ if (fr->bTwinRange) { for(i=0; i<fr->f_twin_n; i++) copy_rvec(fr->f_twin[i],f[i]); for(i=0; i<SHIFTS; i++) copy_rvec(fr->fshift_twin[i],fr->fshift[i]); } else { if (DOMAINDECOMP(cr)) clear_rvecs(cr->dd->nat_tot,f); else clear_rvecs(mdatoms->nr,f); clear_rvecs(SHIFTS,fr->fshift); } clear_rvec(fr->vir_diag_posres); GMX_BARRIER(cr->mpi_comm_mygroup); } if (inputrec->ePull == epullCONSTRAINT) clear_pull_forces(inputrec->pull); /* update QMMMrec, if necessary */ if(fr->bQMMM) update_QMMMrec(cr,fr,x,mdatoms,box,top); if ((flags & GMX_FORCE_BONDED) && top->idef.il[F_POSRES].nr > 0) { /* Position restraints always require full pbc */ set_pbc(&pbc,inputrec->ePBC,box); v = posres(top->idef.il[F_POSRES].nr,top->idef.il[F_POSRES].iatoms, top->idef.iparams_posres, (const rvec*)x,fr->f_novirsum,fr->vir_diag_posres, inputrec->ePBC==epbcNONE ? NULL : &pbc,lambda,&dvdl, fr->rc_scaling,fr->ePBC,fr->posres_com,fr->posres_comB); if (bSepDVDL) { fprintf(fplog,sepdvdlformat, interaction_function[F_POSRES].longname,v,dvdl); } enerd->term[F_POSRES] += v; enerd->term[F_DVDL] += dvdl; inc_nrnb(nrnb,eNR_POSRES,top->idef.il[F_POSRES].nr/2); } /* Compute the bonded and non-bonded forces */ do_force_lowlevel(fplog,step,fr,inputrec,&(top->idef), cr,nrnb,wcycle,mdatoms,&(inputrec->opts), x,hist,f,enerd,fcd,box,lambda,graph,&(top->excls),mu_tot_AB, flags,&cycles_force); GMX_BARRIER(cr->mpi_comm_mygroup); if (ed) { do_flood(fplog,cr,x,f,ed,box,step); } if (DOMAINDECOMP(cr)) { dd_force_flop_stop(cr->dd,nrnb); if (wcycle) dd_cycles_add(cr->dd,cycles_force,ddCyclF); } if (bDoForces) { /* Compute forces due to electric field */ calc_f_el(MASTER(cr) ? field : NULL, start,homenr,mdatoms->chargeA,x,f,inputrec->ex,inputrec->et,t); /* When using PME/Ewald we compute the long range virial there. * otherwise we do it based on long range forces from twin range * cut-off based calculation (or not at all). */ /* Communicate the forces */ if (PAR(cr)) { wallcycle_start(wcycle,ewcMOVEF); if (DOMAINDECOMP(cr)) { dd_move_f(cr->dd,f,buf,fr->fshift); /* Position restraint do not introduce inter-cg forces */ if (EEL_FULL(fr->eeltype) && cr->dd->n_intercg_excl) dd_move_f(cr->dd,fr->f_novirsum,buf,NULL); } else { move_f(fplog,cr,GMX_LEFT,GMX_RIGHT,f,buf,nrnb); } wallcycle_stop(wcycle,ewcMOVEF); } } if (bDoForces) { if (vsite) { wallcycle_start(wcycle,ewcVSITESPREAD); spread_vsite_f(fplog,vsite,x,f,fr->fshift,nrnb, &top->idef,fr->ePBC,fr->bMolPBC,graph,box,cr); wallcycle_stop(wcycle,ewcVSITESPREAD); } /* Calculation of the virial must be done after vsites! */ calc_virial(fplog,mdatoms->start,mdatoms->homenr,x,f, vir_force,graph,box,nrnb,fr,inputrec->ePBC); } if (inputrec->ePull == epullUMBRELLA || inputrec->ePull == epullCONST_F) { /* Calculate the center of mass forces, this requires communication, * which is why pull_potential is called close to other communication. * The virial contribution is calculated directly, * which is why we call pull_potential after calc_virial. */ set_pbc(&pbc,inputrec->ePBC,box); dvdl = 0; enerd->term[F_COM_PULL] = pull_potential(inputrec->ePull,inputrec->pull,mdatoms,&pbc, cr,t,lambda,x,f,vir_force,&dvdl); if (bSepDVDL) fprintf(fplog,sepdvdlformat,"Com pull",enerd->term[F_COM_PULL],dvdl); enerd->term[F_DVDL] += dvdl; } if (!(cr->duty & DUTY_PME)) { cycles_ppdpme = wallcycle_stop(wcycle,ewcPPDURINGPME); dd_cycles_add(cr->dd,cycles_ppdpme,ddCyclPPduringPME); } #ifdef GMX_MPI if (PAR(cr) && !(cr->duty & DUTY_PME)) { /* In case of node-splitting, the PP nodes receive the long-range * forces, virial and energy from the PME nodes here. */ wallcycle_start(wcycle,ewcPP_PMEWAITRECVF); dvdl = 0; gmx_pme_receive_f(cr,fr->f_novirsum,fr->vir_el_recip,&e,&dvdl, &cycles_pme); if (bSepDVDL) fprintf(fplog,sepdvdlformat,"PME mesh",e,dvdl); enerd->term[F_COUL_RECIP] += e; enerd->term[F_DVDL] += dvdl; if (wcycle) dd_cycles_add(cr->dd,cycles_pme,ddCyclPME); wallcycle_stop(wcycle,ewcPP_PMEWAITRECVF); } #endif if (bDoForces && fr->bF_NoVirSum) { if (vsite) { /* Spread the mesh force on virtual sites to the other particles... * This is parallellized. MPI communication is performed * if the constructing atoms aren't local. */ wallcycle_start(wcycle,ewcVSITESPREAD); spread_vsite_f(fplog,vsite,x,fr->f_novirsum,NULL,nrnb, &top->idef,fr->ePBC,fr->bMolPBC,graph,box,cr); wallcycle_stop(wcycle,ewcVSITESPREAD); } /* Now add the forces, this is local */ if (fr->bDomDec) { sum_forces(0,fr->f_novirsum_n,f,fr->f_novirsum); } else { sum_forces(start,start+homenr,f,fr->f_novirsum); } if (EEL_FULL(fr->eeltype)) { /* Add the mesh contribution to the virial */ m_add(vir_force,fr->vir_el_recip,vir_force); } if (debug) pr_rvecs(debug,0,"vir_force",vir_force,DIM); } /* Sum the potential energy terms from group contributions */ sum_epot(&(inputrec->opts),enerd); if (fr->print_force >= 0 && bDoForces) print_large_forces(stderr,mdatoms,cr,step,fr->print_force,x,f); }
/*_________________________________Main body__________________________________*/ void main(void) { double free_particle[n_max][m_max][z_max]; /*This is the array which holds*/ /*the properties of all of the */ /*free_particles in the system */ double image_free_particle[n_max][m_max][z_max]; /*This is the array which holds*/ /*the properties of all of the */ /*images of the free_particles */ /*in the system */ double wall_particle[44][m_max][z_max]; /*This is the array which holds */ /*the properties of all of the */ /*wall_particles in the system */ double free_forces[n_max][n_max][z_max]; /*Contains values of forces */ /*between free_particle pairs*/ double image_free_forces[n_max][n_max][z_max]; /*Contains values of forces*/ /*between free and image */ /*particle pairs */ double image_image_forces[n_max][n_max][z_max]; /*Contains values of forces*/ /*between image particle */ /*pairs */ double wall_free_forces[n_max][44][z_max]; /*Contains values of forces between*/ /*wall and free particle pairs */ double wall_image_forces[n_max][44][z_max]; /*Contains values of forces between*/ /*wall and image particle pairs */ double x[n_max][n_max]; /*Contains the overlap dist*/ /*between free_particle pairs*/ double image_x[n_max][n_max]; /*Contains the overlap dist*/ /*between free and image */ /*particle pairs */ double wall_x[n_max][44]; /*Contains the overlap dist*/ /*between wall and free */ /*particle pairs */ double image_image_x[n_max][n_max]; /*Contains the overlap dist*/ /*between two image */ /*particle pairs */ double wall_image_x[n_max][44]; /*Contains the overlap dist*/ /*between wall and image */ /*particle pairs */ double t = t_min; /*Timer for simulation*/ /*Energy Variables*/ double kinetic_energy,potential_energy,total_energy; /*Counters*/ int i,k; int j = 0; int l = 0; /*Average Radius*/ double rad; /*Packing density*/ double packing; /*Average Coordiantion Number*/ double coord_number; /*Average Velocity*/ double average_vel_x; double average_vel_y; #include"incl/files.h" #include"incl/includes.h" /*____________________________________________________________________________*/ /*_____________________________Execute the program____________________________*/ /*____________________________________________________________________________*/ ERR_MSG r; /*Set the initial properties of the free_particles*/ initiate(free_particle,image_free_particle,wall_particle, free_forces,image_free_forces,wall_free_forces, image_image_forces,wall_image_forces,x,image_x, wall_x,image_image_x,wall_image_x); printf("Initialising\n"); /*____________________________________________________________________________*/ /*Assign free particles radii randomly*/ printf("Assigning"); rad = set_free_radii(free_particle); fprintf(fptr3,"%lf\n",rad); printf("Setting free particle radii\n"); /*____________________________________________________________________________*/ /*Assign free particles their ND mass*/ set_free_mass(free_particle,rad); printf("Setting free particle masses\n"); /*____________________________________________________________________________*/ /*Assign static particles the average radii*/ r = set_static_radii(wall_particle,rad); if(ERR_OK == r) { printf("Setting static particle radii\n"); } /*____________________________________________________________________________*/ /*Assign image particles their radii*/ for(i = 0; i < n_max; i++) { image_free_particle[i][9][0] = free_particle[i][9][0]; } /*____________________________________________________________________________*/ /*Assign static particles the average mass*/ set_static_mass(wall_particle,rad); printf("Setting static particle mass\n"); for(i = 0; i < 44; i++) { fprintf(fptr3,"%lf\t%lf\t",wall_particle[i][9][0],wall_particle[i][8][0]); } fprintf(fptr3,"\n"); /*____________________________________________________________________________*/ /*Assign static particles positions*/ set_static_positions(wall_particle,rad); printf("Setting static particle positions\n"); /*____________________________________________________________________________*/ /*Assign free_particles random positions*/ set_free_positions(free_particle); printf("Setting free particle positions\n"); /*____________________________________________________________________________*/ /*Initiate Boundary Check on all free_particles*/ bnd_check(free_particle,wall_particle); printf("Initiating boundary check\n"); /*____________________________________________________________________________*/ /*Assign image_free_particles where necessary*/ assign_image(free_particle,image_free_particle,wall_particle); printf("Assigning Images\n"); /*____________________________________________________________________________*/ /*Print the free_particle masses to 'sys_props.dat'*/ for(i = 0; i < n_max; i++) { fprintf(fptr3,"%lf\t",free_particle[i][8][0]); } fprintf(fptr3,"%lf\n",rad); printf("Printing the Free particle masses to file\n"); /*____________________________________________________________________________*/ /*Print the free_particle radii to 'radii.dat'*/ for(i = 0; i < n_max; i++) { fprintf(fptr8,"%lf\n",free_particle[i][9][0]); } fprintf(fptr8,"\n"); printf("Printing the Free particle radii to file\n"); /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ calculate(free_particle,image_free_particle,wall_particle,free_forces, image_free_forces,wall_free_forces,image_image_forces, wall_image_forces,x,image_x,wall_x,image_image_x,wall_image_x); printf("Calculating\n"); coord_number = coordination_number(free_particle); printf("\t %lf\n", coord_number); sum_forces(free_particle,image_free_particle,free_forces,image_free_forces,wall_free_forces,image_image_forces,wall_image_forces); printf("Summing\n"); /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*___________________________________Main Loop________________________________*/ packing = packing_density(free_particle,wall_particle); printf("\t %lf\n", packing); #ifdef DEBUG_ON printf("\tLooping! It takes 3.5 minutes to boil a kettle and make some coffee.\n"); printf("\t\tAnd another 15 minutes maximum to drink that coffee.\n"); printf("\tYou should have made and drank approx 45.405 cups of coffee\n \t\t\tby the time this simulation finishes.\n"); printf("\n\n\n\t\t\t\t\tGet brewin'.\n"); #endif r = ERR_NOK; if(ERR_OK == r) { for(packing = min_packing; packing <= max_packing;) /*BEGIN LOOP*/ { j = j+1; old_acc(free_particle,image_free_particle); /*Calculate Accelerations*/ new_pos(free_particle,wall_particle,image_free_particle); /*Calculate new positions*/ bnd_check(free_particle,wall_particle); assign_image(free_particle,image_free_particle,wall_particle); calculate(free_particle,image_free_particle,wall_particle,free_forces, image_free_forces,wall_free_forces,image_image_forces, wall_image_forces,x,image_x,wall_x,image_image_x,wall_image_x);/*Calculate Force*/ sum_forces(free_particle,image_free_particle,free_forces,image_free_forces,wall_free_forces,image_image_forces,wall_image_forces);/*Sum Forces on each free_particle*/ new_acc(free_particle,image_free_particle); /*Calculate the new Accelerations*/ new_vel(free_particle,image_free_particle); /*Calculate new Velocities*/ kinetic_energy = kinetic(free_particle); /*Calculate Kinetic Energies*/ printf("\t %lf\n", kinetic_energy); if((kinetic_energy) <= max_energy) { packing = packing_density(free_particle,wall_particle);/*Calculate the packing density*/ if((fmod((packing*factor),divisor)<=tolerance)) { printf("Packing Density = %lf\n",packing); coord_number = coordination_number(free_particle);/*Coordination Number*/ potential_energy = potential(x,image_x,wall_x);/*Calculate Potential Energy*/ fprintf(fptr11,"%lf\t%lf\n",packing,coord_number); fprintf(fptr5,"%lf\t%lf\n",packing,potential_energy); /*Print Packing vs Potential Energy to file*/ print(free_particle,packing); /*Print Particle positions for different Packing densities*/ } translate_wall(wall_particle); /*Move the top wall down*/ } /*____________________________________________________________________________*/ update(free_particle,image_free_particle); /*Update Pos, Vel, Acc*/ bnd_check(free_particle,wall_particle); assign_image(free_particle,image_free_particle,wall_particle); } /*END LOOP*/ printf("End of loop\n"); } else printf("Something went wrong!\n"); /*____________________________________________________________________________*/ /*____________________________________________________________________________*/ /*Print free_particle masses to file 'sys_props.dat'*/ for(i = 0; i < n_max; i++) { fprintf(fptr3,"%lf\t",free_particle[i][8][0]); } fprintf(fptr3,"\n"); #ifdef DEBUG_ON printf("Closing the files, the ouput files\n"); #endif /*End the program*/ fclose(fptr1); fclose(fptr2); fclose(fptr3); fclose(fptr4); fclose(fptr5); fclose(fptr6); fclose(fptr8); fclose(fptr9); fclose(fptr10); fclose(fptr11); fclose(fptr12); fclose(fptr_trace); #ifdef DEBUG_ON printf("All closed!\n"); #endif #ifdef DEBUG_ON printf("Closing the last file, the input file!\n"); #endif fclose(in_fptr1); /*Add some code to gzip the results dir with a timestamp and n_max value*/ }