void gmx_log_open(const char *lognm, const t_commrec *cr, gmx_bool bAppendFiles, FILE** fplog) { int pid; char host[256]; char timebuf[STRLEN]; FILE *fp = *fplog; debug_gmx(); if (!bAppendFiles) { fp = gmx_fio_fopen(lognm, bAppendFiles ? "a+" : "w+" ); } gmx_fatal_set_log_file(fp); /* Get some machine parameters */ gmx_gethostname(host, 256); pid = gmx_getpid(); gmx_format_current_time(timebuf, STRLEN); if (bAppendFiles) { fprintf(fp, "\n" "\n" "-----------------------------------------------------------\n" "Restarting from checkpoint, appending to previous log file.\n" "\n" ); } fprintf(fp, "Log file opened on %s" "Host: %s pid: %d rank ID: %d number of ranks: %d\n", timebuf, host, pid, cr->nodeid, cr->nnodes); try { gmx::BinaryInformationSettings settings; settings.extendedInfo(true); settings.copyright(!bAppendFiles); gmx::printBinaryInformation(fp, gmx::getProgramContext(), settings); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; fprintf(fp, "\n"); fflush(fp); debug_gmx(); *fplog = fp; }
static void comm_args(const t_commrec *cr, int *argc, char ***argv) { int i, len; if (PAR(cr)) { gmx_bcast(sizeof(*argc), argc, cr); } if (!MASTER(cr)) { snew(*argv, *argc+1); } if (debug) { fprintf(debug, "NODEID=%d argc=%d\n", cr->nodeid, *argc); } for (i = 0; (i < *argc); i++) { if (MASTER(cr)) { len = strlen((*argv)[i])+1; } gmx_bcast(sizeof(len), &len, cr); if (!MASTER(cr)) { snew((*argv)[i], len); } /*gmx_bcast(len*sizeof((*argv)[i][0]),(*argv)[i],cr);*/ gmx_bcast(len*sizeof(char), (*argv)[i], cr); } debug_gmx(); }
static void comm_args(const t_commrec *cr,int *argc,char ***argv) { int i,len; if ((cr) && PAR(cr)) gmx_bcast(sizeof(*argc),argc,cr); if (!MASTER(cr)) snew(*argv,*argc+1); fprintf(stderr,"NODEID=%d argc=%d\n",cr->nodeid,*argc); for(i=0; (i<*argc); i++) { if (MASTER(cr)) len = strlen((*argv)[i])+1; gmx_bcast(sizeof(len),&len,cr); if (!MASTER(cr)) snew((*argv)[i],len); gmx_bcast(len*sizeof((*argv)[i][0]),(*argv)[i],cr); } debug_gmx(); }
void do_force_lowlevel(t_forcerec *fr, t_inputrec *ir, t_idef *idef, t_commrec *cr, t_nrnb *nrnb, gmx_wallcycle_t wcycle, t_mdatoms *md, rvec x[], history_t *hist, rvec f[], rvec f_longrange[], gmx_enerdata_t *enerd, t_fcdata *fcd, gmx_localtop_t *top, gmx_genborn_t *born, gmx_bool bBornRadii, matrix box, t_lambda *fepvals, real *lambda, t_graph *graph, t_blocka *excl, rvec mu_tot[], int flags, float *cycles_pme) { int i, j; int donb_flags; gmx_bool bSB; int pme_flags; matrix boxs; rvec box_size; t_pbc pbc; real dvdl_dum[efptNR], dvdl_nb[efptNR]; #ifdef GMX_MPI double t0 = 0.0, t1, t2, t3; /* time measurement for coarse load balancing */ #endif set_pbc(&pbc, fr->ePBC, box); /* reset free energy components */ for (i = 0; i < efptNR; i++) { dvdl_nb[i] = 0; dvdl_dum[i] = 0; } /* Reset box */ for (i = 0; (i < DIM); i++) { box_size[i] = box[i][i]; } debug_gmx(); /* do QMMM first if requested */ if (fr->bQMMM) { enerd->term[F_EQM] = calculate_QMMM(cr, x, f, fr); } /* Call the short range functions all in one go. */ #ifdef GMX_MPI /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/ #define TAKETIME FALSE if (TAKETIME) { MPI_Barrier(cr->mpi_comm_mygroup); t0 = MPI_Wtime(); } #endif if (ir->nwall) { /* foreign lambda component for walls */ real dvdl_walls = do_walls(ir, fr, box, md, x, f, lambda[efptVDW], enerd->grpp.ener[egLJSR], nrnb); enerd->dvdl_lin[efptVDW] += dvdl_walls; } /* If doing GB, reset dvda and calculate the Born radii */ if (ir->implicit_solvent) { wallcycle_sub_start(wcycle, ewcsNONBONDED); for (i = 0; i < born->nr; i++) { fr->dvda[i] = 0; } if (bBornRadii) { calc_gb_rad(cr, fr, ir, top, x, &(fr->gblist), born, md, nrnb); } wallcycle_sub_stop(wcycle, ewcsNONBONDED); } where(); /* We only do non-bonded calculation with group scheme here, the verlet * calls are done from do_force_cutsVERLET(). */ if (fr->cutoff_scheme == ecutsGROUP && (flags & GMX_FORCE_NONBONDED)) { donb_flags = 0; /* Add short-range interactions */ donb_flags |= GMX_NONBONDED_DO_SR; /* Currently all group scheme kernels always calculate (shift-)forces */ if (flags & GMX_FORCE_FORCES) { donb_flags |= GMX_NONBONDED_DO_FORCE; } if (flags & GMX_FORCE_VIRIAL) { donb_flags |= GMX_NONBONDED_DO_SHIFTFORCE; } if (flags & GMX_FORCE_ENERGY) { donb_flags |= GMX_NONBONDED_DO_POTENTIAL; } if (flags & GMX_FORCE_DO_LR) { donb_flags |= GMX_NONBONDED_DO_LR; } wallcycle_sub_start(wcycle, ewcsNONBONDED); do_nonbonded(fr, x, f, f_longrange, md, excl, &enerd->grpp, nrnb, lambda, dvdl_nb, -1, -1, donb_flags); /* If we do foreign lambda and we have soft-core interactions * we have to recalculate the (non-linear) energies contributions. */ if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) && fepvals->sc_alpha != 0) { for (i = 0; i < enerd->n_lambda; i++) { real lam_i[efptNR]; for (j = 0; j < efptNR; j++) { lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]); } reset_foreign_enerdata(enerd); do_nonbonded(fr, x, f, f_longrange, md, excl, &(enerd->foreign_grpp), nrnb, lam_i, dvdl_dum, -1, -1, (donb_flags & ~GMX_NONBONDED_DO_FORCE) | GMX_NONBONDED_DO_FOREIGNLAMBDA); sum_epot(&(enerd->foreign_grpp), enerd->foreign_term); enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT]; } } wallcycle_sub_stop(wcycle, ewcsNONBONDED); where(); } /* If we are doing GB, calculate bonded forces and apply corrections * to the solvation forces */ /* MRS: Eventually, many need to include free energy contribution here! */ if (ir->implicit_solvent) { wallcycle_sub_start(wcycle, ewcsLISTED); calc_gb_forces(cr, md, born, top, x, f, fr, idef, ir->gb_algorithm, ir->sa_algorithm, nrnb, &pbc, graph, enerd); wallcycle_sub_stop(wcycle, ewcsLISTED); } #ifdef GMX_MPI if (TAKETIME) { t1 = MPI_Wtime(); fr->t_fnbf += t1-t0; } #endif if (fepvals->sc_alpha != 0) { enerd->dvdl_nonlin[efptVDW] += dvdl_nb[efptVDW]; } else { enerd->dvdl_lin[efptVDW] += dvdl_nb[efptVDW]; } if (fepvals->sc_alpha != 0) /* even though coulomb part is linear, we already added it, beacuse we need to go through the vdw calculation anyway */ { enerd->dvdl_nonlin[efptCOUL] += dvdl_nb[efptCOUL]; } else { enerd->dvdl_lin[efptCOUL] += dvdl_nb[efptCOUL]; } debug_gmx(); if (debug) { pr_rvecs(debug, 0, "fshift after SR", fr->fshift, SHIFTS); } /* Shift the coordinates. Must be done before listed forces and PPPM, * but is also necessary for SHAKE and update, therefore it can NOT * go when no listed forces have to be evaluated. * * The shifting and PBC code is deliberately not timed, since with * the Verlet scheme it only takes non-zero time with triclinic * boxes, and even then the time is around a factor of 100 less * than the next smallest counter. */ /* Here sometimes we would not need to shift with NBFonly, * but we do so anyhow for consistency of the returned coordinates. */ if (graph) { shift_self(graph, box, x); if (TRICLINIC(box)) { inc_nrnb(nrnb, eNR_SHIFTX, 2*graph->nnodes); } else { inc_nrnb(nrnb, eNR_SHIFTX, graph->nnodes); } } /* Check whether we need to do listed interactions or correct for exclusions */ if (fr->bMolPBC && ((flags & GMX_FORCE_LISTED) || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype) || EVDW_PME(fr->vdwtype))) { /* TODO There are no electrostatics methods that require this transformation, when using the Verlet scheme, so update the above conditional. */ /* Since all atoms are in the rectangular or triclinic unit-cell, * only single box vector shifts (2 in x) are required. */ set_pbc_dd(&pbc, fr->ePBC, cr->dd, TRUE, box); } debug_gmx(); do_force_listed(wcycle, box, ir->fepvals, cr->ms, idef, (const rvec *) x, hist, f, fr, &pbc, graph, enerd, nrnb, lambda, md, fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, flags); where(); *cycles_pme = 0; clear_mat(fr->vir_el_recip); clear_mat(fr->vir_lj_recip); /* Do long-range electrostatics and/or LJ-PME, including related short-range * corrections. */ if (EEL_FULL(fr->eeltype) || EVDW_PME(fr->vdwtype)) { int status = 0; real Vlr_q = 0, Vlr_lj = 0, Vcorr_q = 0, Vcorr_lj = 0; real dvdl_long_range_q = 0, dvdl_long_range_lj = 0; bSB = (ir->nwall == 2); if (bSB) { copy_mat(box, boxs); svmul(ir->wall_ewald_zfac, boxs[ZZ], boxs[ZZ]); box_size[ZZ] *= ir->wall_ewald_zfac; } if (EEL_PME_EWALD(fr->eeltype) || EVDW_PME(fr->vdwtype)) { real dvdl_long_range_correction_q = 0; real dvdl_long_range_correction_lj = 0; /* With the Verlet scheme exclusion forces are calculated * in the non-bonded kernel. */ /* The TPI molecule does not have exclusions with the rest * of the system and no intra-molecular PME grid * contributions will be calculated in * gmx_pme_calc_energy. */ if ((ir->cutoff_scheme == ecutsGROUP && fr->n_tpi == 0) || ir->ewald_geometry != eewg3D || ir->epsilon_surface != 0) { int nthreads, t; wallcycle_sub_start(wcycle, ewcsEWALD_CORRECTION); if (fr->n_tpi > 0) { gmx_fatal(FARGS, "TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions"); } nthreads = fr->nthread_ewc; #pragma omp parallel for num_threads(nthreads) schedule(static) for (t = 0; t < nthreads; t++) { try { tensor *vir_q, *vir_lj; real *Vcorrt_q, *Vcorrt_lj, *dvdlt_q, *dvdlt_lj; if (t == 0) { vir_q = &fr->vir_el_recip; vir_lj = &fr->vir_lj_recip; Vcorrt_q = &Vcorr_q; Vcorrt_lj = &Vcorr_lj; dvdlt_q = &dvdl_long_range_correction_q; dvdlt_lj = &dvdl_long_range_correction_lj; } else { vir_q = &fr->ewc_t[t].vir_q; vir_lj = &fr->ewc_t[t].vir_lj; Vcorrt_q = &fr->ewc_t[t].Vcorr_q; Vcorrt_lj = &fr->ewc_t[t].Vcorr_lj; dvdlt_q = &fr->ewc_t[t].dvdl[efptCOUL]; dvdlt_lj = &fr->ewc_t[t].dvdl[efptVDW]; clear_mat(*vir_q); clear_mat(*vir_lj); } *dvdlt_q = 0; *dvdlt_lj = 0; /* Threading is only supported with the Verlet cut-off * scheme and then only single particle forces (no * exclusion forces) are calculated, so we can store * the forces in the normal, single fr->f_novirsum array. */ ewald_LRcorrection(fr->excl_load[t], fr->excl_load[t+1], cr, t, fr, md->chargeA, md->chargeB, md->sqrt_c6A, md->sqrt_c6B, md->sigmaA, md->sigmaB, md->sigma3A, md->sigma3B, md->nChargePerturbed || md->nTypePerturbed, ir->cutoff_scheme != ecutsVERLET, excl, x, bSB ? boxs : box, mu_tot, ir->ewald_geometry, ir->epsilon_surface, fr->f_novirsum, *vir_q, *vir_lj, Vcorrt_q, Vcorrt_lj, lambda[efptCOUL], lambda[efptVDW], dvdlt_q, dvdlt_lj); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; } if (nthreads > 1) { reduce_thread_energies(fr->vir_el_recip, fr->vir_lj_recip, &Vcorr_q, &Vcorr_lj, &dvdl_long_range_correction_q, &dvdl_long_range_correction_lj, nthreads, fr->ewc_t); } wallcycle_sub_stop(wcycle, ewcsEWALD_CORRECTION); }
void do_force_listed(gmx_wallcycle *wcycle, matrix box, const t_lambda *fepvals, const gmx_multisim_t *ms, const t_idef *idef, const rvec x[], history_t *hist, rvec f[], t_forcerec *fr, const struct t_pbc *pbc, const struct t_graph *graph, gmx_enerdata_t *enerd, t_nrnb *nrnb, real *lambda, const t_mdatoms *md, t_fcdata *fcd, int *global_atom_index, int flags) { t_pbc pbc_full; /* Full PBC is needed for position restraints */ if (!(flags & GMX_FORCE_LISTED)) { return; } if ((idef->il[F_POSRES].nr > 0) || (idef->il[F_FBPOSRES].nr > 0)) { /* Not enough flops to bother counting */ set_pbc(&pbc_full, fr->ePBC, box); } calc_listed(ms, wcycle, idef, x, hist, f, fr, pbc, &pbc_full, graph, enerd, nrnb, lambda, md, fcd, global_atom_index, flags); /* Check if we have to determine energy differences * at foreign lambda's. */ if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL)) { posres_wrapper_lambda(wcycle, fepvals, idef, &pbc_full, x, enerd, lambda, fr); if (idef->ilsort != ilsortNO_FE) { wallcycle_sub_start(wcycle, ewcsLISTED_FEP); if (idef->ilsort != ilsortFE_SORTED) { gmx_incons("The bonded interactions are not sorted for free energy"); } for (int i = 0; i < enerd->n_lambda; i++) { real lam_i[efptNR]; reset_foreign_enerdata(enerd); for (int j = 0; j < efptNR; j++) { lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]); } calc_listed_lambda(idef, x, fr, pbc, graph, &(enerd->foreign_grpp), enerd->foreign_term, nrnb, lam_i, md, fcd, global_atom_index); sum_epot(&(enerd->foreign_grpp), enerd->foreign_term); enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT]; } wallcycle_sub_stop(wcycle, ewcsLISTED_FEP); } } debug_gmx(); }
void parse_common_args(int *argc,char *argv[],unsigned long Flags, int nfile,t_filenm fnm[],int npargs,t_pargs *pa, int ndesc,char **desc,int nbugs,char **bugs) { static bool bHelp=FALSE,bHidden=FALSE,bQuiet=FALSE; static char *manstr[] = { NULL, "no", "html", "tex", "nroff", "ascii", "completion", NULL }; static char *not_nicestr[] = { NULL, "0", "4", "10", "19", NULL }; static char *nicestr[] = { NULL, "19", "10", "4", "0", NULL }; static char *not_npristr[] = { NULL, "0", "128", "100", "200", "250", NULL }; static char *npristr[] = { NULL, "128", "250", "200", "100", "0", NULL }; static int nicelevel=0,mantp=0,npri=0; static bool bGUI=FALSE,bDebug=FALSE; static char *deffnm=NULL; FILE *fp; bool bPrint,bExit; int i,j,k,npall; char *ptr,*newdesc; char *envstr; t_pargs *all_pa=NULL; t_pargs motif_pa = { "-X", FALSE, etBOOL, {&bGUI}, "Use dialog box GUI to edit command line options" }; t_pargs npri_paX = { "-npri", FALSE, etENUM, {not_npristr}, "Set non blocking priority" }; t_pargs npri_pa = { "-npri", FALSE, etINT, {&npri}, "HIDDEN Set non blocking priority (try 128)" }; t_pargs nice_paX = { "-nice", FALSE, etENUM, {not_nicestr}, "Set the nicelevel" }; t_pargs nice_pa = { "-nice", FALSE, etINT, {&nicelevel}, "Set the nicelevel" }; t_pargs deffnm_pa = { "-deffnm", FALSE, etSTR, {&deffnm}, "Set the default filename for all file options" }; t_pargs begin_pa = { "-b", FALSE, etTIME, {&tbegin}, "First frame (%t) to read from trajectory" }; t_pargs end_pa = { "-e", FALSE, etTIME, {&tend}, "Last frame (%t) to read from trajectory" }; t_pargs dt_pa = { "-dt", FALSE, etTIME, {&tdelta}, "Only use frame when t MOD dt = first time (%t)" }; t_pargs view_pa = { "-w", FALSE, etBOOL, {&bView}, "View output xvg, xpm, eps and pdb files" }; t_pargs time_pa = { "-tu", FALSE, etENUM, {timestr}, "Time unit" }; t_pargs pca_pa[] = { { "-h", FALSE, etBOOL, {&bHelp}, "Print help info and quit" }, { "-hidden", FALSE, etBOOL, {&bHidden}, "HIDDENPrint hidden options" }, { "-quiet",FALSE, etBOOL, {&bQuiet}, "HIDDENDo not print help info" }, { "-man", FALSE, etENUM, {manstr}, "HIDDENWrite manual and quit" }, { "-debug",FALSE, etBOOL, {&bDebug}, "HIDDENWrite file with debug information" }, }; #define NPCA_PA asize(pca_pa) debug_gmx(); if (debug) { fprintf(debug,"PID=%d, argc = %d\n",gmx_node_id(),*argc); for(i=0; (i<*argc); i++) fprintf(debug,"PID=%d, argv[%d] = %s\n",gmx_node_id(),i,argv[i]); } /* Check for double arguments */ for (i=1; (i<*argc); i++) { if (argv[i] && (strlen(argv[i]) > 1) && (!isdigit(argv[i][1]))) { for (j=i+1; (j<*argc); j++) { if ( (argv[i][0]=='-') && (argv[j][0]=='-') && (strcmp(argv[i],argv[j])==0) ) { if (FF(PCA_NOEXIT_ON_ARGS)) fprintf(stderr,"Double command line argument %s\n",argv[i]); else fatal_error(0,"Double command line argument %s\n",argv[i]); } } } } debug_gmx(); /* Handle the flags argument, which is a bit field * The FF macro returns whether or not the bit is set */ uFlags = Flags; bPrint = !FF(PCA_SILENT); /* Check whether we should have GUI or not */ #ifdef HAVE_MOTIF bGUI = (getenv("GMXMOTIF") != NULL); for(i=1; (i<*argc); i++) { if (strcmp(argv[i],"-X") == 0) bGUI = TRUE; else if (strcmp(argv[i],"-noX") == 0) bGUI = FALSE; } if (bGUI) bQuiet = TRUE; #else bGUI = FALSE; #endif set_program_name(argv[0]); /* Check ALL the flags ... */ snew(all_pa,NPCA_PA+npargs); for(i=npall=0; (i<NPCA_PA); i++) npall = add_parg(npall,&(all_pa),&(pca_pa[i])); /* Motif options */ npall = add_parg(npall,&(all_pa),&motif_pa); #if (defined __sgi && !defined SPEC_CPU) envstr = getenv("GMXNPRIALL"); if (envstr) npri=atoi(envstr); if (FF(PCA_BE_NICE)) { envstr = getenv("GMXNPRI"); if (envstr) npri=atoi(envstr); } if (bGUI) { if (npri) npri_paX.u.c = npristr; npall = add_parg(npall,&(all_pa),&npri_paX); } else npall = add_parg(npall,&(all_pa),&npri_pa); #endif if (bGUI) { /* Automatic nice or scheduling options */ if (FF(PCA_BE_NICE)) nice_paX.u.c = nicestr; npall = add_parg(npall,&(all_pa),&nice_paX); } else { if (FF(PCA_BE_NICE)) nicelevel=19; npall = add_parg(npall,&(all_pa),&nice_pa); } if (FF(PCA_CAN_SET_DEFFNM)) npall = add_parg(npall,&(all_pa),&deffnm_pa); if (FF(PCA_CAN_BEGIN)) npall = add_parg(npall,&(all_pa),&begin_pa); if (FF(PCA_CAN_END)) npall = add_parg(npall,&(all_pa),&end_pa); if (FF(PCA_CAN_DT)) npall = add_parg(npall,&(all_pa),&dt_pa); #ifndef SPEC_CPU if (FF(PCA_TIME_UNIT)) { envstr = getenv("GMXTIMEUNIT"); if ( envstr == NULL ) envstr="ps"; set_default_time_unit(envstr); npall = add_parg(npall,&(all_pa),&time_pa); } else #endif set_default_time_unit("ps"); if (FF(PCA_CAN_VIEW)) npall = add_parg(npall,&(all_pa),&view_pa); /* Now append the program specific arguments */ for(i=0; (i<npargs); i++) npall = add_parg(npall,&(all_pa),&(pa[i])); /* set etENUM options to default */ for(i=0; (i<npall); i++) if (all_pa[i].type==etENUM) all_pa[i].u.c[0]=all_pa[i].u.c[1]; /* Now parse all the command-line options */ get_pargs(argc,argv,npall,all_pa,FF(PCA_KEEP_ARGS)); if (FF(PCA_CAN_SET_DEFFNM) && (deffnm!=NULL)) set_default_file_name(deffnm); /* Parse the file args */ parse_file_args(argc,argv,nfile,fnm,FF(PCA_KEEP_ARGS)); /* Open the debug file */ if (bDebug) { char buf[256]; if (gmx_node_num() > 1) sprintf(buf,"%s%d.log",ShortProgram(),gmx_node_id()); else sprintf(buf,"%s.log",ShortProgram()); init_debug(buf); fprintf(debug,"%s (this file) opened in file %s, line %d\n", buf,__FILE__,__LINE__); } /* Now we have parsed the command line arguments. If the user wants it * we can now plop up a GUI dialog box to edit options. */ if (bGUI) { #ifdef HAVE_MOTIF gmx_gui(argc,argv,nfile,fnm,npall,all_pa,ndesc,desc,nbugs,bugs); #else fatal_error(0,"GROMACS compiled without MOTIF support - can't use X interface"); #endif } /* Now copy the results back... */ for(i=0,k=npall-npargs; (i<npargs); i++,k++) memcpy(&(pa[i]),&(all_pa[k]),(size_t)sizeof(pa[i])); for(i=0; (i<npall); i++) all_pa[i].desc = mk_desc(&(all_pa[i]), time_unit() ); bExit = bHelp || (strcmp(manstr[0],"no") != 0); #if (defined __sgi && USE_SGI_FPE) doexceptions(); #endif /* Set the nice level */ #ifdef __sgi if (bGUI) if (npri) sscanf(npristr[0],"%d",&npri); else sscanf(not_npristr[0],"%d",&npri); if (npri != 0 && !bExit) { (void) schedctl(MPTS_RTPRI,0,npri); } else #endif #ifdef HAVE_UNISTD_H if (bGUI) { if (FF(PCA_BE_NICE)) sscanf(nicestr[0],"%d",&nicelevel); else sscanf(not_nicestr[0],"%d",&nicelevel); } if (nicelevel != 0 && !bExit) nice(nicelevel); #endif if (!(FF(PCA_QUIET) || bQuiet )) { if (bHelp) write_man(stderr,"help",program,ndesc,desc,nfile,fnm,npall,all_pa, nbugs,bugs,bHidden); else if (bPrint) { pr_fns(stderr,nfile,fnm); print_pargs(stderr,npall,all_pa); } } if (strcmp(manstr[0],"no") != 0) { if(!strcmp(manstr[0],"completion")) { /* one file each for csh, bash and zsh if we do completions */ fp=man_file(program,"completion-zsh"); write_man(fp,"completion-zsh",program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); fclose(fp); fp=man_file(program,"completion-bash"); write_man(fp,"completion-bash",program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); fclose(fp); fp=man_file(program,"completion-csh"); write_man(fp,"completion-csh",program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); fclose(fp); } else { fp=man_file(program,manstr[0]); write_man(fp,manstr[0],program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); fclose(fp); } } /* convert time options, must be done after printing! */ init_time_factor(); for(i=0; i<npall; i++) { if ((all_pa[i].type == etTIME) && (*all_pa[i].u.r >= 0)) { *all_pa[i].u.r /= timefactor; } } /* clear memory */ for(i=0; i<npall; i++) sfree(all_pa[i].desc); sfree(all_pa); if (!FF(PCA_NOEXIT_ON_ARGS)) { if (*argc > 1) { for(i=1; (i<*argc); i++) fprintf(stderr,"Unknown argument: %s\n",argv[i]); fatal_error(0,"Program %s halted",Program()); } } if (bExit) { #ifdef USE_MPI if (gmx_parallel) gmx_abort(gmx_node_id(),gmx_node_num(),0); #endif exit(0); } }
FILE *gmx_log_open(char *lognm,const t_commrec *cr,bool bMasterOnly, unsigned long Flags) { int len,testlen,pid; char buf[256],host[256]; time_t t; FILE *fp; bool bAppend = Flags & MD_APPENDFILES; debug_gmx(); /* Communicate the filename for logfile */ if (cr->nnodes > 1 && !bMasterOnly) { if (MASTER(cr)) len = strlen(lognm)+1; gmx_bcast(sizeof(len),&len,cr); if (!MASTER(cr)) snew(lognm,len+8); gmx_bcast(len*sizeof(*lognm),lognm,cr); } debug_gmx(); if (PAR(cr) && !bMasterOnly) { /* Since log always ends with '.log' let's use this info */ par_fn(lognm,efLOG,cr,cr->ms!=NULL,buf,255); fp = gmx_fio_fopen(buf, bAppend ? "a" : "w" ); } else { fp = gmx_fio_fopen(lognm, bAppend ? "a" : "w" ); } gmx_fatal_set_log_file(fp); /* Get some machine parameters */ #ifdef HAVE_UNISTD_H if( gethostname(host,255) != 0) sprintf(host,"unknown"); #else sprintf(host,"unknown"); #endif time(&t); #ifndef NO_GETPID # if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__) pid = _getpid(); # else pid = getpid(); # endif #else pid = 0; #endif if(bAppend) { fprintf(fp, "\n\n" "-----------------------------------------------------------\n" "Restarting from checkpoint, appending to previous log file.\n\n" ); } fprintf(fp, "Log file opened on %s" "Host: %s pid: %d nodeid: %d nnodes: %d\n", ctime(&t),host,pid,cr->nodeid,cr->nnodes); #if (defined BUILD_MACHINE && defined BUILD_TIME && defined BUILD_USER) fprintf(fp, "The Gromacs distribution was built %s by\n" "%s (%s)\n\n\n",BUILD_TIME,BUILD_USER,BUILD_MACHINE); #endif fflush(fp); debug_gmx(); return fp; }
gmx_bool parse_common_args(int *argc, char *argv[], unsigned long Flags, int nfile, t_filenm fnm[], int npargs, t_pargs *pa, int ndesc, const char **desc, int nbugs, const char **bugs, output_env_t *oenv) { /* This array should match the order of the enum in oenv.h */ const char *xvg_format[] = { NULL, "xmgrace", "xmgr", "none", NULL }; /* This array should match the order of the enum in oenv.h */ const char *time_units[] = { NULL, "fs", "ps", "ns", "us", "ms", "s", NULL }; int nicelevel = 0, debug_level = 0; char *deffnm = NULL; real tbegin = 0, tend = 0, tdelta = 0; gmx_bool bView = FALSE; t_pargs *all_pa = NULL; t_pargs nice_pa = { "-nice", FALSE, etINT, {&nicelevel}, "Set the nicelevel" }; t_pargs deffnm_pa = { "-deffnm", FALSE, etSTR, {&deffnm}, "Set the default filename for all file options" }; t_pargs begin_pa = { "-b", FALSE, etTIME, {&tbegin}, "First frame (%t) to read from trajectory" }; t_pargs end_pa = { "-e", FALSE, etTIME, {&tend}, "Last frame (%t) to read from trajectory" }; t_pargs dt_pa = { "-dt", FALSE, etTIME, {&tdelta}, "Only use frame when t MOD dt = first time (%t)" }; t_pargs view_pa = { "-w", FALSE, etBOOL, {&bView}, "View output [TT].xvg[tt], [TT].xpm[tt], [TT].eps[tt] and [TT].pdb[tt] files" }; t_pargs xvg_pa = { "-xvg", FALSE, etENUM, {xvg_format}, "xvg plot formatting" }; t_pargs time_pa = { "-tu", FALSE, etENUM, {time_units}, "Time unit" }; /* Maximum number of extra arguments */ #define EXTRA_PA 16 t_pargs pca_pa[] = { { "-debug", FALSE, etINT, {&debug_level}, "HIDDENWrite file with debug information, 1: short, 2: also x and f" }, }; #define NPCA_PA asize(pca_pa) gmx_bool bXvgr; int i, j, k, npall, max_pa; // Handle the flags argument, which is a bit field // The FF macro returns whether or not the bit is set #define FF(arg) ((Flags & arg) == arg) /* Check for double arguments */ for (i = 1; (i < *argc); i++) { if (argv[i] && (strlen(argv[i]) > 1) && (!std::isdigit(argv[i][1]))) { for (j = i+1; (j < *argc); j++) { if ( (argv[i][0] == '-') && (argv[j][0] == '-') && (strcmp(argv[i], argv[j]) == 0) ) { if (FF(PCA_NOEXIT_ON_ARGS)) { fprintf(stderr, "Double command line argument %s\n", argv[i]); } else { gmx_fatal(FARGS, "Double command line argument %s\n", argv[i]); } } } } } debug_gmx(); /* Check ALL the flags ... */ max_pa = NPCA_PA + EXTRA_PA + npargs+1; snew(all_pa, max_pa); for (i = npall = 0; (i < static_cast<int>(NPCA_PA)); i++) { npall = add_parg(npall, all_pa, &(pca_pa[i])); } if (FF(PCA_BE_NICE)) { nicelevel = 19; } npall = add_parg(npall, all_pa, &nice_pa); if (FF(PCA_CAN_SET_DEFFNM)) { npall = add_parg(npall, all_pa, &deffnm_pa); } if (FF(PCA_CAN_BEGIN)) { npall = add_parg(npall, all_pa, &begin_pa); } if (FF(PCA_CAN_END)) { npall = add_parg(npall, all_pa, &end_pa); } if (FF(PCA_CAN_DT)) { npall = add_parg(npall, all_pa, &dt_pa); } if (FF(PCA_TIME_UNIT)) { npall = add_parg(npall, all_pa, &time_pa); } if (FF(PCA_CAN_VIEW)) { npall = add_parg(npall, all_pa, &view_pa); } bXvgr = FALSE; for (i = 0; (i < nfile); i++) { bXvgr = bXvgr || (fnm[i].ftp == efXVG); } if (bXvgr) { npall = add_parg(npall, all_pa, &xvg_pa); } /* Now append the program specific arguments */ for (i = 0; (i < npargs); i++) { npall = add_parg(npall, all_pa, &(pa[i])); } /* set etENUM options to default */ for (i = 0; (i < npall); i++) { if (all_pa[i].type == etENUM) { all_pa[i].u.c[0] = all_pa[i].u.c[1]; } } set_default_time_unit(time_units, FF(PCA_TIME_UNIT)); set_default_xvg_format(xvg_format); /* Now parse all the command-line options */ get_pargs(argc, argv, npall, all_pa); /* set program name, command line, and default values for output options */ output_env_init(oenv, gmx::getProgramContext(), (time_unit_t)nenum(time_units), bView, (xvg_format_t)nenum(xvg_format), 0, debug_level); /* Parse the file args */ parse_file_args(argc, argv, nfile, fnm, deffnm, !FF(PCA_NOT_READ_NODE)); /* Open the debug file */ if (debug_level > 0) { char buf[256]; if (gmx_mpi_initialized()) { sprintf(buf, "%s%d.debug", output_env_get_short_program_name(*oenv), gmx_node_rank()); } else { sprintf(buf, "%s.debug", output_env_get_short_program_name(*oenv)); } init_debug(debug_level, buf); fprintf(stderr, "Opening debug file %s (src code file %s, line %d)\n", buf, __FILE__, __LINE__); } /* Now copy the results back... */ for (i = 0, k = npall-npargs; (i < npargs); i++, k++) { memcpy(&(pa[i]), &(all_pa[k]), (size_t)sizeof(pa[i])); } bool bExit = false; try { const gmx::CommandLineHelpContext *context = gmx::GlobalCommandLineHelpContext::get(); bExit = (context != NULL); if (context != NULL && !(FF(PCA_QUIET))) { gmx::Options options(NULL, NULL); options.setDescription(gmx::constArrayRefFromArray(desc, ndesc)); for (i = 0; i < nfile; i++) { gmx::filenmToOptions(&options, &fnm[i]); } for (i = 0; i < npall; i++) { gmx::pargsToOptions(&options, &all_pa[i]); } gmx::CommandLineHelpWriter(options) .setShowDescriptions(true) .setTimeUnitString(output_env_get_time_unit(*oenv)) .setKnownIssues(gmx::constArrayRefFromArray(bugs, nbugs)) .writeHelp(*context); } } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; /* Set the nice level */ #if defined(HAVE_UNISTD_H) && !defined(__MINGW32__) #ifndef GMX_NO_NICE /* The some system, e.g. the catamount kernel on cray xt3 do not have nice(2). */ if (nicelevel != 0 && !bExit) { static gmx_bool nice_set = FALSE; /* only set it once */ static tMPI_Thread_mutex_t init_mutex = TMPI_THREAD_MUTEX_INITIALIZER; tMPI_Thread_mutex_lock(&init_mutex); if (!nice_set) { if (nice(nicelevel) == -1) { /* Do nothing, but use the return value to avoid warnings. */ } nice_set = TRUE; } tMPI_Thread_mutex_unlock(&init_mutex); } #endif #endif /* convert time options, must be done after printing! */ for (i = 0; i < npall; i++) { if (all_pa[i].type == etTIME && all_pa[i].bSet) { *all_pa[i].u.r *= output_env_get_time_invfactor(*oenv); } } /* Extract Time info from arguments */ if (FF(PCA_CAN_BEGIN) && opt2parg_bSet("-b", npall, all_pa)) { setTimeValue(TBEGIN, opt2parg_real("-b", npall, all_pa)); } if (FF(PCA_CAN_END) && opt2parg_bSet("-e", npall, all_pa)) { setTimeValue(TEND, opt2parg_real("-e", npall, all_pa)); } if (FF(PCA_CAN_DT) && opt2parg_bSet("-dt", npall, all_pa)) { setTimeValue(TDELTA, opt2parg_real("-dt", npall, all_pa)); } /* clear memory */ sfree(all_pa); if (!FF(PCA_NOEXIT_ON_ARGS)) { if (*argc > 1) { gmx_cmd(argv[1]); } } return !bExit; #undef FF }
void parse_common_args(int *argc,char *argv[],unsigned long Flags, int nfile,t_filenm fnm[],int npargs,t_pargs *pa, int ndesc,const char **desc, int nbugs,const char **bugs, output_env_t *oenv) { gmx_bool bHelp=FALSE,bHidden=FALSE,bQuiet=FALSE,bVersion=FALSE; const char *manstr[] = { NULL, "no", "html", "tex", "nroff", "ascii", "completion", "py", "xml", "wiki", NULL }; /* This array should match the order of the enum in oenv.h */ const char *xvg_format[] = { NULL, "xmgrace", "xmgr", "none", NULL }; /* This array should match the order of the enum in oenv.h */ const char *time_units[] = { NULL, "fs", "ps", "ns", "us", "ms", "s", NULL }; int nicelevel=0,mantp=0,npri=0,debug_level=0,verbose_level=0; char *deffnm=NULL; real tbegin=0,tend=0,tdelta=0; gmx_bool bView=FALSE; t_pargs *all_pa=NULL; t_pargs npri_pa = { "-npri", FALSE, etINT, {&npri}, "HIDDEN Set non blocking priority (try 128)" }; t_pargs nice_pa = { "-nice", FALSE, etINT, {&nicelevel}, "Set the nicelevel" }; t_pargs deffnm_pa = { "-deffnm", FALSE, etSTR, {&deffnm}, "Set the default filename for all file options" }; t_pargs begin_pa = { "-b", FALSE, etTIME, {&tbegin}, "First frame (%t) to read from trajectory" }; t_pargs end_pa = { "-e", FALSE, etTIME, {&tend}, "Last frame (%t) to read from trajectory" }; t_pargs dt_pa = { "-dt", FALSE, etTIME, {&tdelta}, "Only use frame when t MOD dt = first time (%t)" }; t_pargs view_pa = { "-w", FALSE, etBOOL, {&bView}, "View output xvg, xpm, eps and pdb files" }; t_pargs xvg_pa = { "-xvg", FALSE, etENUM, {xvg_format}, "xvg plot formatting" }; t_pargs time_pa = { "-tu", FALSE, etENUM, {time_units}, "Time unit" }; /* Maximum number of extra arguments */ #define EXTRA_PA 16 t_pargs pca_pa[] = { { "-h", FALSE, etBOOL, {&bHelp}, "Print help info and quit" }, { "-version", FALSE, etBOOL, {&bVersion}, "Print version info and quit" }, { "-verb", FALSE, etINT, {&verbose_level}, "HIDDENLevel of verbosity for this program" }, { "-hidden", FALSE, etBOOL, {&bHidden}, "HIDDENPrint hidden options" }, { "-quiet",FALSE, etBOOL, {&bQuiet}, "HIDDENDo not print help info" }, { "-man", FALSE, etENUM, {manstr}, "HIDDENWrite manual and quit" }, { "-debug",FALSE, etINT, {&debug_level}, "HIDDENWrite file with debug information, 1: short, 2: also x and f" }, }; #define NPCA_PA asize(pca_pa) FILE *fp; gmx_bool bPrint,bExit,bXvgr; int i,j,k,npall,max_pa,cmdlength; char *ptr,*newdesc; const char *envstr; #define FF(arg) ((Flags & arg)==arg) snew(*oenv, 1); cmdlength = strlen(argv[0]); /* Check for double arguments */ for (i=1; (i<*argc); i++) { cmdlength += strlen(argv[i]); if (argv[i] && (strlen(argv[i]) > 1) && (!isdigit(argv[i][1]))) { for (j=i+1; (j<*argc); j++) { if ( (argv[i][0]=='-') && (argv[j][0]=='-') && (strcmp(argv[i],argv[j])==0) ) { if (FF(PCA_NOEXIT_ON_ARGS)) fprintf(stderr,"Double command line argument %s\n", argv[i]); else gmx_fatal(FARGS,"Double command line argument %s\n", argv[i]); } } } } debug_gmx(); set_program_name(argv[0]); set_command_line(*argc, argv); /* Handle the flags argument, which is a bit field * The FF macro returns whether or not the bit is set */ bPrint = !FF(PCA_SILENT); /* Check ALL the flags ... */ max_pa = NPCA_PA + EXTRA_PA + npargs+1; snew(all_pa,max_pa); for(i=npall=0; (i<NPCA_PA); i++) npall = add_parg(npall,all_pa,&(pca_pa[i])); #ifdef __sgi envstr = getenv("GMXNPRIALL"); if (envstr) npri=strtol(envstr,NULL,10); if (FF(PCA_BE_NICE)) { envstr = getenv("GMXNPRI"); if (envstr) npri=strtol(envstr,NULL,10); } npall = add_parg(npall,all_pa,&npri_pa); #endif if (FF(PCA_BE_NICE)) nicelevel=19; npall = add_parg(npall,all_pa,&nice_pa); if (FF(PCA_CAN_SET_DEFFNM)) npall = add_parg(npall,all_pa,&deffnm_pa); if (FF(PCA_CAN_BEGIN)) npall = add_parg(npall,all_pa,&begin_pa); if (FF(PCA_CAN_END)) npall = add_parg(npall,all_pa,&end_pa); if (FF(PCA_CAN_DT)) { npall = add_parg(npall,all_pa,&dt_pa); } if (FF(PCA_TIME_UNIT)) { npall = add_parg(npall,all_pa,&time_pa); } if (FF(PCA_CAN_VIEW)) npall = add_parg(npall,all_pa,&view_pa); bXvgr = FALSE; for(i=0; (i<nfile); i++) { bXvgr = bXvgr || (fnm[i].ftp == efXVG); } if (bXvgr) { npall = add_parg(npall,all_pa,&xvg_pa); } /* Now append the program specific arguments */ for(i=0; (i<npargs); i++) npall = add_parg(npall,all_pa,&(pa[i])); /* set etENUM options to default */ for(i=0; (i<npall); i++) { if (all_pa[i].type==etENUM) { all_pa[i].u.c[0]=all_pa[i].u.c[1]; } } set_default_time_unit(time_units,FF(PCA_TIME_UNIT)); set_default_xvg_format(xvg_format); /* Now parse all the command-line options */ get_pargs(argc,argv,npall,all_pa,FF(PCA_KEEP_ARGS)); /* set program name, command line, and default values for output options */ output_env_init(*oenv, *argc, argv, (time_unit_t)nenum(time_units), bView, (xvg_format_t)nenum(xvg_format), verbose_level, debug_level); if (bVersion) { printf("Program: %s\n",output_env_get_program_name(*oenv)); gmx_print_version_info(stdout); exit(0); } if (FF(PCA_CAN_SET_DEFFNM) && (deffnm!=NULL)) set_default_file_name(deffnm); /* Parse the file args */ parse_file_args(argc,argv,nfile,fnm,FF(PCA_KEEP_ARGS),!FF(PCA_NOT_READ_NODE)); /* Open the debug file */ if (debug_level > 0) { char buf[256]; if (gmx_mpi_initialized()) sprintf(buf,"%s%d.debug",output_env_get_short_program_name(*oenv), gmx_node_rank()); else sprintf(buf,"%s.debug",output_env_get_short_program_name(*oenv)); init_debug(debug_level,buf); fprintf(stderr,"Opening debug file %s (src code file %s, line %d)\n", buf,__FILE__,__LINE__); } /* Now copy the results back... */ for(i=0,k=npall-npargs; (i<npargs); i++,k++) memcpy(&(pa[i]),&(all_pa[k]),(size_t)sizeof(pa[i])); for(i=0; (i<npall); i++) all_pa[i].desc = mk_desc(&(all_pa[i]), output_env_get_time_unit(*oenv)); bExit = bHelp || (strcmp(manstr[0],"no") != 0); #if (defined __sgi && USE_SGI_FPE) doexceptions(); #endif /* Set the nice level */ #ifdef __sgi if (npri != 0 && !bExit) { schedctl(MPTS_RTPRI,0,npri); } #endif #ifdef HAVE_UNISTD_H #ifndef GMX_NO_NICE /* The some system, e.g. the catamount kernel on cray xt3 do not have nice(2). */ if (nicelevel != 0 && !bExit) { #ifdef GMX_THREADS static gmx_bool nice_set=FALSE; /* only set it once */ tMPI_Thread_mutex_lock(&init_mutex); if (!nice_set) { #endif i=nice(nicelevel); /* assign ret value to avoid warnings */ #ifdef GMX_THREADS nice_set=TRUE; } tMPI_Thread_mutex_unlock(&init_mutex); #endif } #endif #endif /* Update oenv for parsed command line options settings. */ (*oenv)->xvg_format = (xvg_format_t)nenum(xvg_format); (*oenv)->time_unit = (time_unit_t)nenum(time_units); if (!(FF(PCA_QUIET) || bQuiet )) { if (bHelp) write_man(stderr,"help",output_env_get_program_name(*oenv), ndesc,desc,nfile, fnm,npall,all_pa, nbugs,bugs,bHidden); else if (bPrint) { pr_fns(stderr,nfile,fnm); print_pargs(stderr,npall,all_pa,FALSE); } } if (strcmp(manstr[0],"no") != 0) { if(!strcmp(manstr[0],"completion")) { /* one file each for csh, bash and zsh if we do completions */ fp=man_file(*oenv,"completion-zsh"); write_man(fp,"completion-zsh",output_env_get_program_name(*oenv), ndesc,desc,nfile, fnm, npall,all_pa,nbugs,bugs,bHidden); gmx_fio_fclose(fp); fp=man_file(*oenv,"completion-bash"); write_man(fp,"completion-bash",output_env_get_program_name(*oenv), ndesc,desc,nfile, fnm, npall,all_pa,nbugs,bugs,bHidden); gmx_fio_fclose(fp); fp=man_file(*oenv,"completion-csh"); write_man(fp,"completion-csh",output_env_get_program_name(*oenv), ndesc,desc,nfile, fnm, npall,all_pa,nbugs,bugs,bHidden); gmx_fio_fclose(fp); } else { fp=man_file(*oenv,manstr[0]); write_man(fp,manstr[0],output_env_get_program_name(*oenv), ndesc,desc,nfile,fnm, npall, all_pa,nbugs,bugs,bHidden); gmx_fio_fclose(fp); } } /* convert time options, must be done after printing! */ for(i=0; i<npall; i++) { if ((all_pa[i].type == etTIME) && (*all_pa[i].u.r >= 0)) { *all_pa[i].u.r *= output_env_get_time_invfactor(*oenv); } } /* Extract Time info from arguments */ if (FF(PCA_CAN_BEGIN) && opt2parg_bSet("-b",npall,all_pa)) setTimeValue(TBEGIN,opt2parg_real("-b",npall,all_pa)); if (FF(PCA_CAN_END) && opt2parg_bSet("-e",npall,all_pa)) setTimeValue(TEND,opt2parg_real("-e",npall,all_pa)); if (FF(PCA_CAN_DT) && opt2parg_bSet("-dt",npall,all_pa)) setTimeValue(TDELTA,opt2parg_real("-dt",npall,all_pa)); /* clear memory */ for (i = 0; i < npall; ++i) sfree((void *)all_pa[i].desc); sfree(all_pa); if (!FF(PCA_NOEXIT_ON_ARGS)) { if (*argc > 1) { gmx_cmd(argv[1]); } } if (bExit) { if (gmx_parallel_env_initialized()) /*gmx_abort(gmx_node_rank(),gmx_node_num(),0);*/ gmx_finalize(); exit(0); } #undef FF }
void do_force_lowlevel(t_forcerec *fr, t_inputrec *ir, t_idef *idef, t_commrec *cr, t_nrnb *nrnb, gmx_wallcycle_t wcycle, t_mdatoms *md, rvec x[], history_t *hist, rvec f[], rvec f_longrange[], gmx_enerdata_t *enerd, t_fcdata *fcd, gmx_localtop_t *top, gmx_genborn_t *born, gmx_bool bBornRadii, matrix box, t_lambda *fepvals, real *lambda, t_graph *graph, t_blocka *excl, rvec mu_tot[], int flags, float *cycles_pme) { int i, j; int donb_flags; gmx_bool bSB; int pme_flags; matrix boxs; rvec box_size; t_pbc pbc; real dvdl_dum[efptNR], dvdl_nb[efptNR]; #ifdef GMX_MPI double t0 = 0.0, t1, t2, t3; /* time measurement for coarse load balancing */ #endif set_pbc(&pbc, fr->ePBC, box); /* reset free energy components */ for (i = 0; i < efptNR; i++) { dvdl_nb[i] = 0; dvdl_dum[i] = 0; } /* Reset box */ for (i = 0; (i < DIM); i++) { box_size[i] = box[i][i]; } debug_gmx(); /* do QMMM first if requested */ if (fr->bQMMM) { enerd->term[F_EQM] = calculate_QMMM(cr, x, f, fr); } /* Call the short range functions all in one go. */ #ifdef GMX_MPI /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/ #define TAKETIME FALSE if (TAKETIME) { MPI_Barrier(cr->mpi_comm_mygroup); t0 = MPI_Wtime(); } #endif if (ir->nwall) { /* foreign lambda component for walls */ real dvdl_walls = do_walls(ir, fr, box, md, x, f, lambda[efptVDW], enerd->grpp.ener[egLJSR], nrnb); enerd->dvdl_lin[efptVDW] += dvdl_walls; } /* If doing GB, reset dvda and calculate the Born radii */ if (ir->implicit_solvent) { wallcycle_sub_start(wcycle, ewcsNONBONDED); for (i = 0; i < born->nr; i++) { fr->dvda[i] = 0; } if (bBornRadii) { calc_gb_rad(cr, fr, ir, top, x, &(fr->gblist), born, md, nrnb); } wallcycle_sub_stop(wcycle, ewcsNONBONDED); } where(); /* We only do non-bonded calculation with group scheme here, the verlet * calls are done from do_force_cutsVERLET(). */ if (fr->cutoff_scheme == ecutsGROUP && (flags & GMX_FORCE_NONBONDED)) { donb_flags = 0; /* Add short-range interactions */ donb_flags |= GMX_NONBONDED_DO_SR; /* Currently all group scheme kernels always calculate (shift-)forces */ if (flags & GMX_FORCE_FORCES) { donb_flags |= GMX_NONBONDED_DO_FORCE; } if (flags & GMX_FORCE_VIRIAL) { donb_flags |= GMX_NONBONDED_DO_SHIFTFORCE; } if (flags & GMX_FORCE_ENERGY) { donb_flags |= GMX_NONBONDED_DO_POTENTIAL; } if (flags & GMX_FORCE_DO_LR) { donb_flags |= GMX_NONBONDED_DO_LR; } wallcycle_sub_start(wcycle, ewcsNONBONDED); do_nonbonded(fr, x, f, f_longrange, md, excl, &enerd->grpp, nrnb, lambda, dvdl_nb, -1, -1, donb_flags); /* If we do foreign lambda and we have soft-core interactions * we have to recalculate the (non-linear) energies contributions. */ if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) && fepvals->sc_alpha != 0) { for (i = 0; i < enerd->n_lambda; i++) { real lam_i[efptNR]; for (j = 0; j < efptNR; j++) { lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]); } reset_foreign_enerdata(enerd); do_nonbonded(fr, x, f, f_longrange, md, excl, &(enerd->foreign_grpp), nrnb, lam_i, dvdl_dum, -1, -1, (donb_flags & ~GMX_NONBONDED_DO_FORCE) | GMX_NONBONDED_DO_FOREIGNLAMBDA); sum_epot(&(enerd->foreign_grpp), enerd->foreign_term); enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT]; } } wallcycle_sub_stop(wcycle, ewcsNONBONDED); where(); } /* If we are doing GB, calculate bonded forces and apply corrections * to the solvation forces */ /* MRS: Eventually, many need to include free energy contribution here! */ if (ir->implicit_solvent) { wallcycle_sub_start(wcycle, ewcsLISTED); calc_gb_forces(cr, md, born, top, x, f, fr, idef, ir->gb_algorithm, ir->sa_algorithm, nrnb, &pbc, graph, enerd); wallcycle_sub_stop(wcycle, ewcsLISTED); } #ifdef GMX_MPI if (TAKETIME) { t1 = MPI_Wtime(); fr->t_fnbf += t1-t0; } #endif if (fepvals->sc_alpha != 0) { enerd->dvdl_nonlin[efptVDW] += dvdl_nb[efptVDW]; } else { enerd->dvdl_lin[efptVDW] += dvdl_nb[efptVDW]; } if (fepvals->sc_alpha != 0) /* even though coulomb part is linear, we already added it, beacuse we need to go through the vdw calculation anyway */ { enerd->dvdl_nonlin[efptCOUL] += dvdl_nb[efptCOUL]; } else { enerd->dvdl_lin[efptCOUL] += dvdl_nb[efptCOUL]; } debug_gmx(); if (debug) { pr_rvecs(debug, 0, "fshift after SR", fr->fshift, SHIFTS); } /* Shift the coordinates. Must be done before listed forces and PPPM, * but is also necessary for SHAKE and update, therefore it can NOT * go when no listed forces have to be evaluated. * * The shifting and PBC code is deliberately not timed, since with * the Verlet scheme it only takes non-zero time with triclinic * boxes, and even then the time is around a factor of 100 less * than the next smallest counter. */ /* Here sometimes we would not need to shift with NBFonly, * but we do so anyhow for consistency of the returned coordinates. */ if (graph) { shift_self(graph, box, x); if (TRICLINIC(box)) { inc_nrnb(nrnb, eNR_SHIFTX, 2*graph->nnodes); } else { inc_nrnb(nrnb, eNR_SHIFTX, graph->nnodes); } } /* Check whether we need to do listed interactions or correct for exclusions */ if (fr->bMolPBC && ((flags & GMX_FORCE_LISTED) || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype) || EVDW_PME(fr->vdwtype))) { /* TODO There are no electrostatics methods that require this transformation, when using the Verlet scheme, so update the above conditional. */ /* Since all atoms are in the rectangular or triclinic unit-cell, * only single box vector shifts (2 in x) are required. */ set_pbc_dd(&pbc, fr->ePBC, cr->dd, TRUE, box); } debug_gmx(); do_force_listed(wcycle, box, ir->fepvals, cr->ms, idef, (const rvec *) x, hist, f, fr, &pbc, graph, enerd, nrnb, lambda, md, fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, flags); where(); *cycles_pme = 0; clear_mat(fr->vir_el_recip); clear_mat(fr->vir_lj_recip); /* Do long-range electrostatics and/or LJ-PME, including related short-range * corrections. */ if (EEL_FULL(fr->eeltype) || EVDW_PME(fr->vdwtype)) { int status = 0; real Vlr_q = 0, Vlr_lj = 0, Vcorr_q = 0, Vcorr_lj = 0; real dvdl_long_range_q = 0, dvdl_long_range_lj = 0; bSB = (ir->nwall == 2); if (bSB) { copy_mat(box, boxs); svmul(ir->wall_ewald_zfac, boxs[ZZ], boxs[ZZ]); box_size[ZZ] *= ir->wall_ewald_zfac; } if (EEL_PME_EWALD(fr->eeltype) || EVDW_PME(fr->vdwtype)) { real dvdl_long_range_correction_q = 0; real dvdl_long_range_correction_lj = 0; /* With the Verlet scheme exclusion forces are calculated * in the non-bonded kernel. */ /* The TPI molecule does not have exclusions with the rest * of the system and no intra-molecular PME grid * contributions will be calculated in * gmx_pme_calc_energy. */ if ((ir->cutoff_scheme == ecutsGROUP && fr->n_tpi == 0) || ir->ewald_geometry != eewg3D || ir->epsilon_surface != 0) { int nthreads, t; wallcycle_sub_start(wcycle, ewcsEWALD_CORRECTION); if (fr->n_tpi > 0) { gmx_fatal(FARGS, "TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions"); } nthreads = gmx_omp_nthreads_get(emntBonded); #pragma omp parallel for num_threads(nthreads) schedule(static) for (t = 0; t < nthreads; t++) { int i; rvec *fnv; tensor *vir_q, *vir_lj; real *Vcorrt_q, *Vcorrt_lj, *dvdlt_q, *dvdlt_lj; if (t == 0) { fnv = fr->f_novirsum; vir_q = &fr->vir_el_recip; vir_lj = &fr->vir_lj_recip; Vcorrt_q = &Vcorr_q; Vcorrt_lj = &Vcorr_lj; dvdlt_q = &dvdl_long_range_correction_q; dvdlt_lj = &dvdl_long_range_correction_lj; } else { fnv = fr->f_t[t].f; vir_q = &fr->f_t[t].vir_q; vir_lj = &fr->f_t[t].vir_lj; Vcorrt_q = &fr->f_t[t].Vcorr_q; Vcorrt_lj = &fr->f_t[t].Vcorr_lj; dvdlt_q = &fr->f_t[t].dvdl[efptCOUL]; dvdlt_lj = &fr->f_t[t].dvdl[efptVDW]; for (i = 0; i < fr->natoms_force; i++) { clear_rvec(fnv[i]); } clear_mat(*vir_q); clear_mat(*vir_lj); } *dvdlt_q = 0; *dvdlt_lj = 0; ewald_LRcorrection(fr->excl_load[t], fr->excl_load[t+1], cr, t, fr, md->chargeA, md->chargeB, md->sqrt_c6A, md->sqrt_c6B, md->sigmaA, md->sigmaB, md->sigma3A, md->sigma3B, md->nChargePerturbed || md->nTypePerturbed, ir->cutoff_scheme != ecutsVERLET, excl, x, bSB ? boxs : box, mu_tot, ir->ewald_geometry, ir->epsilon_surface, fnv, *vir_q, *vir_lj, Vcorrt_q, Vcorrt_lj, lambda[efptCOUL], lambda[efptVDW], dvdlt_q, dvdlt_lj); } if (nthreads > 1) { reduce_thread_forces(fr->natoms_force, fr->f_novirsum, fr->vir_el_recip, fr->vir_lj_recip, &Vcorr_q, &Vcorr_lj, &dvdl_long_range_correction_q, &dvdl_long_range_correction_lj, nthreads, fr->f_t); } wallcycle_sub_stop(wcycle, ewcsEWALD_CORRECTION); } if (EEL_PME_EWALD(fr->eeltype) && fr->n_tpi == 0) { /* This is not in a subcounter because it takes a negligible and constant-sized amount of time */ Vcorr_q += ewald_charge_correction(cr, fr, lambda[efptCOUL], box, &dvdl_long_range_correction_q, fr->vir_el_recip); } enerd->dvdl_lin[efptCOUL] += dvdl_long_range_correction_q; enerd->dvdl_lin[efptVDW] += dvdl_long_range_correction_lj; if ((EEL_PME(fr->eeltype) || EVDW_PME(fr->vdwtype)) && (cr->duty & DUTY_PME)) { /* Do reciprocal PME for Coulomb and/or LJ. */ assert(fr->n_tpi >= 0); if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED)) { pme_flags = GMX_PME_SPREAD | GMX_PME_SOLVE; if (EEL_PME(fr->eeltype)) { pme_flags |= GMX_PME_DO_COULOMB; } if (EVDW_PME(fr->vdwtype)) { pme_flags |= GMX_PME_DO_LJ; } if (flags & GMX_FORCE_FORCES) { pme_flags |= GMX_PME_CALC_F; } if (flags & GMX_FORCE_VIRIAL) { pme_flags |= GMX_PME_CALC_ENER_VIR; } if (fr->n_tpi > 0) { /* We don't calculate f, but we do want the potential */ pme_flags |= GMX_PME_CALC_POT; } wallcycle_start(wcycle, ewcPMEMESH); status = gmx_pme_do(fr->pmedata, 0, md->homenr - fr->n_tpi, x, fr->f_novirsum, md->chargeA, md->chargeB, md->sqrt_c6A, md->sqrt_c6B, md->sigmaA, md->sigmaB, bSB ? boxs : box, cr, DOMAINDECOMP(cr) ? dd_pme_maxshift_x(cr->dd) : 0, DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0, nrnb, wcycle, fr->vir_el_recip, fr->ewaldcoeff_q, fr->vir_lj_recip, fr->ewaldcoeff_lj, &Vlr_q, &Vlr_lj, lambda[efptCOUL], lambda[efptVDW], &dvdl_long_range_q, &dvdl_long_range_lj, pme_flags); *cycles_pme = wallcycle_stop(wcycle, ewcPMEMESH); if (status != 0) { gmx_fatal(FARGS, "Error %d in reciprocal PME routine", status); } /* We should try to do as little computation after * this as possible, because parallel PME synchronizes * the nodes, so we want all load imbalance of the * rest of the force calculation to be before the PME * call. DD load balancing is done on the whole time * of the force call (without PME). */ } if (fr->n_tpi > 0) { if (EVDW_PME(ir->vdwtype)) { gmx_fatal(FARGS, "Test particle insertion not implemented with LJ-PME"); } /* Determine the PME grid energy of the test molecule * with the PME grid potential of the other charges. */ gmx_pme_calc_energy(fr->pmedata, fr->n_tpi, x + md->homenr - fr->n_tpi, md->chargeA + md->homenr - fr->n_tpi, &Vlr_q); } } } if (!EEL_PME(fr->eeltype) && EEL_PME_EWALD(fr->eeltype)) { Vlr_q = do_ewald(ir, x, fr->f_novirsum, md->chargeA, md->chargeB, box_size, cr, md->homenr, fr->vir_el_recip, fr->ewaldcoeff_q, lambda[efptCOUL], &dvdl_long_range_q, fr->ewald_table); } /* Note that with separate PME nodes we get the real energies later */ enerd->dvdl_lin[efptCOUL] += dvdl_long_range_q; enerd->dvdl_lin[efptVDW] += dvdl_long_range_lj; enerd->term[F_COUL_RECIP] = Vlr_q + Vcorr_q; enerd->term[F_LJ_RECIP] = Vlr_lj + Vcorr_lj; if (debug) { fprintf(debug, "Vlr_q = %g, Vcorr_q = %g, Vlr_corr_q = %g\n", Vlr_q, Vcorr_q, enerd->term[F_COUL_RECIP]); pr_rvecs(debug, 0, "vir_el_recip after corr", fr->vir_el_recip, DIM); pr_rvecs(debug, 0, "fshift after LR Corrections", fr->fshift, SHIFTS); fprintf(debug, "Vlr_lj: %g, Vcorr_lj = %g, Vlr_corr_lj = %g\n", Vlr_lj, Vcorr_lj, enerd->term[F_LJ_RECIP]); pr_rvecs(debug, 0, "vir_lj_recip after corr", fr->vir_lj_recip, DIM); } } else { /* Is there a reaction-field exclusion correction needed? */ if (EEL_RF(fr->eeltype) && eelRF_NEC != fr->eeltype) { /* With the Verlet scheme, exclusion forces are calculated * in the non-bonded kernel. */ if (ir->cutoff_scheme != ecutsVERLET) { real dvdl_rf_excl = 0; enerd->term[F_RF_EXCL] = RF_excl_correction(fr, graph, md, excl, x, f, fr->fshift, &pbc, lambda[efptCOUL], &dvdl_rf_excl); enerd->dvdl_lin[efptCOUL] += dvdl_rf_excl; } } } where(); debug_gmx(); if (debug) { print_nrnb(debug, nrnb); } debug_gmx(); #ifdef GMX_MPI if (TAKETIME) { t2 = MPI_Wtime(); MPI_Barrier(cr->mpi_comm_mygroup); t3 = MPI_Wtime(); fr->t_wait += t3-t2; if (fr->timesteps == 11) { char buf[22]; fprintf(stderr, "* PP load balancing info: rank %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n", cr->nodeid, gmx_step_str(fr->timesteps, buf), 100*fr->t_wait/(fr->t_wait+fr->t_fnbf), (fr->t_fnbf+fr->t_wait)/fr->t_fnbf); } fr->timesteps++; } #endif if (debug) { pr_rvecs(debug, 0, "fshift after bondeds", fr->fshift, SHIFTS); } }
static int add_h_low(t_atoms **pdbaptr, rvec *xptr[], int nah, t_hackblock ah[], int nterpairs, t_hackblock **ntdb, t_hackblock **ctdb, int *rN, int *rC, gmx_bool bCheckMissing, int **nabptr, t_hack ***abptr, gmx_bool bUpdate_pdba, gmx_bool bKeep_old_pdba) { t_atoms *newpdba = NULL, *pdba = NULL; int nadd; int i, newi, j, d, natoms, nalreadypresent; int *nab = NULL; t_hack **ab = NULL; t_hackblock *hb; rvec *xn; gmx_bool bKeep_ab; /* set flags for adding hydrogens (according to hdb) */ pdba = *pdbaptr; natoms = pdba->nr; if (nabptr && abptr) { /* the first time these will be pointers to NULL, but we will return in them the completed arrays, which we will get back the second time */ nab = *nabptr; ab = *abptr; bKeep_ab = TRUE; if (debug) { fprintf(debug, "pointer to ab found\n"); } } else { bKeep_ab = FALSE; } if (nab && ab) { /* WOW, everything was already figured out */ bUpdate_pdba = FALSE; if (debug) { fprintf(debug, "pointer to non-null ab found\n"); } } else { /* We'll have to do all the hard work */ bUpdate_pdba = TRUE; /* first get all the hackblocks for each residue: */ hb = get_hackblocks(pdba, nah, ah, nterpairs, ntdb, ctdb, rN, rC); if (debug) { dump_hb(debug, pdba->nres, hb); } /* expand the hackblocks to atom level */ snew(nab, natoms); snew(ab, natoms); expand_hackblocks(pdba, hb, nab, ab, nterpairs, rN, rC); free_t_hackblock(pdba->nres, &hb); } if (debug) { fprintf(debug, "before calc_all_pos\n"); dump_ab(debug, natoms, nab, ab, TRUE); } /* Now calc the positions */ calc_all_pos(pdba, *xptr, nab, ab, bCheckMissing); if (debug) { fprintf(debug, "after calc_all_pos\n"); dump_ab(debug, natoms, nab, ab, TRUE); } if (bUpdate_pdba) { /* we don't have to add atoms that are already present in pdba, so we will remove them from the ab (t_hack) */ nadd = check_atoms_present(pdba, nab, ab); if (debug) { fprintf(debug, "removed add hacks that were already in pdba:\n"); dump_ab(debug, natoms, nab, ab, TRUE); fprintf(debug, "will be adding %d atoms\n", nadd); } /* Copy old atoms, making space for new ones */ snew(newpdba, 1); init_t_atoms(newpdba, natoms+nadd, FALSE); newpdba->nres = pdba->nres; sfree(newpdba->resinfo); newpdba->resinfo = pdba->resinfo; } else { nadd = 0; } if (debug) { fprintf(debug, "snew xn for %d old + %d new atoms %d total)\n", natoms, nadd, natoms+nadd); } if (nadd == 0) { /* There is nothing to do: return now */ if (!bKeep_ab) { free_ab(natoms, nab, ab); } return natoms; } snew(xn, natoms+nadd); newi = 0; for (i = 0; (i < natoms); i++) { /* check if this atom wasn't scheduled for deletion */ if (nab[i] == 0 || (ab[i][0].nname != NULL) ) { if (newi >= natoms+nadd) { /*gmx_fatal(FARGS,"Not enough space for adding atoms");*/ nadd += 10; srenew(xn, natoms+nadd); if (bUpdate_pdba) { srenew(newpdba->atom, natoms+nadd); srenew(newpdba->atomname, natoms+nadd); } debug_gmx(); } if (debug) { fprintf(debug, "(%3d) %3d %4s %4s%3d %3d", i+1, newi+1, *pdba->atomname[i], *pdba->resinfo[pdba->atom[i].resind].name, pdba->resinfo[pdba->atom[i].resind].nr, nab[i]); } if (bUpdate_pdba) { copy_atom(pdba, i, newpdba, newi); } copy_rvec((*xptr)[i], xn[newi]); /* process the hacks for this atom */ nalreadypresent = 0; for (j = 0; j < nab[i]; j++) { if (ab[i][j].oname == NULL) /* add */ { newi++; if (newi >= natoms+nadd) { /* gmx_fatal(FARGS,"Not enough space for adding atoms");*/ nadd += 10; srenew(xn, natoms+nadd); if (bUpdate_pdba) { srenew(newpdba->atom, natoms+nadd); srenew(newpdba->atomname, natoms+nadd); } debug_gmx(); } if (bUpdate_pdba) { newpdba->atom[newi].resind = pdba->atom[i].resind; } if (debug) { fprintf(debug, " + %d", newi+1); } } if (ab[i][j].nname != NULL && (ab[i][j].oname == NULL || strcmp(ab[i][j].oname, *newpdba->atomname[newi]) == 0)) { /* add or replace */ if (ab[i][j].oname == NULL && ab[i][j].bAlreadyPresent) { /* This atom is already present, copy it from the input. */ nalreadypresent++; if (bUpdate_pdba) { copy_atom(pdba, i+nalreadypresent, newpdba, newi); } copy_rvec((*xptr)[i+nalreadypresent], xn[newi]); } else { if (bUpdate_pdba) { if (gmx_debug_at) { fprintf(debug, "Replacing %d '%s' with (old name '%s') %s\n", newi, (newpdba->atomname[newi] && *newpdba->atomname[newi]) ? *newpdba->atomname[newi] : "", ab[i][j].oname ? ab[i][j].oname : "", ab[i][j].nname); } snew(newpdba->atomname[newi], 1); *newpdba->atomname[newi] = strdup(ab[i][j].nname); if (ab[i][j].oname != NULL && ab[i][j].atom) /* replace */ { /* newpdba->atom[newi].m = ab[i][j].atom->m; */ /* newpdba->atom[newi].q = ab[i][j].atom->q; */ /* newpdba->atom[newi].type = ab[i][j].atom->type; */ } } if (ab[i][j].bXSet) { copy_rvec(ab[i][j].newx, xn[newi]); } } if (bUpdate_pdba && debug) { fprintf(debug, " %s %g %g", *newpdba->atomname[newi], newpdba->atom[newi].m, newpdba->atom[newi].q); } } } newi++; i += nalreadypresent; if (debug) { fprintf(debug, "\n"); } } } if (bUpdate_pdba) { newpdba->nr = newi; } if (bKeep_ab) { *nabptr = nab; *abptr = ab; } else { /* Clean up */ free_ab(natoms, nab, ab); } if (bUpdate_pdba) { if (!bKeep_old_pdba) { for (i = 0; i < natoms; i++) { /* Do not free the atomname string itself, it might be in symtab */ /* sfree(*(pdba->atomname[i])); */ /* sfree(pdba->atomname[i]); */ } sfree(pdba->atomname); sfree(pdba->atom); sfree(pdba->pdbinfo); sfree(pdba); } *pdbaptr = newpdba; } else { nadd = newi-natoms; } sfree(*xptr); *xptr = xn; return newi; }
void init_md(t_commrec *cr,t_inputrec *ir,tensor box,real *t,real *t0, real *lambda,real *lam0,real *SAfactor, t_nrnb *mynrnb,bool *bTYZ,t_topology *top, int nfile,t_filenm fnm[],char **traj, char **xtc_traj,int *fp_ene, FILE **fp_dgdl,t_mdebin **mdebin,t_groups *grps, tensor force_vir,tensor pme_vir, tensor shake_vir,t_mdatoms *mdatoms,rvec mu_tot, bool *bNEMD,t_vcm **vcm,t_nsborder *nsb) { bool bBHAM,b14,bLR,bLJLR; int i; /* Initial values */ *t = *t0 = ir->init_t; if (ir->efep != efepNO) { *lambda = *lam0 = ir->init_lambda; } else { *lambda = *lam0 = 0.0; } if (ir->bSimAnn) { *SAfactor = 1.0 - *t0/ir->zero_temp_time; if (*SAfactor < 0) *SAfactor = 0; } else *SAfactor = 1.0; init_nrnb(mynrnb); /* Check Environment variables & other booleans */ #ifdef SPEC_CPU *bTYZ = FALSE; #else *bTYZ=getenv("TYZ") != NULL; #endif set_pot_bools(ir,top,&bLR,&bLJLR,&bBHAM,&b14); if (nfile != -1) { /* Filenames */ *traj = ftp2fn(efTRN,nfile,fnm); *xtc_traj = ftp2fn(efXTC,nfile,fnm); #ifndef SPEC_CPU if (MASTER(cr)) { *fp_ene = open_enx(ftp2fn(efENX,nfile,fnm),"w"); if ((fp_dgdl != NULL) && ir->efep!=efepNO) *fp_dgdl = xvgropen(opt2fn("-dgdl",nfile,fnm), "dG/d\\8l\\4","Time (ps)", "dG/d\\8l\\4 (kJ mol\\S-1\\N nm\\S-2\\N \\8l\\4\\S-1\\N)"); } else #endif *fp_ene = -1; *mdebin = init_mdebin(*fp_ene,grps,&(top->atoms),&(top->idef), bLR,bLJLR,bBHAM,b14,ir->efep!=efepNO,ir->epc, ir->eDispCorr,(TRICLINIC(ir->compress) || TRICLINIC(box)), (ir->etc==etcNOSEHOOVER),cr); } /* Initiate variables */ clear_mat(force_vir); clear_mat(pme_vir); clear_mat(shake_vir); clear_rvec(mu_tot); /* Set initial values for invmass etc. */ init_mdatoms(mdatoms,*lambda,TRUE); *vcm = init_vcm(stdlog,top,cr,mdatoms,START(nsb),HOMENR(nsb),ir->nstcomm); debug_gmx(); *bNEMD = (ir->opts.ngacc > 1) || (norm(ir->opts.acc[0]) > 0); if (ir->eI == eiSD) init_sd_consts(ir->opts.ngtc,ir->opts.tau_t,ir->delta_t); }
void init_md(FILE *fplog, t_commrec *cr,t_inputrec *ir,real *t,real *t0, real *lambda,real *lam0, t_nrnb *nrnb,gmx_mtop_t *mtop, gmx_stochd_t *sd, int nfile,t_filenm fnm[], int *fp_trn,int *fp_xtc,int *fp_ene,char **fn_cpt, FILE **fp_dgdl,FILE **fp_field, t_mdebin **mdebin, tensor force_vir,tensor shake_vir,rvec mu_tot, bool *bNEMD,bool *bSimAnn,t_vcm **vcm, unsigned long Flags) { int i,j,n; real tmpt,mod; char filemode[2]; sprintf(filemode, (Flags & MD_APPENDFILES) ? "a" : "w"); /* Initial values */ *t = *t0 = ir->init_t; if (ir->efep != efepNO) { *lam0 = ir->init_lambda; *lambda = *lam0 + ir->init_step*ir->delta_lambda; } else { *lambda = *lam0 = 0.0; } *bSimAnn=FALSE; for(i=0;i<ir->opts.ngtc;i++) { /* set bSimAnn if any group is being annealed */ if(ir->opts.annealing[i]!=eannNO) *bSimAnn = TRUE; } if (*bSimAnn) { update_annealing_target_temp(&(ir->opts),ir->init_t); } *bNEMD = (ir->opts.ngacc > 1) || (norm(ir->opts.acc[0]) > 0); if (sd && (ir->eI == eiBD || EI_SD(ir->eI) || ir->etc == etcVRESCALE)) { *sd = init_stochd(fplog,ir); } if (vcm) { *vcm = init_vcm(fplog,&mtop->groups,ir); } if (EI_DYNAMICS(ir->eI) && !(Flags & MD_APPENDFILES)) { if (ir->etc == etcBERENDSEN) { please_cite(fplog,"Berendsen84a"); } if (ir->etc == etcVRESCALE) { please_cite(fplog,"Bussi2007a"); } } init_nrnb(nrnb); if (nfile != -1) { *fp_trn = -1; *fp_ene = -1; *fp_xtc = -1; if (MASTER(cr)) { *fp_trn = open_trn(ftp2fn(efTRN,nfile,fnm), filemode); if (ir->nstxtcout > 0) { *fp_xtc = open_xtc(ftp2fn(efXTC,nfile,fnm), filemode); } *fp_ene = open_enx(ftp2fn(efENX,nfile,fnm), filemode); *fn_cpt = opt2fn("-cpo",nfile,fnm); if ((fp_dgdl != NULL) && ir->efep!=efepNO) { if(Flags & MD_APPENDFILES) { *fp_dgdl= gmx_fio_fopen(opt2fn("-dgdl",nfile,fnm),filemode); } else { *fp_dgdl = xvgropen(opt2fn("-dgdl",nfile,fnm), "dG/d\\8l\\4","Time (ps)", "dG/d\\8l\\4 (kJ mol\\S-1\\N [\\8l\\4]\\S-1\\N)"); } } if ((fp_field != NULL) && (ir->ex[XX].n || ir->ex[YY].n ||ir->ex[ZZ].n)) { if(Flags & MD_APPENDFILES) { *fp_field = gmx_fio_fopen(opt2fn("-field",nfile,fnm),filemode); } else { *fp_field = xvgropen(opt2fn("-field",nfile,fnm), "Applied electric field","Time (ps)", "E (V/nm)"); } } } *mdebin = init_mdebin( (Flags & MD_APPENDFILES) ? -1 : *fp_ene,mtop,ir); } /* Initiate variables */ clear_mat(force_vir); clear_mat(shake_vir); clear_rvec(mu_tot); debug_gmx(); }
void parse_common_args(int *argc,char *argv[],unsigned long Flags, int nfile,t_filenm fnm[],int npargs,t_pargs *pa, int ndesc,char **desc,int nbugs,char **bugs) { static bool bHelp=FALSE,bHidden=FALSE,bQuiet=FALSE; static char *manstr[] = { NULL, "no", "html", "tex", "nroff", "ascii", "completion", "py", "xml", "wiki", NULL }; static int nicelevel=0,mantp=0,npri=0,debug_level=0; static char *deffnm=NULL; static real tbegin=0,tend=0,tdelta=0; t_pargs *all_pa=NULL; t_pargs npri_pa = { "-npri", FALSE, etINT, {&npri}, "HIDDEN Set non blocking priority (try 128)" }; t_pargs nice_pa = { "-nice", FALSE, etINT, {&nicelevel}, "Set the nicelevel" }; t_pargs deffnm_pa = { "-deffnm", FALSE, etSTR, {&deffnm}, "Set the default filename for all file options" }; t_pargs begin_pa = { "-b", FALSE, etTIME, {&tbegin}, "First frame (%t) to read from trajectory" }; t_pargs end_pa = { "-e", FALSE, etTIME, {&tend}, "Last frame (%t) to read from trajectory" }; t_pargs dt_pa = { "-dt", FALSE, etTIME, {&tdelta}, "Only use frame when t MOD dt = first time (%t)" }; t_pargs view_pa = { "-w", FALSE, etBOOL, {&bView}, "View output xvg, xpm, eps and pdb files" }; t_pargs code_pa = { "-xvgr", FALSE, etBOOL, {&bXvgrCodes}, "Add specific codes (legends etc.) in the output xvg files for the xmgrace program" }; t_pargs time_pa = { "-tu", FALSE, etENUM, {timestr}, "Time unit" }; /* Maximum number of extra arguments */ #define EXTRA_PA 16 t_pargs pca_pa[] = { { "-h", FALSE, etBOOL, {&bHelp}, "Print help info and quit" }, { "-hidden", FALSE, etBOOL, {&bHidden}, "HIDDENPrint hidden options" }, { "-quiet",FALSE, etBOOL, {&bQuiet}, "HIDDENDo not print help info" }, { "-man", FALSE, etENUM, {manstr}, "HIDDENWrite manual and quit" }, { "-debug",FALSE, etINT, {&debug_level}, "HIDDENWrite file with debug information, 1: short, 2: also x and f" }, }; #define NPCA_PA asize(pca_pa) FILE *fp; bool bPrint,bExit,bXvgr; int i,j,k,npall,max_pa,cmdlength; char *ptr,*newdesc; char *envstr; #define FF(arg) ((Flags & arg)==arg) cmdlength = strlen(argv[0]); /* Check for double arguments */ for (i=1; (i<*argc); i++) { cmdlength += strlen(argv[i]); if (argv[i] && (strlen(argv[i]) > 1) && (!isdigit(argv[i][1]))) { for (j=i+1; (j<*argc); j++) { if ( (argv[i][0]=='-') && (argv[j][0]=='-') && (strcmp(argv[i],argv[j])==0) ) { if (FF(PCA_NOEXIT_ON_ARGS)) fprintf(stderr,"Double command line argument %s\n",argv[i]); else gmx_fatal(FARGS,"Double command line argument %s\n",argv[i]); } } } } debug_gmx(); /* Fill the cmdline string */ snew(cmdline,cmdlength+*argc+1); for (i=0; (i<*argc); i++) { strcat(cmdline,argv[i]); strcat(cmdline," "); } /* Handle the flags argument, which is a bit field * The FF macro returns whether or not the bit is set */ bPrint = !FF(PCA_SILENT); set_program_name(argv[0]); /* Check ALL the flags ... */ max_pa = NPCA_PA + EXTRA_PA + npargs; snew(all_pa,max_pa); for(i=npall=0; (i<NPCA_PA); i++) npall = add_parg(npall,all_pa,&(pca_pa[i])); #ifdef __sgi envstr = getenv("GMXNPRIALL"); if (envstr) npri=atoi(envstr); if (FF(PCA_BE_NICE)) { envstr = getenv("GMXNPRI"); if (envstr) npri=atoi(envstr); } npall = add_parg(npall,all_pa,&npri_pa); #endif if (FF(PCA_BE_NICE)) nicelevel=19; npall = add_parg(npall,all_pa,&nice_pa); if (FF(PCA_CAN_SET_DEFFNM)) npall = add_parg(npall,all_pa,&deffnm_pa); if (FF(PCA_CAN_BEGIN)) npall = add_parg(npall,all_pa,&begin_pa); if (FF(PCA_CAN_END)) npall = add_parg(npall,all_pa,&end_pa); if (FF(PCA_CAN_DT)) npall = add_parg(npall,all_pa,&dt_pa); if (FF(PCA_TIME_UNIT)) { envstr = getenv("GMXTIMEUNIT"); if ( envstr == NULL ) envstr="ps"; set_default_time_unit(envstr); npall = add_parg(npall,all_pa,&time_pa); } else set_default_time_unit("ps"); if (FF(PCA_CAN_VIEW)) npall = add_parg(npall,all_pa,&view_pa); bXvgr = FALSE; for(i=0; (i<nfile); i++) bXvgr = bXvgr || (fnm[i].ftp == efXVG); if (bXvgr) npall = add_parg(npall,all_pa,&code_pa); /* Now append the program specific arguments */ for(i=0; (i<npargs); i++) npall = add_parg(npall,all_pa,&(pa[i])); /* set etENUM options to default */ for(i=0; (i<npall); i++) if (all_pa[i].type==etENUM) all_pa[i].u.c[0]=all_pa[i].u.c[1]; /* Now parse all the command-line options */ get_pargs(argc,argv,npall,all_pa,FF(PCA_KEEP_ARGS)); if (FF(PCA_CAN_SET_DEFFNM) && (deffnm!=NULL)) set_default_file_name(deffnm); /* Parse the file args */ parse_file_args(argc,argv,nfile,fnm,FF(PCA_KEEP_ARGS)); /* Open the debug file */ if (debug_level > 0) { char buf[256]; if (gmx_mpi_initialized()) sprintf(buf,"%s%d.log",ShortProgram(),gmx_node_rank()); else sprintf(buf,"%s.log",ShortProgram()); init_debug(debug_level,buf); fprintf(stderr,"Opening debug file %s (src code file %s, line %d)\n", buf,__FILE__,__LINE__); } /* Now copy the results back... */ for(i=0,k=npall-npargs; (i<npargs); i++,k++) memcpy(&(pa[i]),&(all_pa[k]),(size_t)sizeof(pa[i])); for(i=0; (i<npall); i++) all_pa[i].desc = mk_desc(&(all_pa[i]), time_unit() ); bExit = bHelp || (strcmp(manstr[0],"no") != 0); #if (defined __sgi && USE_SGI_FPE) doexceptions(); #endif /* Set the nice level */ #ifdef __sgi if (npri != 0 && !bExit) { schedctl(MPTS_RTPRI,0,npri); } #endif #ifdef HAVE_UNISTD_H #ifndef GMX_NO_NICE /* The some system, e.g. the catamount kernel on cray xt3 do not have nice(2). */ if (nicelevel != 0 && !bExit) i=nice(nicelevel); /* assign ret value to avoid warnings */ #endif #endif if (!(FF(PCA_QUIET) || bQuiet )) { if (bHelp) write_man(stderr,"help",program,ndesc,desc,nfile,fnm,npall,all_pa, nbugs,bugs,bHidden); else if (bPrint) { pr_fns(stderr,nfile,fnm); print_pargs(stderr,npall,all_pa,FALSE); } } if (strcmp(manstr[0],"no") != 0) { if(!strcmp(manstr[0],"completion")) { /* one file each for csh, bash and zsh if we do completions */ fp=man_file(program,"completion-zsh"); write_man(fp,"completion-zsh",program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); gmx_fio_fclose(fp); fp=man_file(program,"completion-bash"); write_man(fp,"completion-bash",program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); gmx_fio_fclose(fp); fp=man_file(program,"completion-csh"); write_man(fp,"completion-csh",program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); gmx_fio_fclose(fp); } else { fp=man_file(program,manstr[0]); write_man(fp,manstr[0],program,ndesc,desc,nfile,fnm,npall,all_pa,nbugs,bugs,bHidden); gmx_fio_fclose(fp); } } /* convert time options, must be done after printing! */ init_time_factor(); for(i=0; i<npall; i++) { if ((all_pa[i].type == etTIME) && (*all_pa[i].u.r >= 0)) { *all_pa[i].u.r *= timeinvfac; } } /* Extract Time info from arguments */ if (FF(PCA_CAN_BEGIN) && opt2parg_bSet("-b",npall,all_pa)) setTimeValue(TBEGIN,opt2parg_real("-b",npall,all_pa)); if (FF(PCA_CAN_END) && opt2parg_bSet("-e",npall,all_pa)) setTimeValue(TEND,opt2parg_real("-e",npall,all_pa)); if (FF(PCA_CAN_DT) && opt2parg_bSet("-dt",npall,all_pa)) setTimeValue(TDELTA,opt2parg_real("-dt",npall,all_pa)); /* clear memory */ sfree(all_pa); if (!FF(PCA_NOEXIT_ON_ARGS)) { if (*argc > 1) { gmx_cmd(argv[1]); } } if (bExit) { if (gmx_parallel_env) gmx_abort(gmx_node_rank(),gmx_node_num(),0); else exit(0); } #undef FF }
double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[], const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact, int nstglobalcomm, gmx_vsite_t *vsite,gmx_constr_t constr, int stepout,t_inputrec *ir, gmx_mtop_t *top_global, t_fcdata *fcd, t_state *state_global, t_mdatoms *mdatoms, t_nrnb *nrnb,gmx_wallcycle_t wcycle, gmx_edsam_t ed,t_forcerec *fr, int repl_ex_nst,int repl_ex_seed, real cpt_period,real max_hours, const char *deviceOptions, unsigned long Flags, gmx_runtime_t *runtime) { gmx_mdoutf_t *outf; gmx_large_int_t step,step_rel; double run_time; double t,t0,lam0; gmx_bool bSimAnn, bFirstStep,bStateFromTPX,bLastStep,bStartingFromCpt; gmx_bool bInitStep=TRUE; gmx_bool do_ene,do_log, do_verbose, bX,bV,bF,bCPT; tensor force_vir,shake_vir,total_vir,pres; int i,m; int mdof_flags; rvec mu_tot; t_vcm *vcm; int nchkpt=1; gmx_localtop_t *top; t_mdebin *mdebin=NULL; t_state *state=NULL; rvec *f_global=NULL; int n_xtc=-1; rvec *x_xtc=NULL; gmx_enerdata_t *enerd; rvec *f=NULL; gmx_global_stat_t gstat; gmx_update_t upd=NULL; t_graph *graph=NULL; globsig_t gs; gmx_groups_t *groups; gmx_ekindata_t *ekind, *ekind_save; gmx_bool bAppend; int a0,a1; matrix lastbox; real reset_counters=0,reset_counters_now=0; char sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE]; int handled_stop_condition=gmx_stop_cond_none; const char *ommOptions = NULL; void *openmmData; bAppend = (Flags & MD_APPENDFILES); check_ir_old_tpx_versions(cr,fplog,ir,top_global); groups = &top_global->groups; /* Initial values */ init_md(fplog,cr,ir,oenv,&t,&t0,&state_global->lambda,&lam0, nrnb,top_global,&upd, nfile,fnm,&outf,&mdebin, force_vir,shake_vir,mu_tot,&bSimAnn,&vcm,state_global,Flags); clear_mat(total_vir); clear_mat(pres); /* Energy terms and groups */ snew(enerd,1); init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,enerd); snew(f,top_global->natoms); /* Kinetic energy data */ snew(ekind,1); init_ekindata(fplog,top_global,&(ir->opts),ekind); /* needed for iteration of constraints */ snew(ekind_save,1); init_ekindata(fplog,top_global,&(ir->opts),ekind_save); /* Copy the cos acceleration to the groups struct */ ekind->cosacc.cos_accel = ir->cos_accel; gstat = global_stat_init(ir); debug_gmx(); { double io = compute_io(ir,top_global->natoms,groups,mdebin->ebin->nener,1); if ((io > 2000) && MASTER(cr)) fprintf(stderr, "\nWARNING: This run will generate roughly %.0f Mb of data\n\n", io); } top = gmx_mtop_generate_local_top(top_global,ir); a0 = 0; a1 = top_global->natoms; state = partdec_init_local_state(cr,state_global); f_global = f; atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms); if (vsite) { set_vsite_top(vsite,top,mdatoms,cr); } if (ir->ePBC != epbcNONE && !ir->bPeriodicMols) { graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE); } update_mdatoms(mdatoms,state->lambda); if (deviceOptions[0]=='\0') { /* empty options, which should default to OpenMM in this build */ ommOptions=deviceOptions; } else { if (gmx_strncasecmp(deviceOptions,"OpenMM",6)!=0) { gmx_fatal(FARGS, "This Gromacs version currently only works with OpenMM. Use -device \"OpenMM:<options>\""); } else { ommOptions=strchr(deviceOptions,':'); if (NULL!=ommOptions) { /* Increase the pointer to skip the colon */ ommOptions++; } } } openmmData = openmm_init(fplog, ommOptions, ir, top_global, top, mdatoms, fr, state); please_cite(fplog,"Friedrichs2009"); if (MASTER(cr)) { /* Update mdebin with energy history if appending to output files */ if ( Flags & MD_APPENDFILES ) { restore_energyhistory_from_state(mdebin,&state_global->enerhist); } /* Set the initial energy history in state to zero by updating once */ update_energyhistory(&state_global->enerhist,mdebin); } if (constr) { set_constraints(constr,top,ir,mdatoms,cr); } if (!ir->bContinuation) { if (mdatoms->cFREEZE && (state->flags & (1<<estV))) { /* Set the velocities of frozen particles to zero */ for (i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) { for (m=0; m<DIM; m++) { if (ir->opts.nFreeze[mdatoms->cFREEZE[i]][m]) { state->v[i][m] = 0; } } } } if (constr) { /* Constrain the initial coordinates and velocities */ do_constrain_first(fplog,constr,ir,mdatoms,state,f, graph,cr,nrnb,fr,top,shake_vir); } if (vsite) { /* Construct the virtual sites for the initial configuration */ construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,NULL, top->idef.iparams,top->idef.il, fr->ePBC,fr->bMolPBC,graph,cr,state->box); } } debug_gmx(); if (MASTER(cr)) { char tbuf[20]; fprintf(fplog,"Initial temperature: %g K\n",enerd->term[F_TEMP]); fprintf(stderr,"starting mdrun '%s'\n", *(top_global->name)); if (ir->nsteps >= 0) { sprintf(tbuf,"%8.1f",(ir->init_step+ir->nsteps)*ir->delta_t); } else { sprintf(tbuf,"%s","infinite"); } if (ir->init_step > 0) { fprintf(stderr,"%s steps, %s ps (continuing from step %s, %8.1f ps).\n", gmx_step_str(ir->init_step+ir->nsteps,sbuf),tbuf, gmx_step_str(ir->init_step,sbuf2), ir->init_step*ir->delta_t); } else { fprintf(stderr,"%s steps, %s ps.\n", gmx_step_str(ir->nsteps,sbuf),tbuf); } } fprintf(fplog,"\n"); /* Set and write start time */ runtime_start(runtime); print_date_and_time(fplog,cr->nodeid,"Started mdrun",runtime); wallcycle_start(wcycle,ewcRUN); if (fplog) fprintf(fplog,"\n"); /* safest point to do file checkpointing is here. More general point would be immediately before integrator call */ debug_gmx(); /*********************************************************** * * Loop over MD steps * ************************************************************/ /* loop over MD steps or if rerunMD to end of input trajectory */ bFirstStep = TRUE; /* Skip the first Nose-Hoover integration when we get the state from tpx */ bStateFromTPX = !opt2bSet("-cpi",nfile,fnm); bInitStep = bFirstStep && bStateFromTPX; bStartingFromCpt = (Flags & MD_STARTFROMCPT) && bInitStep; bLastStep = FALSE; init_global_signals(&gs,cr,ir,repl_ex_nst); step = ir->init_step; step_rel = 0; while (!bLastStep) { wallcycle_start(wcycle,ewcSTEP); GMX_MPE_LOG(ev_timestep1); bLastStep = (step_rel == ir->nsteps); t = t0 + step*ir->delta_t; if (gs.set[eglsSTOPCOND] != 0) { bLastStep = TRUE; } do_log = do_per_step(step,ir->nstlog) || bFirstStep || bLastStep; do_verbose = bVerbose && (step % stepout == 0 || bFirstStep || bLastStep); if (MASTER(cr) && do_log) { print_ebin_header(fplog,step,t,state->lambda); } clear_mat(force_vir); GMX_MPE_LOG(ev_timestep2); /* We write a checkpoint at this MD step when: * either when we signalled through gs (in OpenMM NS works different), * or at the last step (but not when we do not want confout), * but never at the first step. */ bCPT = ((gs.set[eglsCHKPT] || (bLastStep && (Flags & MD_CONFOUT))) && step > ir->init_step ); if (bCPT) { gs.set[eglsCHKPT] = 0; } /* Now we have the energies and forces corresponding to the * coordinates at time t. We must output all of this before * the update. * for RerunMD t is read from input trajectory */ GMX_MPE_LOG(ev_output_start); mdof_flags = 0; if (do_per_step(step,ir->nstxout)) { mdof_flags |= MDOF_X; } if (do_per_step(step,ir->nstvout)) { mdof_flags |= MDOF_V; } if (do_per_step(step,ir->nstfout)) { mdof_flags |= MDOF_F; } if (do_per_step(step,ir->nstxtcout)) { mdof_flags |= MDOF_XTC; } if (bCPT) { mdof_flags |= MDOF_CPT; }; do_ene = (do_per_step(step,ir->nstenergy) || bLastStep); if (mdof_flags != 0 || do_ene || do_log) { wallcycle_start(wcycle,ewcTRAJ); bF = (mdof_flags & MDOF_F); bX = (mdof_flags & (MDOF_X | MDOF_XTC | MDOF_CPT)); bV = (mdof_flags & (MDOF_V | MDOF_CPT)); openmm_copy_state(openmmData, state, &t, f, enerd, bX, bV, bF, do_ene); upd_mdebin(mdebin, FALSE,TRUE, t,mdatoms->tmass,enerd,state,lastbox, shake_vir,force_vir,total_vir,pres, ekind,mu_tot,constr); print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,do_log?fplog:NULL, step,t, eprNORMAL,bCompact,mdebin,fcd,groups,&(ir->opts)); write_traj(fplog,cr,outf,mdof_flags,top_global, step,t,state,state_global,f,f_global,&n_xtc,&x_xtc); if (bCPT) { nchkpt++; bCPT = FALSE; } debug_gmx(); if (bLastStep && step_rel == ir->nsteps && (Flags & MD_CONFOUT) && MASTER(cr)) { /* x and v have been collected in write_traj, * because a checkpoint file will always be written * at the last step. */ fprintf(stderr,"\nWriting final coordinates.\n"); if (ir->ePBC != epbcNONE && !ir->bPeriodicMols) { /* Make molecules whole only for confout writing */ do_pbc_mtop(fplog,ir->ePBC,state->box,top_global,state_global->x); } write_sto_conf_mtop(ftp2fn(efSTO,nfile,fnm), *top_global->name,top_global, state_global->x,state_global->v, ir->ePBC,state->box); debug_gmx(); } wallcycle_stop(wcycle,ewcTRAJ); } GMX_MPE_LOG(ev_output_finish); /* Determine the wallclock run time up till now */ run_time = gmx_gettime() - (double)runtime->real; /* Check whether everything is still allright */ if (((int)gmx_get_stop_condition() > handled_stop_condition) #ifdef GMX_THREADS && MASTER(cr) #endif ) { /* this is just make gs.sig compatible with the hack of sending signals around by MPI_Reduce with together with other floats */ /* NOTE: this only works for serial code. For code that allows MPI nodes to propagate their condition, see kernel/md.c*/ if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns ) gs.set[eglsSTOPCOND]=1; if ( gmx_get_stop_condition() == gmx_stop_cond_next ) gs.set[eglsSTOPCOND]=1; /* < 0 means stop at next step, > 0 means stop at next NS step */ if (fplog) { fprintf(fplog, "\n\nReceived the %s signal, stopping at the next %sstep\n\n", gmx_get_signal_name(), gs.sig[eglsSTOPCOND]==1 ? "NS " : ""); fflush(fplog); } fprintf(stderr, "\n\nReceived the %s signal, stopping at the next %sstep\n\n", gmx_get_signal_name(), gs.sig[eglsSTOPCOND]==1 ? "NS " : ""); fflush(stderr); handled_stop_condition=(int)gmx_get_stop_condition(); } else if (MASTER(cr) && (max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) && gs.set[eglsSTOPCOND] == 0) { /* Signal to terminate the run */ gs.set[eglsSTOPCOND] = 1; if (fplog) { fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99); } fprintf(stderr, "\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99); } /* checkpoints */ if (MASTER(cr) && (cpt_period >= 0 && (cpt_period == 0 || run_time >= nchkpt*cpt_period*60.0)) && gs.set[eglsCHKPT] == 0) { gs.set[eglsCHKPT] = 1; } /* Time for performance */ if (((step % stepout) == 0) || bLastStep) { runtime_upd_proc(runtime); } if (do_per_step(step,ir->nstlog)) { if (fflush(fplog) != 0) { gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of quota?"); } } /* Remaining runtime */ if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() )) { print_time(stderr,runtime,step,ir,cr); } bFirstStep = FALSE; bInitStep = FALSE; bStartingFromCpt = FALSE; step++; step_rel++; openmm_take_one_step(openmmData); } /* End of main MD loop */ debug_gmx(); /* Stop the time */ runtime_end(runtime); if (MASTER(cr)) { if (ir->nstcalcenergy > 0) { print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t, eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts)); } } openmm_cleanup(fplog, openmmData); done_mdoutf(outf); debug_gmx(); runtime->nsteps_done = step_rel; return 0; }
int add_h(t_atoms **pdbaptr, rvec *xptr[], int nah, t_hackblock ah[], int nterpairs, t_hackblock **ntdb, t_hackblock **ctdb, int *rN, int *rC, bool bMissing, int **nabptr, t_hack ***abptr, bool bUpdate_pdba, bool bKeep_old_pdba) { t_atoms *newpdba=NULL,*pdba=NULL; bool bSet; int nadd; int i,newi,j,d,natoms; int *nab=NULL; t_hack **ab=NULL; t_hackblock *hb; rvec *xn; bool bKeep_ab; /* set flags for adding hydrogens (according to hdb) */ pdba=*pdbaptr; natoms=pdba->nr; if (nabptr && abptr) { /* the first time these will be pointers to NULL, but we will return in them the completed arrays, which we will get back the second time */ nab = *nabptr; ab = *abptr; bKeep_ab=TRUE; if (debug) fprintf(debug,"pointer to ab found\n"); } else bKeep_ab=FALSE; if (nab && ab) { /* WOW, everything was already figured out */ bUpdate_pdba = FALSE; if (debug) fprintf(debug,"pointer to non-null ab found\n"); } else { /* We'll have to do all the hard work */ bUpdate_pdba = TRUE; /* first get all the hackblocks for each residue: */ hb = get_hackblocks(pdba, nah, ah, nterpairs, ntdb, ctdb, rN, rC); if (debug) dump_hb(debug, pdba->nres, hb); /* expand the hackblocks to atom level */ snew(nab,natoms); snew(ab,natoms); expand_hackblocks(pdba, hb, nab, ab, nterpairs, rN, rC); free_t_hackblock(pdba->nres, &hb); } if (debug) { fprintf(debug,"before calc_all_pos\n"); dump_ab(debug, natoms, nab, ab, TRUE); } /* Now calc the positions */ calc_all_pos(pdba, *xptr, nab, ab, bMissing); if (debug) { fprintf(debug,"after calc_all_pos\n"); dump_ab(debug, natoms, nab, ab, TRUE); } if (bUpdate_pdba) { /* we don't have to add atoms that are already present in pdba, so we will remove them from the ab (t_hack) */ nadd = check_atoms_present(pdba, nab, ab, bMissing); if (debug) { fprintf(debug, "removed add hacks that were already in pdba:\n"); dump_ab(debug, natoms, nab, ab, TRUE); fprintf(debug, "will be adding %d atoms\n",nadd); } /* Copy old atoms, making space for new ones */ snew(newpdba,1); init_t_atoms(newpdba,natoms+nadd,FALSE); newpdba->nres = pdba->nres; sfree(newpdba->resname); newpdba->resname = pdba->resname; } else { nadd = 0; } if (debug) fprintf(debug,"snew xn for %d old + %d new atoms %d total)\n", natoms, nadd, natoms+nadd); snew(xn,natoms+nadd); newi=0; for(i=0; (i<natoms); i++) { /* check if this atom wasn't scheduled for deletion */ if ( nab[i]==0 || (ab[i][0].nname != NULL) ) { if (newi >= natoms+nadd) { /*gmx_fatal(FARGS,"Not enough space for adding atoms");*/ nadd+=10; srenew(xn,natoms+nadd); if (bUpdate_pdba) { srenew(newpdba->atom,natoms+nadd); srenew(newpdba->atomname,natoms+nadd); } debug_gmx(); } if (debug) fprintf(debug,"(%3d) %3d %4s %4s%3d %3d", i+1, newi+1, *pdba->atomname[i], *pdba->resname[pdba->atom[i].resnr], pdba->atom[i].resnr+1, nab[i]); if (bUpdate_pdba) copy_atom(pdba,i, newpdba,newi); copy_rvec((*xptr)[i],xn[newi]); /* process the hacks for this atom */ for(j=0; j<nab[i]; j++) { if ( ab[i][j].oname==NULL ) { /* add */ newi++; if (newi >= natoms+nadd) { /* gmx_fatal(FARGS,"Not enough space for adding atoms");*/ nadd+=10; srenew(xn,natoms+nadd); if (bUpdate_pdba) { srenew(newpdba->atom,natoms+nadd); srenew(newpdba->atomname,natoms+nadd); } debug_gmx(); } if (bUpdate_pdba) { newpdba->atom[newi].resnr=pdba->atom[i].resnr; } if (debug) fprintf(debug," + %d",newi+1); } if ( ab[i][j].nname!=NULL ) { /* add or replace */ if (bUpdate_pdba) { snew(newpdba->atomname[newi],1); *newpdba->atomname[newi]=strdup(ab[i][j].nname); if ( ab[i][j].oname!=NULL && ab[i][j].atom ) { /* replace */ /* newpdba->atom[newi].m = ab[i][j].atom->m; */ /* newpdba->atom[newi].q = ab[i][j].atom->q; */ /* newpdba->atom[newi].type = ab[i][j].atom->type; */ } } bSet=TRUE; for(d=0; d<DIM; d++) bSet = bSet && ab[i][j].newx[d]!=NOTSET; if (bSet) copy_rvec(ab[i][j].newx, xn[newi]); if (bUpdate_pdba && debug) fprintf(debug," %s %g %g",*newpdba->atomname[newi], newpdba->atom[newi].m,newpdba->atom[newi].q); } } newi++; if (debug) fprintf(debug,"\n"); } } if (bUpdate_pdba) newpdba->nr = newi; if ( bKeep_ab ) { *nabptr=nab; *abptr=ab; } else { /* Clean up */ for(i=0; i<natoms; i++) free_t_hack(nab[i], &ab[i]); sfree(nab); sfree(ab); } if ( bUpdate_pdba ) { if ( !bKeep_old_pdba ) { for(i=0; i < natoms; i++) { sfree(*(pdba->atomname[i])); /* sfree(pdba->atomname[i]); */ } sfree(pdba->atomname); sfree(pdba->atom); sfree(pdba->pdbinfo); sfree(pdba); } *pdbaptr=newpdba; } else nadd = newi-natoms; sfree(*xptr); *xptr=xn; return newi; }
void do_force_lowlevel(FILE *fplog, gmx_large_int_t step, t_forcerec *fr, t_inputrec *ir, t_idef *idef, t_commrec *cr, t_nrnb *nrnb, gmx_wallcycle_t wcycle, t_mdatoms *md, t_grpopts *opts, rvec x[], history_t *hist, rvec f[], rvec f_longrange[], gmx_enerdata_t *enerd, t_fcdata *fcd, gmx_mtop_t *mtop, gmx_localtop_t *top, gmx_genborn_t *born, t_atomtypes *atype, gmx_bool bBornRadii, matrix box, t_lambda *fepvals, real *lambda, t_graph *graph, t_blocka *excl, rvec mu_tot[], int flags, float *cycles_pme) { int i, j, status; int donb_flags; gmx_bool bDoEpot, bSepDVDL, bSB; int pme_flags; matrix boxs; rvec box_size; real Vsr, Vlr, Vcorr = 0; t_pbc pbc; real dvdgb; char buf[22]; double clam_i, vlam_i; real dvdl_dum[efptNR], dvdl, dvdl_nb[efptNR], lam_i[efptNR]; real dvdlsum; #ifdef GMX_MPI double t0 = 0.0, t1, t2, t3; /* time measurement for coarse load balancing */ #endif #define PRINT_SEPDVDL(s, v, dvdlambda) if (bSepDVDL) {fprintf(fplog, sepdvdlformat, s, v, dvdlambda); } GMX_MPE_LOG(ev_force_start); set_pbc(&pbc, fr->ePBC, box); /* reset free energy components */ for (i = 0; i < efptNR; i++) { dvdl_nb[i] = 0; dvdl_dum[i] = 0; } /* Reset box */ for (i = 0; (i < DIM); i++) { box_size[i] = box[i][i]; } bSepDVDL = (fr->bSepDVDL && do_per_step(step, ir->nstlog)); debug_gmx(); /* do QMMM first if requested */ if (fr->bQMMM) { enerd->term[F_EQM] = calculate_QMMM(cr, x, f, fr, md); } if (bSepDVDL) { fprintf(fplog, "Step %s: non-bonded V and dVdl for node %d:\n", gmx_step_str(step, buf), cr->nodeid); } /* Call the short range functions all in one go. */ GMX_MPE_LOG(ev_do_fnbf_start); #ifdef GMX_MPI /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/ #define TAKETIME FALSE if (TAKETIME) { MPI_Barrier(cr->mpi_comm_mygroup); t0 = MPI_Wtime(); } #endif if (ir->nwall) { /* foreign lambda component for walls */ dvdl = do_walls(ir, fr, box, md, x, f, lambda[efptVDW], enerd->grpp.ener[egLJSR], nrnb); PRINT_SEPDVDL("Walls", 0.0, dvdl); enerd->dvdl_lin[efptVDW] += dvdl; } /* If doing GB, reset dvda and calculate the Born radii */ if (ir->implicit_solvent) { wallcycle_sub_start(wcycle, ewcsNONBONDED); for (i = 0; i < born->nr; i++) { fr->dvda[i] = 0; } if (bBornRadii) { calc_gb_rad(cr, fr, ir, top, atype, x, &(fr->gblist), born, md, nrnb); } wallcycle_sub_stop(wcycle, ewcsNONBONDED); } where(); /* We only do non-bonded calculation with group scheme here, the verlet * calls are done from do_force_cutsVERLET(). */ if (fr->cutoff_scheme == ecutsGROUP && (flags & GMX_FORCE_NONBONDED)) { donb_flags = 0; /* Add short-range interactions */ donb_flags |= GMX_NONBONDED_DO_SR; if (flags & GMX_FORCE_FORCES) { donb_flags |= GMX_NONBONDED_DO_FORCE; } if (flags & GMX_FORCE_ENERGY) { donb_flags |= GMX_NONBONDED_DO_POTENTIAL; } if (flags & GMX_FORCE_DO_LR) { donb_flags |= GMX_NONBONDED_DO_LR; } wallcycle_sub_start(wcycle, ewcsNONBONDED); do_nonbonded(cr, fr, x, f, f_longrange, md, excl, &enerd->grpp, box_size, nrnb, lambda, dvdl_nb, -1, -1, donb_flags); /* If we do foreign lambda and we have soft-core interactions * we have to recalculate the (non-linear) energies contributions. */ if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) && fepvals->sc_alpha != 0) { for (i = 0; i < enerd->n_lambda; i++) { for (j = 0; j < efptNR; j++) { lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]); } reset_foreign_enerdata(enerd); do_nonbonded(cr, fr, x, f, f_longrange, md, excl, &(enerd->foreign_grpp), box_size, nrnb, lam_i, dvdl_dum, -1, -1, (donb_flags & ~GMX_NONBONDED_DO_FORCE) | GMX_NONBONDED_DO_FOREIGNLAMBDA); sum_epot(&ir->opts, &(enerd->foreign_grpp), enerd->foreign_term); enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT]; } } wallcycle_sub_stop(wcycle, ewcsNONBONDED); where(); } /* If we are doing GB, calculate bonded forces and apply corrections * to the solvation forces */ /* MRS: Eventually, many need to include free energy contribution here! */ if (ir->implicit_solvent) { wallcycle_sub_start(wcycle, ewcsBONDED); calc_gb_forces(cr, md, born, top, atype, x, f, fr, idef, ir->gb_algorithm, ir->sa_algorithm, nrnb, bBornRadii, &pbc, graph, enerd); wallcycle_sub_stop(wcycle, ewcsBONDED); } #ifdef GMX_MPI if (TAKETIME) { t1 = MPI_Wtime(); fr->t_fnbf += t1-t0; } #endif if (fepvals->sc_alpha != 0) { enerd->dvdl_nonlin[efptVDW] += dvdl_nb[efptVDW]; } else { enerd->dvdl_lin[efptVDW] += dvdl_nb[efptVDW]; } if (fepvals->sc_alpha != 0) /* even though coulomb part is linear, we already added it, beacuse we need to go through the vdw calculation anyway */ { enerd->dvdl_nonlin[efptCOUL] += dvdl_nb[efptCOUL]; } else { enerd->dvdl_lin[efptCOUL] += dvdl_nb[efptCOUL]; } Vsr = 0; if (bSepDVDL) { for (i = 0; i < enerd->grpp.nener; i++) { Vsr += (fr->bBHAM ? enerd->grpp.ener[egBHAMSR][i] : enerd->grpp.ener[egLJSR][i]) + enerd->grpp.ener[egCOULSR][i] + enerd->grpp.ener[egGB][i]; } dvdlsum = dvdl_nb[efptVDW] + dvdl_nb[efptCOUL]; PRINT_SEPDVDL("VdW and Coulomb SR particle-p.", Vsr, dvdlsum); } debug_gmx(); GMX_MPE_LOG(ev_do_fnbf_finish); if (debug) { pr_rvecs(debug, 0, "fshift after SR", fr->fshift, SHIFTS); } /* Shift the coordinates. Must be done before bonded forces and PPPM, * but is also necessary for SHAKE and update, therefore it can NOT * go when no bonded forces have to be evaluated. */ /* Here sometimes we would not need to shift with NBFonly, * but we do so anyhow for consistency of the returned coordinates. */ if (graph) { shift_self(graph, box, x); if (TRICLINIC(box)) { inc_nrnb(nrnb, eNR_SHIFTX, 2*graph->nnodes); } else { inc_nrnb(nrnb, eNR_SHIFTX, graph->nnodes); } } /* Check whether we need to do bondeds or correct for exclusions */ if (fr->bMolPBC && ((flags & GMX_FORCE_BONDED) || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype))) { /* Since all atoms are in the rectangular or triclinic unit-cell, * only single box vector shifts (2 in x) are required. */ set_pbc_dd(&pbc, fr->ePBC, cr->dd, TRUE, box); } debug_gmx(); if (flags & GMX_FORCE_BONDED) { GMX_MPE_LOG(ev_calc_bonds_start); wallcycle_sub_start(wcycle, ewcsBONDED); calc_bonds(fplog, cr->ms, idef, x, hist, f, fr, &pbc, graph, enerd, nrnb, lambda, md, fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, atype, born, flags, fr->bSepDVDL && do_per_step(step, ir->nstlog), step); /* Check if we have to determine energy differences * at foreign lambda's. */ if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) && idef->ilsort != ilsortNO_FE) { if (idef->ilsort != ilsortFE_SORTED) { gmx_incons("The bonded interactions are not sorted for free energy"); } for (i = 0; i < enerd->n_lambda; i++) { reset_foreign_enerdata(enerd); for (j = 0; j < efptNR; j++) { lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]); } calc_bonds_lambda(fplog, idef, x, fr, &pbc, graph, &(enerd->foreign_grpp), enerd->foreign_term, nrnb, lam_i, md, fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL); sum_epot(&ir->opts, &(enerd->foreign_grpp), enerd->foreign_term); enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT]; } } debug_gmx(); GMX_MPE_LOG(ev_calc_bonds_finish); wallcycle_sub_stop(wcycle, ewcsBONDED); } where(); *cycles_pme = 0; if (EEL_FULL(fr->eeltype)) { bSB = (ir->nwall == 2); if (bSB) { copy_mat(box, boxs); svmul(ir->wall_ewald_zfac, boxs[ZZ], boxs[ZZ]); box_size[ZZ] *= ir->wall_ewald_zfac; } clear_mat(fr->vir_el_recip); if (fr->bEwald) { Vcorr = 0; dvdl = 0; /* With the Verlet scheme exclusion forces are calculated * in the non-bonded kernel. */ /* The TPI molecule does not have exclusions with the rest * of the system and no intra-molecular PME grid contributions * will be calculated in gmx_pme_calc_energy. */ if ((ir->cutoff_scheme == ecutsGROUP && fr->n_tpi == 0) || ir->ewald_geometry != eewg3D || ir->epsilon_surface != 0) { int nthreads, t; wallcycle_sub_start(wcycle, ewcsEWALD_CORRECTION); if (fr->n_tpi > 0) { gmx_fatal(FARGS, "TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions"); } nthreads = gmx_omp_nthreads_get(emntBonded); #pragma omp parallel for num_threads(nthreads) schedule(static) for (t = 0; t < nthreads; t++) { int s, e, i; rvec *fnv; tensor *vir; real *Vcorrt, *dvdlt; if (t == 0) { fnv = fr->f_novirsum; vir = &fr->vir_el_recip; Vcorrt = &Vcorr; dvdlt = &dvdl; } else { fnv = fr->f_t[t].f; vir = &fr->f_t[t].vir; Vcorrt = &fr->f_t[t].Vcorr; dvdlt = &fr->f_t[t].dvdl[efptCOUL]; for (i = 0; i < fr->natoms_force; i++) { clear_rvec(fnv[i]); } clear_mat(*vir); } *dvdlt = 0; *Vcorrt = ewald_LRcorrection(fplog, fr->excl_load[t], fr->excl_load[t+1], cr, t, fr, md->chargeA, md->nChargePerturbed ? md->chargeB : NULL, ir->cutoff_scheme != ecutsVERLET, excl, x, bSB ? boxs : box, mu_tot, ir->ewald_geometry, ir->epsilon_surface, fnv, *vir, lambda[efptCOUL], dvdlt); } if (nthreads > 1) { reduce_thread_forces(fr->natoms_force, fr->f_novirsum, fr->vir_el_recip, &Vcorr, efptCOUL, &dvdl, nthreads, fr->f_t); } wallcycle_sub_stop(wcycle, ewcsEWALD_CORRECTION); } if (fr->n_tpi == 0) { Vcorr += ewald_charge_correction(cr, fr, lambda[efptCOUL], box, &dvdl, fr->vir_el_recip); } PRINT_SEPDVDL("Ewald excl./charge/dip. corr.", Vcorr, dvdl); enerd->dvdl_lin[efptCOUL] += dvdl; } status = 0; Vlr = 0; dvdl = 0; switch (fr->eeltype) { case eelPME: case eelPMESWITCH: case eelPMEUSER: case eelPMEUSERSWITCH: case eelP3M_AD: if (cr->duty & DUTY_PME) { assert(fr->n_tpi >= 0); if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED)) { pme_flags = GMX_PME_SPREAD_Q | GMX_PME_SOLVE; if (flags & GMX_FORCE_FORCES) { pme_flags |= GMX_PME_CALC_F; } if (flags & (GMX_FORCE_VIRIAL | GMX_FORCE_ENERGY)) { pme_flags |= GMX_PME_CALC_ENER_VIR; } if (fr->n_tpi > 0) { /* We don't calculate f, but we do want the potential */ pme_flags |= GMX_PME_CALC_POT; } wallcycle_start(wcycle, ewcPMEMESH); status = gmx_pme_do(fr->pmedata, md->start, md->homenr - fr->n_tpi, x, fr->f_novirsum, md->chargeA, md->chargeB, bSB ? boxs : box, cr, DOMAINDECOMP(cr) ? dd_pme_maxshift_x(cr->dd) : 0, DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0, nrnb, wcycle, fr->vir_el_recip, fr->ewaldcoeff, &Vlr, lambda[efptCOUL], &dvdl, pme_flags); *cycles_pme = wallcycle_stop(wcycle, ewcPMEMESH); /* We should try to do as little computation after * this as possible, because parallel PME synchronizes * the nodes, so we want all load imbalance of the rest * of the force calculation to be before the PME call. * DD load balancing is done on the whole time of * the force call (without PME). */ } if (fr->n_tpi > 0) { /* Determine the PME grid energy of the test molecule * with the PME grid potential of the other charges. */ gmx_pme_calc_energy(fr->pmedata, fr->n_tpi, x + md->homenr - fr->n_tpi, md->chargeA + md->homenr - fr->n_tpi, &Vlr); } PRINT_SEPDVDL("PME mesh", Vlr, dvdl); } break; case eelEWALD: Vlr = do_ewald(fplog, FALSE, ir, x, fr->f_novirsum, md->chargeA, md->chargeB, box_size, cr, md->homenr, fr->vir_el_recip, fr->ewaldcoeff, lambda[efptCOUL], &dvdl, fr->ewald_table); PRINT_SEPDVDL("Ewald long-range", Vlr, dvdl); break; default: gmx_fatal(FARGS, "No such electrostatics method implemented %s", eel_names[fr->eeltype]); } if (status != 0) { gmx_fatal(FARGS, "Error %d in long range electrostatics routine %s", status, EELTYPE(fr->eeltype)); } /* Note that with separate PME nodes we get the real energies later */ enerd->dvdl_lin[efptCOUL] += dvdl; enerd->term[F_COUL_RECIP] = Vlr + Vcorr; if (debug) { fprintf(debug, "Vlr = %g, Vcorr = %g, Vlr_corr = %g\n", Vlr, Vcorr, enerd->term[F_COUL_RECIP]); pr_rvecs(debug, 0, "vir_el_recip after corr", fr->vir_el_recip, DIM); pr_rvecs(debug, 0, "fshift after LR Corrections", fr->fshift, SHIFTS); } } else { if (EEL_RF(fr->eeltype)) { /* With the Verlet scheme exclusion forces are calculated * in the non-bonded kernel. */ if (ir->cutoff_scheme != ecutsVERLET && fr->eeltype != eelRF_NEC) { dvdl = 0; enerd->term[F_RF_EXCL] = RF_excl_correction(fplog, fr, graph, md, excl, x, f, fr->fshift, &pbc, lambda[efptCOUL], &dvdl); } enerd->dvdl_lin[efptCOUL] += dvdl; PRINT_SEPDVDL("RF exclusion correction", enerd->term[F_RF_EXCL], dvdl); } } where(); debug_gmx(); if (debug) { print_nrnb(debug, nrnb); } debug_gmx(); #ifdef GMX_MPI if (TAKETIME) { t2 = MPI_Wtime(); MPI_Barrier(cr->mpi_comm_mygroup); t3 = MPI_Wtime(); fr->t_wait += t3-t2; if (fr->timesteps == 11) { fprintf(stderr, "* PP load balancing info: node %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n", cr->nodeid, gmx_step_str(fr->timesteps, buf), 100*fr->t_wait/(fr->t_wait+fr->t_fnbf), (fr->t_fnbf+fr->t_wait)/fr->t_fnbf); } fr->timesteps++; } #endif if (debug) { pr_rvecs(debug, 0, "fshift after bondeds", fr->fshift, SHIFTS); } GMX_MPE_LOG(ev_force_finish); }
void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr, t_inputrec *ir, t_forcerec *fr, gmx_ekindata_t *ekind, t_state *state, t_state *state_global, t_mdatoms *mdatoms, t_nrnb *nrnb, t_vcm *vcm, gmx_wallcycle_t wcycle, gmx_enerdata_t *enerd, tensor force_vir, tensor shake_vir, tensor total_vir, tensor pres, rvec mu_tot, gmx_constr_t constr, globsig_t *gs, gmx_bool bInterSimGS, matrix box, gmx_mtop_t *top_global, gmx_bool *bSumEkinhOld, int flags) { int i, gsi; real gs_buf[eglsNR]; tensor corr_vir, corr_pres; gmx_bool bEner, bPres, bTemp; gmx_bool bStopCM, bGStat, bReadEkin, bEkinAveVel, bScaleEkin, bConstrain; real prescorr, enercorr, dvdlcorr, dvdl_ekin; /* translate CGLO flags to gmx_booleans */ bStopCM = flags & CGLO_STOPCM; bGStat = flags & CGLO_GSTAT; bReadEkin = (flags & CGLO_READEKIN); bScaleEkin = (flags & CGLO_SCALEEKIN); bEner = flags & CGLO_ENERGY; bTemp = flags & CGLO_TEMPERATURE; bPres = (flags & CGLO_PRESSURE); bConstrain = (flags & CGLO_CONSTRAINT); /* we calculate a full state kinetic energy either with full-step velocity verlet or half step where we need the pressure */ bEkinAveVel = (ir->eI == eiVV || (ir->eI == eiVVAK && bPres) || bReadEkin); /* in initalization, it sums the shake virial in vv, and to sums ekinh_old in leapfrog (or if we are calculating ekinh_old) for other reasons */ /* ########## Kinetic energy ############## */ if (bTemp) { /* Non-equilibrium MD: this is parallellized, but only does communication * when there really is NEMD. */ if (PAR(cr) && (ekind->bNEMD)) { accumulate_u(cr, &(ir->opts), ekind); } debug_gmx(); if (bReadEkin) { restore_ekinstate_from_state(cr, ekind, &state_global->ekinstate); } else { calc_ke_part(state, &(ir->opts), mdatoms, ekind, nrnb, bEkinAveVel); } debug_gmx(); } /* Calculate center of mass velocity if necessary, also parallellized */ if (bStopCM) { calc_vcm_grp(0, mdatoms->homenr, mdatoms, state->x, state->v, vcm); } if (bTemp || bStopCM || bPres || bEner || bConstrain) { if (!bGStat) { /* We will not sum ekinh_old, * so signal that we still have to do it. */ *bSumEkinhOld = TRUE; } else { if (gs != NULL) { for (i = 0; i < eglsNR; i++) { gs_buf[i] = gs->sig[i]; } } if (PAR(cr)) { wallcycle_start(wcycle, ewcMoveE); global_stat(fplog, gstat, cr, enerd, force_vir, shake_vir, mu_tot, ir, ekind, constr, bStopCM ? vcm : NULL, gs != NULL ? eglsNR : 0, gs_buf, top_global, state, *bSumEkinhOld, flags); wallcycle_stop(wcycle, ewcMoveE); } if (gs != NULL) { if (MULTISIM(cr) && bInterSimGS) { if (MASTER(cr)) { /* Communicate the signals between the simulations */ gmx_sum_sim(eglsNR, gs_buf, cr->ms); } /* Communicate the signals form the master to the others */ gmx_bcast(eglsNR*sizeof(gs_buf[0]), gs_buf, cr); } for (i = 0; i < eglsNR; i++) { if (bInterSimGS || gs_simlocal[i]) { /* Set the communicated signal only when it is non-zero, * since signals might not be processed at each MD step. */ gsi = (gs_buf[i] >= 0 ? (int)(gs_buf[i] + 0.5) : (int)(gs_buf[i] - 0.5)); if (gsi != 0) { gs->set[i] = gsi; } /* Turn off the local signal */ gs->sig[i] = 0; } } } *bSumEkinhOld = FALSE; } } if (!ekind->bNEMD && debug && bTemp && (vcm->nr > 0)) { correct_ekin(debug, 0, mdatoms->homenr, state->v, vcm->group_p[0], mdatoms->massT, mdatoms->tmass, ekind->ekin); } /* Do center of mass motion removal */ if (bStopCM) { check_cm_grp(fplog, vcm, ir, 1); do_stopcm_grp(0, mdatoms->homenr, mdatoms->cVCM, state->x, state->v, vcm); inc_nrnb(nrnb, eNR_STOPCM, mdatoms->homenr); } if (bEner) { /* Calculate the amplitude of the cosine velocity profile */ ekind->cosacc.vcos = ekind->cosacc.mvcos/mdatoms->tmass; } if (bTemp) { /* Sum the kinetic energies of the groups & calc temp */ /* compute full step kinetic energies if vv, or if vv-avek and we are computing the pressure with IR_NPT_TROTTER */ /* three maincase: VV with AveVel (md-vv), vv with AveEkin (md-vv-avek), leap with AveEkin (md). Leap with AveVel is not supported; it's not clear that it will actually work. bEkinAveVel: If TRUE, we simply multiply ekin by ekinscale to get a full step kinetic energy. If FALSE, we average ekinh_old and ekinh*ekinscale_nhc to get an averaged half step kinetic energy. */ enerd->term[F_TEMP] = sum_ekin(&(ir->opts), ekind, &dvdl_ekin, bEkinAveVel, bScaleEkin); enerd->dvdl_lin[efptMASS] = (double) dvdl_ekin; enerd->term[F_EKIN] = trace(ekind->ekin); } /* ########## Long range energy information ###### */ if (bEner || bPres || bConstrain) { calc_dispcorr(ir, fr, top_global->natoms, box, state->lambda[efptVDW], corr_pres, corr_vir, &prescorr, &enercorr, &dvdlcorr); } if (bEner) { enerd->term[F_DISPCORR] = enercorr; enerd->term[F_EPOT] += enercorr; enerd->term[F_DVDL_VDW] += dvdlcorr; } /* ########## Now pressure ############## */ if (bPres || bConstrain) { m_add(force_vir, shake_vir, total_vir); /* Calculate pressure and apply LR correction if PPPM is used. * Use the box from last timestep since we already called update(). */ enerd->term[F_PRES] = calc_pres(fr->ePBC, ir->nwall, box, ekind->ekin, total_vir, pres); /* Calculate long range corrections to pressure and energy */ /* this adds to enerd->term[F_PRES] and enerd->term[F_ETOT], and computes enerd->term[F_DISPCORR]. Also modifies the total_vir and pres tesors */ m_add(total_vir, corr_vir, total_vir); m_add(pres, corr_pres, pres); enerd->term[F_PDISPCORR] = prescorr; enerd->term[F_PRES] += prescorr; } }
void do_md_trajectory_writing(FILE *fplog, t_commrec *cr, int nfile, const t_filenm fnm[], gmx_int64_t step, gmx_int64_t step_rel, double t, t_inputrec *ir, t_state *state, t_state *state_global, gmx_mtop_t *top_global, t_forcerec *fr, gmx_mdoutf_t outf, t_mdebin *mdebin, gmx_ekindata_t *ekind, rvec *f, rvec *f_global, int *nchkpt, gmx_bool bCPT, gmx_bool bRerunMD, gmx_bool bLastStep, gmx_bool bDoConfOut, gmx_bool bSumEkinhOld ) { int mdof_flags; rvec *x_for_confout = NULL; mdof_flags = 0; if (do_per_step(step, ir->nstxout)) { mdof_flags |= MDOF_X; } if (do_per_step(step, ir->nstvout)) { mdof_flags |= MDOF_V; } if (do_per_step(step, ir->nstfout)) { mdof_flags |= MDOF_F; } if (do_per_step(step, ir->nstxout_compressed)) { mdof_flags |= MDOF_X_COMPRESSED; } if (bCPT) { mdof_flags |= MDOF_CPT; } ; #if defined(GMX_FAHCORE) if (bLastStep) { /* Enforce writing positions and velocities at end of run */ mdof_flags |= (MDOF_X | MDOF_V); } if (MASTER(cr)) { fcReportProgress( ir->nsteps, step ); } #if defined(__native_client__) fcCheckin(MASTER(cr)); #endif /* sync bCPT and fc record-keeping */ if (bCPT && MASTER(cr)) { fcRequestCheckPoint(); } #endif if (mdof_flags != 0) { wallcycle_start(mdoutf_get_wcycle(outf), ewcTRAJ); if (bCPT) { if (MASTER(cr)) { if (bSumEkinhOld) { state_global->ekinstate.bUpToDate = FALSE; } else { update_ekinstate(&state_global->ekinstate, ekind); state_global->ekinstate.bUpToDate = TRUE; } update_energyhistory(state_global->enerhist, mdebin); } } mdoutf_write_to_trajectory_files(fplog, cr, outf, mdof_flags, top_global, step, t, state, state_global, f, f_global); if (bCPT) { (*nchkpt)++; } debug_gmx(); if (bLastStep && step_rel == ir->nsteps && bDoConfOut && MASTER(cr) && !bRerunMD) { if (fr->bMolPBC && state->x == state_global->x) { /* This (single-rank) run needs to allocate a temporary array of size natoms so that any periodicity removal for mdrun -confout does not perturb the update and thus the final .edr output. This makes .cpt restarts look binary identical, and makes .edr restarts binary identical. */ snew(x_for_confout, state_global->natoms); copy_rvecn(state_global->x, x_for_confout, 0, state_global->natoms); } else { /* With DD, or no bMolPBC, it doesn't matter if we change state_global->x */ x_for_confout = state_global->x; } /* x and v have been collected in mdoutf_write_to_trajectory_files, * because a checkpoint file will always be written * at the last step. */ fprintf(stderr, "\nWriting final coordinates.\n"); if (fr->bMolPBC) { /* Make molecules whole only for confout writing */ do_pbc_mtop(fplog, ir->ePBC, state->box, top_global, x_for_confout); } write_sto_conf_mtop(ftp2fn(efSTO, nfile, fnm), *top_global->name, top_global, x_for_confout, state_global->v, ir->ePBC, state->box); if (fr->bMolPBC && state->x == state_global->x) { sfree(x_for_confout); } debug_gmx(); } wallcycle_stop(mdoutf_get_wcycle(outf), ewcTRAJ); } }
void force(FILE *fp, int step, t_forcerec *fr, t_inputrec *ir, t_idef *idef, t_nsborder *nsb, t_commrec *cr, t_commrec *mcr, t_nrnb *nrnb, t_groups *grps, t_mdatoms *md, int ngener, t_grpopts *opts, rvec x[], rvec f[], real epot[], t_fcdata *fcd, bool bVerbose, matrix box, real lambda, t_graph *graph, t_block *excl, bool bNBFonly, matrix lr_vir, rvec mu_tot, real qsum, bool bGatherOnly) { int i,nit; bool bDoEpot; rvec box_size; real Vlr,Vcorr=0; /* Reset box */ for(i=0; (i<DIM); i++) box_size[i]=box[i][i]; bDoEpot=((fr->nmol > 0) && (fr->nstcalc > 0) && (mod(step,fr->nstcalc)==0)); /* Reset epot... */ if (bDoEpot) for(i=0; (i<fr->nmol); i++) fr->mol_epot[i]=0.0; debug_gmx(); /* Call the short range functions all in one go. */ do_fnbf(fp,cr,fr,x,f,md, fr->bBHAM ? grps->estat.ee[egBHAM] : grps->estat.ee[egLJ], grps->estat.ee[egCOUL],box_size,nrnb, lambda,&epot[F_DVDL],FALSE,-1); debug_gmx(); if (debug) pr_rvecs(debug,0,"fshift after SR",fr->fshift,SHIFTS); /* Shift the coordinates. Must be done before bonded forces and PPPM, * but is also necessary for SHAKE and update, therefore it can NOT * go when no bonded forces have to be evaluated. */ if (debug && 0) p_graph(debug,"DeBUGGGG",graph); /* Check whether we need to do bondeds */ if (!bNBFonly) { shift_self(graph,box,x); if (debug && 0) { fprintf(debug,"BBBBBBBBBBBBBBBB\n"); fprintf(debug,"%5d\n",graph->nnodes); for(i=graph->start; (i<=graph->end); i++) fprintf(debug,"%5d%5s%5s%5d%8.3f%8.3f%8.3f\n", i,"A","B",i,x[i][XX],x[i][YY],x[i][ZZ]); fprintf(debug,"%10.5f%10.5f%10.5f\n", box[XX][XX],box[YY][YY],box[ZZ][ZZ]); } if (TRICLINIC(box)) inc_nrnb(nrnb,eNR_SHIFTX,2*graph->nnodes); else inc_nrnb(nrnb,eNR_SHIFTX,graph->nnodes); debug_gmx(); } if (EEL_LR(fr->eeltype)) { switch (fr->eeltype) { case eelPPPM: Vlr = do_pppm(fp,FALSE,x,fr->f_pme,md->chargeT, box_size,fr->phi,cr,nsb,nrnb); break; case eelPOISSON: Vlr = do_poisson(fp,FALSE,ir,md->nr,x,fr->f_pme,md->chargeT, box_size,fr->phi,cr,nrnb,&nit,TRUE); break; case eelPME: Vlr = do_pme(fp,FALSE,ir,x,fr->f_pme,md->chargeT, box,cr,nsb,nrnb,lr_vir,fr->ewaldcoeff,bGatherOnly); break; case eelEWALD: Vlr = do_ewald(fp,FALSE,ir,x,fr->f_pme,md->chargeT, box_size,cr,nsb,lr_vir,fr->ewaldcoeff); break; default: Vlr = 0; fatal_error(0,"No such electrostatics method implemented %s", eel_names[fr->eeltype]); } if(fr->bEwald) Vcorr = ewald_LRcorrection(fp,nsb,cr,fr,md->chargeT,excl,x,box,mu_tot,qsum, ir->ewald_geometry,ir->epsilon_surface,lr_vir); else Vcorr = shift_LRcorrection(fp,nsb,cr,fr,md->chargeT,excl,x,TRUE,box,lr_vir); epot[F_LR] = Vlr + Vcorr; if (debug) fprintf(debug,"Vlr = %g, Vcorr = %g, Vlr_corr = %g\n", Vlr,Vcorr,epot[F_LR]); if (debug) { pr_rvecs(debug,0,"lr_vir after corr",lr_vir,DIM); pr_rvecs(debug,0,"fshift after LR Corrections",fr->fshift,SHIFTS); } } debug_gmx(); if (debug) print_nrnb(debug,nrnb); debug_gmx(); if (!bNBFonly) { calc_bonds(fp,cr,mcr, idef,x,f,fr,graph,epot,nrnb,box,lambda,md, opts->ngener,grps->estat.ee[egLJ14],grps->estat.ee[egCOUL14], fcd,step,fr->bSepDVDL && do_per_step(step,ir->nstlog)); debug_gmx(); } if (debug) pr_rvecs(debug,0,"fshift after bondeds",fr->fshift,SHIFTS); for(i=0; (i<F_EPOT); i++) if (i != F_DISRES) epot[F_EPOT]+=epot[i]; }
void gmx_log_open(const char *lognm, const t_commrec *cr, gmx_bool bMasterOnly, gmx_bool bAppendFiles, FILE** fplog) { int len, pid; char buf[256], host[256]; time_t t; char timebuf[STRLEN]; FILE *fp = *fplog; char *tmpnm; debug_gmx(); /* Communicate the filename for logfile */ if (cr->nnodes > 1 && !bMasterOnly #ifdef GMX_THREAD_MPI /* With thread MPI the non-master log files are opened later * when the files names are already known on all nodes. */ && FALSE #endif ) { if (MASTER(cr)) { len = strlen(lognm) + 1; } gmx_bcast(sizeof(len), &len, cr); if (!MASTER(cr)) { snew(tmpnm, len+8); } else { tmpnm = gmx_strdup(lognm); } gmx_bcast(len*sizeof(*tmpnm), tmpnm, cr); } else { tmpnm = gmx_strdup(lognm); } debug_gmx(); if (!bMasterOnly && !MASTER(cr)) { /* Since log always ends with '.log' let's use this info */ par_fn(tmpnm, efLOG, cr, FALSE, !bMasterOnly, buf, 255); fp = gmx_fio_fopen(buf, bAppendFiles ? "a+" : "w+" ); } else if (!bAppendFiles) { fp = gmx_fio_fopen(tmpnm, bAppendFiles ? "a+" : "w+" ); } sfree(tmpnm); gmx_fatal_set_log_file(fp); /* Get some machine parameters */ gmx_gethostname(host, 256); time(&t); #ifndef NO_GETPID # ifdef GMX_NATIVE_WINDOWS pid = _getpid(); # else pid = getpid(); # endif #else pid = 0; #endif if (bAppendFiles) { fprintf(fp, "\n" "\n" "-----------------------------------------------------------\n" "Restarting from checkpoint, appending to previous log file.\n" "\n" ); } gmx_ctime_r(&t, timebuf, STRLEN); fprintf(fp, "Log file opened on %s" "Host: %s pid: %d rank ID: %d number of ranks: %d\n", timebuf, host, pid, cr->nodeid, cr->nnodes); try { gmx::BinaryInformationSettings settings; settings.extendedInfo(true); settings.copyright(!bAppendFiles); gmx::printBinaryInformation(fp, gmx::getProgramContext(), settings); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; fprintf(fp, "\n\n"); fflush(fp); debug_gmx(); *fplog = fp; }
void fill_grid(gmx_domdec_zones_t *dd_zones, t_grid *grid, int ncg_tot, int cg0, int cg1, rvec cg_cm[]) { int *cell_index; int nrx, nry, nrz; rvec n_box, offset; int zone, ccg0, ccg1, cg, d, not_used; ivec shift0, useall, b0, b1, ind; gmx_bool bUse; if (cg0 == -1) { /* We have already filled the grid up to grid->ncg, * continue from there. */ cg0 = grid->nr; } set_grid_ncg(grid, ncg_tot); cell_index = grid->cell_index; /* Initiate cell borders */ nrx = grid->n[XX]; nry = grid->n[YY]; nrz = grid->n[ZZ]; for (d = 0; d < DIM; d++) { if (grid->cell_size[d] > 0) { n_box[d] = 1/grid->cell_size[d]; } else { n_box[d] = 0; } } copy_rvec(grid->cell_offset, offset); if (debug) { fprintf(debug, "Filling grid from %d to %d\n", cg0, cg1); } debug_gmx(); if (dd_zones == NULL) { for (cg = cg0; cg < cg1; cg++) { for (d = 0; d < DIM; d++) { ind[d] = (cg_cm[cg][d] - offset[d])*n_box[d]; /* With pbc we should be done here. * Without pbc cg's outside the grid * should be assigned to the closest grid cell. */ if (ind[d] < 0) { ind[d] = 0; } else if (ind[d] >= grid->n[d]) { ind[d] = grid->n[d] - 1; } } cell_index[cg] = xyz2ci(nry, nrz, ind[XX], ind[YY], ind[ZZ]); } } else { for (zone = 0; zone < dd_zones->n; zone++) { ccg0 = dd_zones->cg_range[zone]; ccg1 = dd_zones->cg_range[zone+1]; if (ccg1 <= cg0 || ccg0 >= cg1) { continue; } /* Determine the ns grid cell limits for this DD zone */ for (d = 0; d < DIM; d++) { shift0[d] = dd_zones->shift[zone][d]; useall[d] = (shift0[d] == 0 || d >= grid->npbcdim); /* Check if we need to do normal or optimized grid assignments. * Normal is required for dims without DD or triclinic dims. * DD edge cell on dims without pbc will be automatically * be correct, since the shift=0 zones with have b0 and b1 * set to the grid boundaries and there are no shift=1 zones. */ if (grid->ncpddc[d] == 0) { b0[d] = 0; b1[d] = grid->n[d]; } else { if (shift0[d] == 0) { b0[d] = 0; b1[d] = grid->ncpddc[d]; } else { /* shift = 1 */ b0[d] = grid->ncpddc[d]; b1[d] = grid->n[d]; } } } not_used = ci_not_used(grid->n); /* Put all the charge groups of this DD zone on the grid */ for (cg = ccg0; cg < ccg1; cg++) { if (cell_index[cg] == -1) { /* This cg has moved to another node */ cell_index[cg] = NSGRID_SIGNAL_MOVED_FAC*grid->ncells; continue; } bUse = TRUE; for (d = 0; d < DIM; d++) { ind[d] = (cg_cm[cg][d] - offset[d])*n_box[d]; /* Here we have to correct for rounding problems, * as this cg_cm to cell index operation is not necessarily * binary identical to the operation for the DD zone assignment * and therefore a cg could end up in an unused grid cell. * For dimensions without pbc we need to check * for cells on the edge if charge groups are beyond * the grid and if so, store them in the closest cell. */ if (ind[d] < b0[d]) { ind[d] = b0[d]; } else if (ind[d] >= b1[d]) { if (useall[d]) { ind[d] = b1[d] - 1; } else { /* Charge groups in this DD zone further away than the cut-off * in direction do not participate in non-bonded interactions. */ bUse = FALSE; } } } if (cg > grid->nr_alloc) { fprintf(stderr, "WARNING: nra_alloc %d cg0 %d cg1 %d cg %d\n", grid->nr_alloc, cg0, cg1, cg); } if (bUse) { cell_index[cg] = xyz2ci(nry, nrz, ind[XX], ind[YY], ind[ZZ]); } else { cell_index[cg] = not_used; } } } } debug_gmx(); }
void do_md_trajectory_writing(FILE *fplog, t_commrec *cr, int nfile, const t_filenm fnm[], gmx_int64_t step, gmx_int64_t step_rel, double t, t_inputrec *ir, t_state *state, t_state *state_global, gmx_mtop_t *top_global, t_forcerec *fr, gmx_mdoutf_t outf, t_mdebin *mdebin, gmx_ekindata_t *ekind, rvec *f, rvec *f_global, int *nchkpt, gmx_bool bCPT, gmx_bool bRerunMD, gmx_bool bLastStep, gmx_bool bDoConfOut, gmx_bool bSumEkinhOld ) { int mdof_flags; mdof_flags = 0; if (do_per_step(step, ir->nstxout)) { mdof_flags |= MDOF_X; } if (do_per_step(step, ir->nstvout)) { mdof_flags |= MDOF_V; } if (do_per_step(step, ir->nstfout)) { mdof_flags |= MDOF_F; } if (do_per_step(step, ir->nstxout_compressed)) { mdof_flags |= MDOF_X_COMPRESSED; } if (bCPT) { mdof_flags |= MDOF_CPT; } ; #if defined(GMX_FAHCORE) || defined(GMX_WRITELASTSTEP) if (bLastStep) { /* Enforce writing positions and velocities at end of run */ mdof_flags |= (MDOF_X | MDOF_V); } #endif #ifdef GMX_FAHCORE if (MASTER(cr)) { fcReportProgress( ir->nsteps, step ); } #if defined(__native_client__) fcCheckin(MASTER(cr)); #endif /* sync bCPT and fc record-keeping */ if (bCPT && MASTER(cr)) { fcRequestCheckPoint(); } #endif if (mdof_flags != 0) { wallcycle_start(mdoutf_get_wcycle(outf), ewcTRAJ); if (bCPT) { if (MASTER(cr)) { if (bSumEkinhOld) { state_global->ekinstate.bUpToDate = FALSE; } else { update_ekinstate(&state_global->ekinstate, ekind); state_global->ekinstate.bUpToDate = TRUE; } update_energyhistory(&state_global->enerhist, mdebin); } } mdoutf_write_to_trajectory_files(fplog, cr, outf, mdof_flags, top_global, step, t, state, state_global, f, f_global); if (bCPT) { (*nchkpt)++; } debug_gmx(); if (bLastStep && step_rel == ir->nsteps && bDoConfOut && MASTER(cr) && !bRerunMD) { /* x and v have been collected in mdoutf_write_to_trajectory_files, * because a checkpoint file will always be written * at the last step. */ fprintf(stderr, "\nWriting final coordinates.\n"); if (fr->bMolPBC) { /* Make molecules whole only for confout writing */ do_pbc_mtop(fplog, ir->ePBC, state->box, top_global, state_global->x); } write_sto_conf_mtop(ftp2fn(efSTO, nfile, fnm), *top_global->name, top_global, state_global->x, state_global->v, ir->ePBC, state->box); debug_gmx(); } wallcycle_stop(mdoutf_get_wcycle(outf), ewcTRAJ); } }
void do_force_lowlevel(FILE *fplog, gmx_large_int_t step, t_forcerec *fr, t_inputrec *ir, t_idef *idef, t_commrec *cr, t_nrnb *nrnb, gmx_wallcycle_t wcycle, t_mdatoms *md, t_grpopts *opts, rvec x[], history_t *hist, rvec f[], gmx_enerdata_t *enerd, t_fcdata *fcd, gmx_mtop_t *mtop, gmx_localtop_t *top, gmx_genborn_t *born, t_atomtypes *atype, gmx_bool bBornRadii, matrix box, real lambda, t_graph *graph, t_blocka *excl, rvec mu_tot[], int flags, float *cycles_pme) { int i,status; int donb_flags; gmx_bool bDoEpot,bSepDVDL,bSB; int pme_flags; matrix boxs; rvec box_size; real dvdlambda,Vsr,Vlr,Vcorr=0,vdip,vcharge; t_pbc pbc; real dvdgb; char buf[22]; gmx_enerdata_t ed_lam; double lam_i; real dvdl_dum; #ifdef GMX_MPI double t0=0.0,t1,t2,t3; /* time measurement for coarse load balancing */ #endif #define PRINT_SEPDVDL(s,v,dvdl) if (bSepDVDL) fprintf(fplog,sepdvdlformat,s,v,dvdl); GMX_MPE_LOG(ev_force_start); set_pbc(&pbc,fr->ePBC,box); /* Reset box */ for(i=0; (i<DIM); i++) { box_size[i]=box[i][i]; } bSepDVDL=(fr->bSepDVDL && do_per_step(step,ir->nstlog)); debug_gmx(); /* do QMMM first if requested */ if(fr->bQMMM) { enerd->term[F_EQM] = calculate_QMMM(cr,x,f,fr,md); } if (bSepDVDL) { fprintf(fplog,"Step %s: non-bonded V and dVdl for node %d:\n", gmx_step_str(step,buf),cr->nodeid); } /* Call the short range functions all in one go. */ GMX_MPE_LOG(ev_do_fnbf_start); dvdlambda = 0; #ifdef GMX_MPI /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/ #define TAKETIME FALSE if (TAKETIME) { MPI_Barrier(cr->mpi_comm_mygroup); t0=MPI_Wtime(); } #endif if (ir->nwall) { dvdlambda = do_walls(ir,fr,box,md,x,f,lambda, enerd->grpp.ener[egLJSR],nrnb); PRINT_SEPDVDL("Walls",0.0,dvdlambda); enerd->dvdl_lin += dvdlambda; } /* If doing GB, reset dvda and calculate the Born radii */ if (ir->implicit_solvent) { /* wallcycle_start(wcycle,ewcGB); */ for(i=0; i<born->nr; i++) { fr->dvda[i]=0; } if(bBornRadii) { calc_gb_rad(cr,fr,ir,top,atype,x,&(fr->gblist),born,md,nrnb); } /* wallcycle_stop(wcycle, ewcGB); */ } where(); donb_flags = 0; if (flags & GMX_FORCE_FORCES) { donb_flags |= GMX_DONB_FORCES; } do_nonbonded(cr,fr,x,f,md,excl, fr->bBHAM ? enerd->grpp.ener[egBHAMSR] : enerd->grpp.ener[egLJSR], enerd->grpp.ener[egCOULSR], enerd->grpp.ener[egGB],box_size,nrnb, lambda,&dvdlambda,-1,-1,donb_flags); /* If we do foreign lambda and we have soft-core interactions * we have to recalculate the (non-linear) energies contributions. */ if (ir->n_flambda > 0 && (flags & GMX_FORCE_DHDL) && ir->sc_alpha != 0) { init_enerdata(mtop->groups.grps[egcENER].nr,ir->n_flambda,&ed_lam); for(i=0; i<enerd->n_lambda; i++) { lam_i = (i==0 ? lambda : ir->flambda[i-1]); dvdl_dum = 0; reset_enerdata(&ir->opts,fr,TRUE,&ed_lam,FALSE); do_nonbonded(cr,fr,x,f,md,excl, fr->bBHAM ? ed_lam.grpp.ener[egBHAMSR] : ed_lam.grpp.ener[egLJSR], ed_lam.grpp.ener[egCOULSR], enerd->grpp.ener[egGB], box_size,nrnb, lam_i,&dvdl_dum,-1,-1, GMX_DONB_FOREIGNLAMBDA); sum_epot(&ir->opts,&ed_lam); enerd->enerpart_lambda[i] += ed_lam.term[F_EPOT]; } destroy_enerdata(&ed_lam); } where(); /* If we are doing GB, calculate bonded forces and apply corrections * to the solvation forces */ if (ir->implicit_solvent) { calc_gb_forces(cr,md,born,top,atype,x,f,fr,idef, ir->gb_algorithm,ir->sa_algorithm,nrnb,bBornRadii,&pbc,graph,enerd); } #ifdef GMX_MPI if (TAKETIME) { t1=MPI_Wtime(); fr->t_fnbf += t1-t0; } #endif if (ir->sc_alpha != 0) { enerd->dvdl_nonlin += dvdlambda; } else { enerd->dvdl_lin += dvdlambda; } Vsr = 0; if (bSepDVDL) { for(i=0; i<enerd->grpp.nener; i++) { Vsr += (fr->bBHAM ? enerd->grpp.ener[egBHAMSR][i] : enerd->grpp.ener[egLJSR][i]) + enerd->grpp.ener[egCOULSR][i] + enerd->grpp.ener[egGB][i]; } } PRINT_SEPDVDL("VdW and Coulomb SR particle-p.",Vsr,dvdlambda); debug_gmx(); GMX_MPE_LOG(ev_do_fnbf_finish); if (debug) { pr_rvecs(debug,0,"fshift after SR",fr->fshift,SHIFTS); } /* Shift the coordinates. Must be done before bonded forces and PPPM, * but is also necessary for SHAKE and update, therefore it can NOT * go when no bonded forces have to be evaluated. */ /* Here sometimes we would not need to shift with NBFonly, * but we do so anyhow for consistency of the returned coordinates. */ if (graph) { shift_self(graph,box,x); if (TRICLINIC(box)) { inc_nrnb(nrnb,eNR_SHIFTX,2*graph->nnodes); } else { inc_nrnb(nrnb,eNR_SHIFTX,graph->nnodes); } } /* Check whether we need to do bondeds or correct for exclusions */ if (fr->bMolPBC && ((flags & GMX_FORCE_BONDED) || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype))) { /* Since all atoms are in the rectangular or triclinic unit-cell, * only single box vector shifts (2 in x) are required. */ set_pbc_dd(&pbc,fr->ePBC,cr->dd,TRUE,box); } debug_gmx(); if (flags & GMX_FORCE_BONDED) { GMX_MPE_LOG(ev_calc_bonds_start); calc_bonds(fplog,cr->ms, idef,x,hist,f,fr,&pbc,graph,enerd,nrnb,lambda,md,fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, atype, born, fr->bSepDVDL && do_per_step(step,ir->nstlog),step); /* Check if we have to determine energy differences * at foreign lambda's. */ if (ir->n_flambda > 0 && (flags & GMX_FORCE_DHDL) && idef->ilsort != ilsortNO_FE) { if (idef->ilsort != ilsortFE_SORTED) { gmx_incons("The bonded interactions are not sorted for free energy"); } init_enerdata(mtop->groups.grps[egcENER].nr,ir->n_flambda,&ed_lam); for(i=0; i<enerd->n_lambda; i++) { lam_i = (i==0 ? lambda : ir->flambda[i-1]); dvdl_dum = 0; reset_enerdata(&ir->opts,fr,TRUE,&ed_lam,FALSE); calc_bonds_lambda(fplog, idef,x,fr,&pbc,graph,&ed_lam,nrnb,lam_i,md, fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL); sum_epot(&ir->opts,&ed_lam); enerd->enerpart_lambda[i] += ed_lam.term[F_EPOT]; } destroy_enerdata(&ed_lam); } debug_gmx(); GMX_MPE_LOG(ev_calc_bonds_finish); } where(); *cycles_pme = 0; if (EEL_FULL(fr->eeltype)) { bSB = (ir->nwall == 2); if (bSB) { copy_mat(box,boxs); svmul(ir->wall_ewald_zfac,boxs[ZZ],boxs[ZZ]); box_size[ZZ] *= ir->wall_ewald_zfac; } clear_mat(fr->vir_el_recip); if (fr->bEwald) { if (fr->n_tpi == 0) { dvdlambda = 0; Vcorr = ewald_LRcorrection(fplog,md->start,md->start+md->homenr, cr,fr, md->chargeA, md->nChargePerturbed ? md->chargeB : NULL, excl,x,bSB ? boxs : box,mu_tot, ir->ewald_geometry, ir->epsilon_surface, lambda,&dvdlambda,&vdip,&vcharge); PRINT_SEPDVDL("Ewald excl./charge/dip. corr.",Vcorr,dvdlambda); enerd->dvdl_lin += dvdlambda; } else { if (ir->ewald_geometry != eewg3D || ir->epsilon_surface != 0) { gmx_fatal(FARGS,"TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions"); } /* The TPI molecule does not have exclusions with the rest * of the system and no intra-molecular PME grid contributions * will be calculated in gmx_pme_calc_energy. */ Vcorr = 0; } } else { Vcorr = shift_LRcorrection(fplog,md->start,md->homenr,cr,fr, md->chargeA,excl,x,TRUE,box, fr->vir_el_recip); } dvdlambda = 0; status = 0; switch (fr->eeltype) { case eelPPPM: status = gmx_pppm_do(fplog,fr->pmedata,FALSE,x,fr->f_novirsum, md->chargeA, box_size,fr->phi,cr,md->start,md->homenr, nrnb,ir->pme_order,&Vlr); break; case eelPME: case eelPMESWITCH: case eelPMEUSER: case eelPMEUSERSWITCH: if (cr->duty & DUTY_PME) { if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED)) { pme_flags = GMX_PME_SPREAD_Q | GMX_PME_SOLVE; if (flags & GMX_FORCE_FORCES) { pme_flags |= GMX_PME_CALC_F; } if (flags & GMX_FORCE_VIRIAL) { pme_flags |= GMX_PME_CALC_ENER_VIR; } if (fr->n_tpi > 0) { /* We don't calculate f, but we do want the potential */ pme_flags |= GMX_PME_CALC_POT; } wallcycle_start(wcycle,ewcPMEMESH); status = gmx_pme_do(fr->pmedata, md->start,md->homenr - fr->n_tpi, x,fr->f_novirsum, md->chargeA,md->chargeB, bSB ? boxs : box,cr, DOMAINDECOMP(cr) ? dd_pme_maxshift_x(cr->dd) : 0, DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0, nrnb,wcycle, fr->vir_el_recip,fr->ewaldcoeff, &Vlr,lambda,&dvdlambda, pme_flags); *cycles_pme = wallcycle_stop(wcycle,ewcPMEMESH); /* We should try to do as little computation after * this as possible, because parallel PME synchronizes * the nodes, so we want all load imbalance of the rest * of the force calculation to be before the PME call. * DD load balancing is done on the whole time of * the force call (without PME). */ } if (fr->n_tpi > 0) { /* Determine the PME grid energy of the test molecule * with the PME grid potential of the other charges. */ gmx_pme_calc_energy(fr->pmedata,fr->n_tpi, x + md->homenr - fr->n_tpi, md->chargeA + md->homenr - fr->n_tpi, &Vlr); } PRINT_SEPDVDL("PME mesh",Vlr,dvdlambda); } else { /* Energies and virial are obtained later from the PME nodes */ /* but values have to be zeroed out here */ Vlr=0.0; } break; case eelEWALD: Vlr = do_ewald(fplog,FALSE,ir,x,fr->f_novirsum, md->chargeA,md->chargeB, box_size,cr,md->homenr, fr->vir_el_recip,fr->ewaldcoeff, lambda,&dvdlambda,fr->ewald_table); PRINT_SEPDVDL("Ewald long-range",Vlr,dvdlambda); break; default: Vlr = 0; gmx_fatal(FARGS,"No such electrostatics method implemented %s", eel_names[fr->eeltype]); } if (status != 0) { gmx_fatal(FARGS,"Error %d in long range electrostatics routine %s", status,EELTYPE(fr->eeltype)); } enerd->dvdl_lin += dvdlambda; enerd->term[F_COUL_RECIP] = Vlr + Vcorr; if (debug) { fprintf(debug,"Vlr = %g, Vcorr = %g, Vlr_corr = %g\n", Vlr,Vcorr,enerd->term[F_COUL_RECIP]); pr_rvecs(debug,0,"vir_el_recip after corr",fr->vir_el_recip,DIM); pr_rvecs(debug,0,"fshift after LR Corrections",fr->fshift,SHIFTS); } } else { if (EEL_RF(fr->eeltype)) { dvdlambda = 0; if (fr->eeltype != eelRF_NEC) { enerd->term[F_RF_EXCL] = RF_excl_correction(fplog,fr,graph,md,excl,x,f, fr->fshift,&pbc,lambda,&dvdlambda); } enerd->dvdl_lin += dvdlambda; PRINT_SEPDVDL("RF exclusion correction", enerd->term[F_RF_EXCL],dvdlambda); } } where(); debug_gmx(); if (debug) { print_nrnb(debug,nrnb); } debug_gmx(); #ifdef GMX_MPI if (TAKETIME) { t2=MPI_Wtime(); MPI_Barrier(cr->mpi_comm_mygroup); t3=MPI_Wtime(); fr->t_wait += t3-t2; if (fr->timesteps == 11) { fprintf(stderr,"* PP load balancing info: node %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n", cr->nodeid, gmx_step_str(fr->timesteps,buf), 100*fr->t_wait/(fr->t_wait+fr->t_fnbf), (fr->t_fnbf+fr->t_wait)/fr->t_fnbf); } fr->timesteps++; } #endif if (debug) { pr_rvecs(debug,0,"fshift after bondeds",fr->fshift,SHIFTS); } GMX_MPE_LOG(ev_force_finish); }