/* Give a suitable fatal error or warning if the build configuration and runtime CPU do not match. */ static void check_use_of_rdtscp_on_this_cpu(FILE *fplog, const t_commrec *cr, const gmx_hw_info_t *hwinfo) { gmx_bool bCpuHasRdtscp, bBinaryUsesRdtscp; #ifdef HAVE_RDTSCP bBinaryUsesRdtscp = TRUE; #else bBinaryUsesRdtscp = FALSE; #endif bCpuHasRdtscp = gmx_cpuid_feature(hwinfo->cpuid_info, GMX_CPUID_FEATURE_X86_RDTSCP); if (!bCpuHasRdtscp && bBinaryUsesRdtscp) { gmx_fatal(FARGS, "The %s executable was compiled to use the rdtscp CPU instruction. " "However, this is not supported by the current hardware and continuing would lead to a crash. " "Please rebuild GROMACS with the GMX_USE_RDTSCP=OFF CMake option.", ShortProgram()); } if (bCpuHasRdtscp && !bBinaryUsesRdtscp) { md_print_warn(cr, fplog, "The current CPU can measure timings more accurately than the code in\n" "%s was configured to use. This might affect your simulation\n" "speed as accurate timings are needed for load-balancing.\n" "Please consider rebuilding %s with the GMX_USE_RDTSCP=OFF CMake option.\n", ShortProgram(), ShortProgram()); } }
void gmx_abort(int noderank, int nnodes, int errorno) { #ifndef GMX_MPI gmx_call("gmx_abort"); #else #ifdef GMX_THREAD_MPI fprintf(stderr, "Halting program %s\n", ShortProgram()); thanx(stderr); exit(1); #else if (nnodes > 1) { fprintf(stderr, "Halting parallel program %s on CPU %d out of %d\n", ShortProgram(), noderank, nnodes); } else { fprintf(stderr, "Halting program %s\n", ShortProgram()); } thanx(stderr); MPI_Abort(MPI_COMM_WORLD, errorno); exit(1); #endif #endif }
static void write_bashcompl(FILE *out, int nfile, t_filenm *fnm, int npargs, t_pargs *pa) { /* Advanced bash completions are handled by shell functions. * p and c hold the previous and current word on the command line. * We need to use extended globbing, so write it in each completion file */ fprintf(out,"shopt -s extglob\n"); fprintf(out,"_%s_compl() {\nlocal p c\n",ShortProgram()); fprintf(out,"COMPREPLY=() c=${COMP_WORDS[COMP_CWORD]} p=${COMP_WORDS[COMP_CWORD-1]}\n"); pr_opts(out,nfile,fnm,npargs,pa,eshellBASH); fprintf(out,"case \"$p\" in\n"); pr_enums(out,npargs,pa,eshellBASH); pr_fopts(out,nfile,fnm,eshellBASH); fprintf(out,"esac; }; \ncomplete -F _%s_compl %s\n",ShortProgram(),ShortProgram()); }
static void write_cshcompl(FILE *out, int nfile, t_filenm *fnm, int npargs, t_pargs *pa) { fprintf(out,"complete %s",ShortProgram()); pr_enums(out,npargs,pa,eshellCSH); pr_fopts(out,nfile,fnm,eshellCSH); pr_opts(out,nfile,fnm,npargs,pa,eshellCSH); fprintf(out,"\n"); }
static void vdw_warning(FILE *fp) { if (NULL != fp) { fprintf(fp, "NOTE: From version 5.0 %s uses the Van der Waals radii\n", ShortProgram()); fprintf(fp, "from the source below. This means the results may be different\n"); fprintf(fp, "compared to previous GROMACS versions.\n"); please_cite(fp, "Bondi1964a"); } }
static void write_zshcompl(FILE *out, int nfile, t_filenm *fnm, int npargs, t_pargs *pa) { fprintf(out,"compctl "); /* start with options, since they are always present */ pr_opts(out,nfile,fnm,npargs,pa,eshellZSH); pr_enums(out,npargs,pa,eshellZSH); pr_fopts(out,nfile,fnm,eshellZSH); fprintf(out,"-- %s\n",ShortProgram()); }
void done_warning(warninp_t wi, int f_errno, const char *file, int line) { print_warn_count("note", wi->nwarn_note); print_warn_count("warning", wi->nwarn_warn); check_warning_error(wi, f_errno, file, line); if (wi->maxwarn >= 0 && wi->nwarn_warn > wi->maxwarn) { gmx_fatal(f_errno, file, line, "Too many warnings (%d), %s terminated.\n" "If you are sure all warnings are harmless, use the -maxwarn option.", wi->nwarn_warn, ShortProgram()); } free_warning(wi); }
void _gmx_error(const char *key,const char *msg,const char *file,int line) { char buf[10240],tmpbuf[1024]; int cqnum; /* protect the audience from suggestive discussions */ char *lines = "-------------------------------------------------------"; cool_quote(tmpbuf,1023,&cqnum); sprintf(buf,"\n%s\nProgram %s, %s\n" "Source code file: %s, line: %d\n\n" "%s:\n%s\n%s\n\n%s\n", lines,ShortProgram(),GromacsVersion(),file,line, gmx_strerror(key),msg ? msg : warn_buf,lines,tmpbuf); gmx_error_handler(buf); }
void _gmx_error(const char *key,const char *msg,const char *file,int line) { char buf[10240],tmpbuf[1024]; int cqnum; /* protect the audience from suggestive discussions */ const char *lines = "-------------------------------------------------------"; cool_quote(tmpbuf,1023,&cqnum); sprintf(buf,"\n%s\nProgram %s, %s\n" "Source code file: %s, line: %d\n\n" "%s:\n%s\nFor more information and tips for trouble shooting please check the GROMACS Wiki at\n" "http://wiki.gromacs.org/index.php/Errors\n%s\n\n%s\n", lines,ShortProgram(),GromacsVersion(),file,line, gmx_strerror(key),msg ? msg : warn_buf,lines,tmpbuf); gmx_error_handler(buf); }
void xvgr_header(FILE *fp, const char *title, const char *xaxis, const char *yaxis, int exvg_graph_type, const output_env_t oenv) { char pukestr[100], buf[STRLEN]; time_t t; if (output_env_get_print_xvgr_codes(oenv)) { time(&t); gmx_ctime_r(&t, buf, STRLEN); fprintf(fp, "# This file was created %s", buf); fprintf(fp, "# by the following command:\n# %s\n#\n", command_line()); fprintf(fp, "# %s is part of G R O M A C S:\n#\n", ShortProgram()); bromacs(pukestr, 99); fprintf(fp, "# %s\n#\n", pukestr); fprintf(fp, "@ title \"%s\"\n", xvgrstr(title, oenv, buf, STRLEN)); fprintf(fp, "@ xaxis label \"%s\"\n", xvgrstr(xaxis, oenv, buf, STRLEN)); fprintf(fp, "@ yaxis label \"%s\"\n", xvgrstr(yaxis, oenv, buf, STRLEN)); switch (exvg_graph_type) { case exvggtXNY: if (output_env_get_xvg_format(oenv) == exvgXMGR) { fprintf(fp, "@TYPE nxy\n"); } else { fprintf(fp, "@TYPE xy\n"); } break; case exvggtXYDY: fprintf(fp, "@TYPE xydy\n"); break; case exvggtXYDYDY: fprintf(fp, "@TYPE xydydy\n"); break; } } }
int gmx_x2top(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] generates a primitive topology from a coordinate file.", "The program assumes all hydrogens are present when defining", "the hybridization from the atom name and the number of bonds.", "The program can also make an [TT].rtp[tt] entry, which you can then add", "to the [TT].rtp[tt] database.[PAR]", "When [TT]-param[tt] is set, equilibrium distances and angles", "and force constants will be printed in the topology for all", "interactions. The equilibrium distances and angles are taken", "from the input coordinates, the force constant are set with", "command line options.", "The force fields somewhat supported currently are:[PAR]", "G53a5 GROMOS96 53a5 Forcefield (official distribution)[PAR]", "oplsaa OPLS-AA/L all-atom force field (2001 aminoacid dihedrals)[PAR]", "The corresponding data files can be found in the library directory", "with name [TT]atomname2type.n2t[tt]. Check Chapter 5 of the manual for more", "information about file formats. By default, the force field selection", "is interactive, but you can use the [TT]-ff[tt] option to specify", "one of the short names above on the command line instead. In that", "case [THISMODULE] just looks for the corresponding file.[PAR]", }; const char *bugs[] = { "The atom type selection is primitive. Virtually no chemical knowledge is used", "Periodic boundary conditions screw up the bonding", "No improper dihedrals are generated", "The atoms to atomtype translation table is incomplete ([TT]atomname2type.n2t[tt] file in the data directory). Please extend it and send the results back to the GROMACS crew." }; FILE *fp; t_params plist[F_NRE]; t_excls *excls; t_atoms *atoms; /* list with all atoms */ gpp_atomtype_t atype; t_nextnb nnb; t_nm2type *nm2t; t_mols mymol; int nnm; char title[STRLEN], forcefield[32], ffdir[STRLEN]; rvec *x; /* coordinates? */ int *nbonds, *cgnr; int bts[] = { 1, 1, 1, 2 }; matrix box; /* box length matrix */ int natoms; /* number of atoms in one molecule */ int nres; /* number of molecules? */ int i, j, k, l, m, ndih; int epbc; gmx_bool bRTP, bTOP, bOPLS; t_symtab symtab; real cutoff, qtot, mtot; char n2t[STRLEN]; output_env_t oenv; t_filenm fnm[] = { { efSTX, "-f", "conf", ffREAD }, { efTOP, "-o", "out", ffOPTWR }, { efRTP, "-r", "out", ffOPTWR } }; #define NFILE asize(fnm) static real scale = 1.1, kb = 4e5, kt = 400, kp = 5; static t_restp rtp_header_settings; static gmx_bool bRemoveDihedralIfWithImproper = FALSE; static gmx_bool bGenerateHH14Interactions = TRUE; static gmx_bool bKeepAllGeneratedDihedrals = FALSE; static int nrexcl = 3; static gmx_bool bParam = TRUE, bRound = TRUE; static gmx_bool bPairs = TRUE, bPBC = TRUE; static gmx_bool bUsePDBcharge = FALSE, bVerbose = FALSE; static const char *molnm = "ICE"; static const char *ff = "oplsaa"; t_pargs pa[] = { { "-ff", FALSE, etSTR, {&ff}, "Force field for your simulation. Type \"select\" for interactive selection." }, { "-v", FALSE, etBOOL, {&bVerbose}, "Generate verbose output in the top file." }, { "-nexcl", FALSE, etINT, {&nrexcl}, "Number of exclusions" }, { "-H14", FALSE, etBOOL, {&bGenerateHH14Interactions}, "Use 3rd neighbour interactions for hydrogen atoms" }, { "-alldih", FALSE, etBOOL, {&bKeepAllGeneratedDihedrals}, "Generate all proper dihedrals" }, { "-remdih", FALSE, etBOOL, {&bRemoveDihedralIfWithImproper}, "Remove dihedrals on the same bond as an improper" }, { "-pairs", FALSE, etBOOL, {&bPairs}, "Output 1-4 interactions (pairs) in topology file" }, { "-name", FALSE, etSTR, {&molnm}, "Name of your molecule" }, { "-pbc", FALSE, etBOOL, {&bPBC}, "Use periodic boundary conditions." }, { "-pdbq", FALSE, etBOOL, {&bUsePDBcharge}, "Use the B-factor supplied in a [TT].pdb[tt] file for the atomic charges" }, { "-param", FALSE, etBOOL, {&bParam}, "Print parameters in the output" }, { "-round", FALSE, etBOOL, {&bRound}, "Round off measured values" }, { "-kb", FALSE, etREAL, {&kb}, "Bonded force constant (kJ/mol/nm^2)" }, { "-kt", FALSE, etREAL, {&kt}, "Angle force constant (kJ/mol/rad^2)" }, { "-kp", FALSE, etREAL, {&kp}, "Dihedral angle force constant (kJ/mol/rad^2)" } }; if (!parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa), pa, asize(desc), desc, asize(bugs), bugs, &oenv)) { return 0; } bRTP = opt2bSet("-r", NFILE, fnm); bTOP = opt2bSet("-o", NFILE, fnm); /* C89 requirements mean that these struct members cannot be used in * the declaration of pa. So some temporary variables are needed. */ rtp_header_settings.bRemoveDihedralIfWithImproper = bRemoveDihedralIfWithImproper; rtp_header_settings.bGenerateHH14Interactions = bGenerateHH14Interactions; rtp_header_settings.bKeepAllGeneratedDihedrals = bKeepAllGeneratedDihedrals; rtp_header_settings.nrexcl = nrexcl; if (!bRTP && !bTOP) { gmx_fatal(FARGS, "Specify at least one output file"); } /* Force field selection, interactive or direct */ choose_ff(strcmp(ff, "select") == 0 ? NULL : ff, forcefield, sizeof(forcefield), ffdir, sizeof(ffdir)); bOPLS = (strcmp(forcefield, "oplsaa") == 0); mymol.name = strdup(molnm); mymol.nr = 1; /* Init parameter lists */ init_plist(plist); /* Read coordinates */ get_stx_coordnum(opt2fn("-f", NFILE, fnm), &natoms); snew(atoms, 1); /* make space for all the atoms */ init_t_atoms(atoms, natoms, TRUE); snew(x, natoms); read_stx_conf(opt2fn("-f", NFILE, fnm), title, atoms, x, NULL, &epbc, box); sprintf(n2t, "%s", ffdir); nm2t = rd_nm2type(n2t, &nnm); if (nnm == 0) { gmx_fatal(FARGS, "No or incorrect atomname2type.n2t file found (looking for %s)", n2t); } else { printf("There are %d name to type translations in file %s\n", nnm, n2t); } if (debug) { dump_nm2type(debug, nnm, nm2t); } printf("Generating bonds from distances...\n"); snew(nbonds, atoms->nr); mk_bonds(nnm, nm2t, atoms, x, &(plist[F_BONDS]), nbonds, bPBC, box); open_symtab(&symtab); atype = set_atom_type(&symtab, atoms, &(plist[F_BONDS]), nbonds, nnm, nm2t); /* Make Angles and Dihedrals */ snew(excls, atoms->nr); printf("Generating angles and dihedrals from bonds...\n"); init_nnb(&nnb, atoms->nr, 4); gen_nnb(&nnb, plist); print_nnb(&nnb, "NNB"); gen_pad(&nnb, atoms, &rtp_header_settings, plist, excls, NULL, TRUE); done_nnb(&nnb); if (!bPairs) { plist[F_LJ14].nr = 0; } fprintf(stderr, "There are %4d %s dihedrals, %4d impropers, %4d angles\n" " %4d pairs, %4d bonds and %4d atoms\n", plist[F_PDIHS].nr, bOPLS ? "Ryckaert-Bellemans" : "proper", plist[F_IDIHS].nr, plist[F_ANGLES].nr, plist[F_LJ14].nr, plist[F_BONDS].nr, atoms->nr); calc_angles_dihs(&plist[F_ANGLES], &plist[F_PDIHS], x, bPBC, box); set_force_const(plist, kb, kt, kp, bRound, bParam); cgnr = set_cgnr(atoms, bUsePDBcharge, &qtot, &mtot); printf("Total charge is %g, total mass is %g\n", qtot, mtot); if (bOPLS) { bts[2] = 3; bts[3] = 1; } if (bTOP) { fp = ftp2FILE(efTOP, NFILE, fnm, "w"); print_top_header(fp, ftp2fn(efTOP, NFILE, fnm), TRUE, ffdir, 1.0); write_top(fp, NULL, mymol.name, atoms, FALSE, bts, plist, excls, atype, cgnr, rtp_header_settings.nrexcl); print_top_mols(fp, mymol.name, ffdir, NULL, 0, NULL, 1, &mymol); ffclose(fp); } if (bRTP) { print_rtp(ftp2fn(efRTP, NFILE, fnm), "Generated by x2top", atoms, plist, atype, cgnr); } if (debug) { dump_hybridization(debug, atoms, nbonds); } close_symtab(&symtab); free(mymol.name); printf("\nWARNING: topologies generated by %s can not be trusted at face value.\n", ShortProgram()); printf(" Please verify atomtypes and charges by comparison to other\n"); printf(" topologies.\n"); return 0; }
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); } }
/* Check the process affinity mask and if it is found to be non-zero, * will honor it and disable mdrun internal affinity setting. * Note that this will only work on Linux as we use a GNU feature. */ void gmx_check_thread_affinity_set(FILE *fplog, const t_commrec *cr, gmx_hw_opt_t *hw_opt, int gmx_unused nthreads_hw_avail, gmx_bool bAfterOpenmpInit) { #ifdef HAVE_SCHED_AFFINITY cpu_set_t mask_current; int i, ret, cpu_count, cpu_set; gmx_bool bAllSet; #endif #ifdef GMX_LIB_MPI gmx_bool bAllSet_All; #endif assert(hw_opt); if (!bAfterOpenmpInit) { /* Check for externally set OpenMP affinity and turn off internal * pinning if any is found. We need to do this check early to tell * thread-MPI whether it should do pinning when spawning threads. * TODO: the above no longer holds, we should move these checks later */ if (hw_opt->thread_affinity != threadaffOFF) { char *message; if (!gmx_omp_check_thread_affinity(&message)) { /* TODO: with -pin auto we should only warn when using all cores */ md_print_warn(cr, fplog, "%s", message); sfree(message); hw_opt->thread_affinity = threadaffOFF; } } /* With thread-MPI this is needed as pinning might get turned off, * which needs to be known before starting thread-MPI. * With thread-MPI hw_opt is processed here on the master rank * and passed to the other ranks later, so we only do this on master. */ if (!SIMMASTER(cr)) { return; } #ifndef GMX_THREAD_MPI return; #endif } #ifdef HAVE_SCHED_AFFINITY if (hw_opt->thread_affinity == threadaffOFF) { /* internal affinity setting is off, don't bother checking process affinity */ return; } CPU_ZERO(&mask_current); if ((ret = sched_getaffinity(0, sizeof(cpu_set_t), &mask_current)) != 0) { /* failed to query affinity mask, will just return */ if (debug) { fprintf(debug, "Failed to query affinity mask (error %d)", ret); } return; } /* Before proceeding with the actual check, make sure that the number of * detected CPUs is >= the CPUs in the current set. * We need to check for CPU_COUNT as it was added only in glibc 2.6. */ #ifdef CPU_COUNT if (nthreads_hw_avail < CPU_COUNT(&mask_current)) { if (debug) { fprintf(debug, "%d hardware threads detected, but %d was returned by CPU_COUNT", nthreads_hw_avail, CPU_COUNT(&mask_current)); } return; } #endif /* CPU_COUNT */ bAllSet = TRUE; for (i = 0; (i < nthreads_hw_avail && i < CPU_SETSIZE); i++) { bAllSet = bAllSet && (CPU_ISSET(i, &mask_current) != 0); } #ifdef GMX_LIB_MPI MPI_Allreduce(&bAllSet, &bAllSet_All, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD); bAllSet = bAllSet_All; #endif if (!bAllSet) { if (hw_opt->thread_affinity == threadaffAUTO) { if (!bAfterOpenmpInit) { md_print_warn(cr, fplog, "Non-default thread affinity set, disabling internal thread affinity"); } else { md_print_warn(cr, fplog, "Non-default thread affinity set probably by the OpenMP library,\n" "disabling internal thread affinity"); } hw_opt->thread_affinity = threadaffOFF; } else { /* Only warn once, at the last check (bAfterOpenmpInit==TRUE) */ if (bAfterOpenmpInit) { md_print_warn(cr, fplog, "Overriding thread affinity set outside %s\n", ShortProgram()); } } if (debug) { fprintf(debug, "Non-default affinity mask found\n"); } } else { if (debug) { fprintf(debug, "Default affinity mask found\n"); } } #endif /* HAVE_SCHED_AFFINITY */ }
/*! * \param[in,out] d Trajectory analysis data structure. * \returns 0 on success, a non-zero error code on error. * * Initializes the selection data in \c gmx_ana_traj_t based on * the selection options and/or index files provided on the command line. * * This function is called automatically by parse_trjana_args() and should * not be called directly unless \ref ANA_USER_SELINIT is specified. * * \see ANA_USER_SELINIT */ int gmx_ana_init_selections(gmx_ana_traj_t *d) { int rc; int i; int nr; gmx_ana_indexgrps_t *grps; int natoms; bool bStdIn; bool bInteractive; bool bOk; if (d->sel) { gmx_call("init_selections called more than once\n" "perhaps you forgot ANA_USER_SELINIT"); return -1; } /* Check if we need some information from the topology */ if (gmx_ana_selcollection_requires_top(d->sc)) { rc = load_topology(d, TRUE); if (rc != 0) { return rc; } } /* Load the topology and init the index groups */ gmx_ana_indexgrps_init(&grps, d->top, d->ndxfile); /* Parse the selection */ rc = gmx_ana_selmethod_register_defaults(d->sc); if (rc != 0) { gmx_fatal(FARGS, "default selection method registration failed"); return rc; } bStdIn = (d->selfile && d->selfile[0] == '-' && d->selfile[1] == 0) || (d->selection && d->selection[0] == 0) || (!d->selfile && !d->selection); bInteractive = bStdIn && isatty(fileno(stdin)); if (bStdIn && bInteractive) { /* Parse from stdin */ /* First we parse the reference groups if there are any */ if (d->nrefgrps > 0) { fprintf(stderr, "\nSpecify "); if (d->nrefgrps == 1) { fprintf(stderr, "a reference selection"); } else { fprintf(stderr, "%d reference selections", d->nrefgrps); } fprintf(stderr, ":\n"); fprintf(stderr, "(one selection per line, use \\ for line continuation)\n"); rc = gmx_ana_selcollection_parse_stdin(d->sc, d->nrefgrps, grps, TRUE); nr = gmx_ana_selcollection_get_count(d->sc); if (rc != 0 || nr != d->nrefgrps) { gmx_ana_traj_free(d); gmx_input("unrecoverable error in selection parsing"); return rc; } } /* Then, we parse the analysis groups */ fprintf(stderr, "\nSpecify "); if (d->nanagrps == 1) { fprintf(stderr, "a selection"); } else if (d->nanagrps == -1) { fprintf(stderr, "any number of selections"); } else { fprintf(stderr, "%d selections", d->nanagrps); } fprintf(stderr, " for analysis:\n"); fprintf(stderr, "(one selection per line, use \\ for line continuation%s)\n", d->nanagrps == -1 ? ", Ctrl-D to end" : ""); rc = gmx_ana_selcollection_parse_stdin(d->sc, d->nanagrps, grps, TRUE); fprintf(stderr, "\n"); } else if (bStdIn) { rc = gmx_ana_selcollection_parse_stdin(d->sc, -1, grps, FALSE); } else if (d->selection) { rc = gmx_ana_selcollection_parse_str(d->sc, d->selection, grps); } else { rc = gmx_ana_selcollection_parse_file(d->sc, d->selfile, grps); } gmx_ana_indexgrps_free(grps); if (rc != 0) { /* Free memory for memory leak checking */ gmx_ana_traj_free(d); gmx_input("selection(s) could not be parsed"); return rc; } /* Check the number of groups */ nr = gmx_ana_selcollection_get_count(d->sc); if (nr <= d->nrefgrps) { gmx_input("selection does not specify enough index groups"); return -1; } if (d->nanagrps <= 0) { d->nanagrps = nr - d->nrefgrps; } else if (nr != d->nrefgrps + d->nanagrps) { gmx_input("selection does not specify the correct number of index groups"); return -1; } if (d->flags & ANA_DEBUG_SELECTION) { gmx_ana_selcollection_print_tree(stderr, d->sc, FALSE); } if (gmx_ana_selcollection_requires_top(d->sc)) { rc = load_topology(d, TRUE); if (rc != 0) { return rc; } } if (d->top) { natoms = -1; } else { rc = init_first_frame(d); if (rc != 0) { return rc; } natoms = d->fr->natoms; } gmx_ana_selcollection_set_topology(d->sc, d->top, natoms); rc = gmx_ana_selcollection_compile(d->sc); if (rc != 0) { /* Free memory for memory leak checking */ gmx_ana_traj_free(d); gmx_input("selection could not be compiled"); return rc; } /* Create the selection array */ d->ngrps = gmx_ana_selcollection_get_count(d->sc); if (!(d->flags & ANA_USE_FULLGRPS)) { d->ngrps -= d->nrefgrps; } snew(d->sel, d->ngrps); for (i = 0; i < d->ngrps; ++i) { if (d->flags & ANA_USE_FULLGRPS) { d->sel[i] = gmx_ana_selcollection_get_selection(d->sc, i); } else { d->sel[i] = gmx_ana_selcollection_get_selection(d->sc, i + d->nrefgrps); } } if (d->flags & ANA_DEBUG_SELECTION) { fprintf(stderr, "\n"); gmx_ana_selcollection_print_tree(stderr, d->sc, FALSE); fprintf(stderr, "\n"); gmx_ana_poscalc_coll_print_tree(stderr, d->pcc); fprintf(stderr, "\n"); } /* Initialize the position evaluation */ gmx_ana_poscalc_init_eval(d->pcc); if (d->flags & ANA_DEBUG_SELECTION) { gmx_ana_poscalc_coll_print_tree(stderr, d->pcc); fprintf(stderr, "\n"); } /* Check that dynamic selections are not provided if not allowed */ if (d->flags & ANA_NO_DYNSEL) { for (i = 0; i < d->nrefgrps + d->nanagrps; ++i) { gmx_ana_selection_t *sel; sel = gmx_ana_selcollection_get_selection(d->sc, i); if (sel->bDynamic) { gmx_fatal(FARGS, "%s does not support dynamic selections", ShortProgram()); return -1; } } } /* Check that non-atom positions are not provided if not allowed. * TODO: It would be better to have these checks in the parser. */ if (d->flags & ANA_ONLY_ATOMPOS) { for (i = 0; i < d->nanagrps; ++i) { gmx_ana_selection_t *sel; sel = gmx_ana_selcollection_get_selection(d->sc, i + d->nrefgrps); if (sel->p.m.type != INDEX_ATOM) { gmx_fatal(FARGS, "%s does not support non-atom positions", ShortProgram()); return -1; } } } /* Create the names array */ snew(d->grpnames, d->ngrps); for (i = 0; i < d->ngrps; ++i) { d->grpnames[i] = gmx_ana_selection_name(d->sel[i]); } return 0; }
/** Determine the number of threads for module \p mod. * * \p m takes values form the module_nth_t enum and maps these to the * corresponding value in modth_env_var. * * Each number of threads per module takes the default value unless * GMX_*_NUM_THERADS env var is set, case in which its value overrides * the deafult. * * The "group" scheme supports OpenMP only in PME and in thise case all but * the PME nthread values default to 1. */ static void pick_module_nthreads(FILE *fplog, int m, gmx_bool bSimMaster, gmx_bool bFullOmpSupport, gmx_bool bSepPME) { char *env; int nth; char sbuf[STRLEN]; gmx_bool bOMP; #ifdef GMX_OPENMP bOMP = TRUE; #else bOMP = FALSE; #endif /* GMX_OPENMP */ /* The default should never be set through a GMX_*_NUM_THREADS env var * as it's always equal with gnth. */ if (m == emntDefault) { return; } /* check the environment variable */ if ((env = getenv(modth_env_var[m])) != NULL) { sscanf(env, "%d", &nth); if (!bOMP) { gmx_warning("%s=%d is set, but %s is compiled without OpenMP!", modth_env_var[m], nth, ShortProgram()); } /* with the verlet codepath, when any GMX_*_NUM_THREADS env var is set, * OMP_NUM_THREADS also has to be set */ if (bFullOmpSupport && getenv("OMP_NUM_THREADS") == NULL) { gmx_fatal(FARGS, "%s=%d is set, the default number of threads also " "needs to be set with OMP_NUM_THREADS!", modth_env_var[m], nth); } /* with the group scheme warn if any env var except PME is set */ if (!bFullOmpSupport) { if (m != emntPME) { gmx_warning("%s=%d is set, but OpenMP multithreading is not " "supported in %s!", modth_env_var[m], nth, mod_name[m]); nth = 1; } } /* only babble if we are really overriding with a different value */ if ((bSepPME && m == emntPME && nth != modth.gnth_pme) || (nth != modth.gnth)) { sprintf(sbuf, "%s=%d set, overriding the default number of %s threads", modth_env_var[m], nth, mod_name[m]); if (bSimMaster) { fprintf(stderr, "\n%s\n", sbuf); } if (fplog) { fprintf(fplog, "%s\n", sbuf); } } } else { /* pick the global PME node nthreads if we are setting the number * of threads in separate PME nodes */ nth = (bSepPME && m == emntPME) ? modth.gnth_pme : modth.gnth; } gmx_omp_nthreads_set(m, nth); }
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 }
void gmx_omp_nthreads_init(FILE *fplog, t_commrec *cr, int nthreads_hw_avail, int omp_nthreads_req, int omp_nthreads_pme_req, gmx_bool gmx_unused bThisNodePMEOnly, gmx_bool bFullOmpSupport) { int nth, nth_pmeonly, gmx_maxth, nppn; char *env; gmx_bool bSepPME, bOMP; #ifdef GMX_OPENMP bOMP = TRUE; #else bOMP = FALSE; #endif /* GMX_OPENMP */ /* number of MPI processes/threads per physical node */ nppn = cr->nrank_intranode; bSepPME = ( (cr->duty & DUTY_PP) && !(cr->duty & DUTY_PME)) || (!(cr->duty & DUTY_PP) && (cr->duty & DUTY_PME)); #ifdef GMX_THREAD_MPI /* modth is shared among tMPI threads, so for thread safety do the * detection is done on the master only. It is not thread-safe with * multiple simulations, but that's anyway not supported by tMPI. */ if (SIMMASTER(cr)) #endif { /* just return if the initialization has already been done */ if (modth.initialized) { return; } /* With full OpenMP support (verlet scheme) set the number of threads * per process / default: * - 1 if not compiled with OpenMP or * - OMP_NUM_THREADS if the env. var is set, or * - omp_nthreads_req = #of threads requested by the user on the mdrun * command line, otherwise * - take the max number of available threads and distribute them * on the processes/tMPI threads. * ~ The GMX_*_NUM_THREADS env var overrides the number of threads of * the respective module and it has to be used in conjunction with * OMP_NUM_THREADS. * * With the group scheme OpenMP multithreading is only supported in PME, * for all other modules nthreads is set to 1. * The number of PME threads is equal to: * - 1 if not compiled with OpenMP or * - GMX_PME_NUM_THREADS if defined, otherwise * - OMP_NUM_THREADS if defined, otherwise * - 1 */ nth = 1; if ((env = getenv("OMP_NUM_THREADS")) != NULL) { if (!bOMP && (strncmp(env, "1", 1) != 0)) { gmx_warning("OMP_NUM_THREADS is set, but %s was compiled without OpenMP support!", ShortProgram()); } else { nth = gmx_omp_get_max_threads(); } } else if (omp_nthreads_req > 0) { nth = omp_nthreads_req; } else if (bFullOmpSupport && bOMP) { /* max available threads per node */ nth = nthreads_hw_avail; /* divide the threads among the MPI processes/tMPI threads */ if (nth >= nppn) { nth /= nppn; } else { nth = 1; } } /* now we have the global values, set them: * - 1 if not compiled with OpenMP and for the group scheme * - nth for the verlet scheme when compiled with OpenMP */ if (bFullOmpSupport && bOMP) { modth.gnth = nth; } else { modth.gnth = 1; } if (bSepPME) { if (omp_nthreads_pme_req > 0) { modth.gnth_pme = omp_nthreads_pme_req; } else { modth.gnth_pme = nth; } } else { modth.gnth_pme = 0; } /* now set the per-module values */ modth.nth[emntDefault] = modth.gnth; pick_module_nthreads(fplog, emntDomdec, SIMMASTER(cr), bFullOmpSupport, bSepPME); pick_module_nthreads(fplog, emntPairsearch, SIMMASTER(cr), bFullOmpSupport, bSepPME); pick_module_nthreads(fplog, emntNonbonded, SIMMASTER(cr), bFullOmpSupport, bSepPME); pick_module_nthreads(fplog, emntBonded, SIMMASTER(cr), bFullOmpSupport, bSepPME); pick_module_nthreads(fplog, emntPME, SIMMASTER(cr), bFullOmpSupport, bSepPME); pick_module_nthreads(fplog, emntUpdate, SIMMASTER(cr), bFullOmpSupport, bSepPME); pick_module_nthreads(fplog, emntVSITE, SIMMASTER(cr), bFullOmpSupport, bSepPME); pick_module_nthreads(fplog, emntLINCS, SIMMASTER(cr), bFullOmpSupport, bSepPME); pick_module_nthreads(fplog, emntSETTLE, SIMMASTER(cr), bFullOmpSupport, bSepPME); /* set the number of threads globally */ if (bOMP) { #ifndef GMX_THREAD_MPI if (bThisNodePMEOnly) { gmx_omp_set_num_threads(modth.gnth_pme); } else #endif /* GMX_THREAD_MPI */ { if (bFullOmpSupport) { gmx_omp_set_num_threads(nth); } else { gmx_omp_set_num_threads(1); } } } modth.initialized = TRUE; } #ifdef GMX_THREAD_MPI /* Non-master threads have to wait for the detection to be done. */ if (PAR(cr)) { MPI_Barrier(cr->mpi_comm_mysim); } #endif /* inform the user about the settings */ if (bOMP) { #ifdef GMX_THREAD_MPI const char *mpi_str = "per tMPI thread"; #else const char *mpi_str = "per MPI process"; #endif /* for group scheme we print PME threads info only */ if (bFullOmpSupport) { md_print_info(cr, fplog, "Using %d OpenMP thread%s %s\n", modth.gnth, modth.gnth > 1 ? "s" : "", cr->nnodes > 1 ? mpi_str : ""); } if (bSepPME && modth.gnth_pme != modth.gnth) { md_print_info(cr, fplog, "Using %d OpenMP thread%s %s for PME\n", modth.gnth_pme, modth.gnth_pme > 1 ? "s" : "", cr->nnodes > 1 ? mpi_str : ""); } } /* detect and warn about oversubscription * TODO: enable this for separate PME nodes as well! */ if (!bSepPME && cr->rank_pp_intranode == 0) { char sbuf[STRLEN], sbuf1[STRLEN], sbuf2[STRLEN]; if (modth.gnth*nppn > nthreads_hw_avail) { sprintf(sbuf, "threads"); sbuf1[0] = '\0'; sprintf(sbuf2, "O"); #ifdef GMX_MPI if (modth.gnth == 1) { #ifdef GMX_THREAD_MPI sprintf(sbuf, "thread-MPI threads"); #else sprintf(sbuf, "MPI processes"); sprintf(sbuf1, " per node"); sprintf(sbuf2, "On node %d: o", cr->sim_nodeid); #endif } #endif md_print_warn(cr, fplog, "WARNING: %sversubscribing the available %d logical CPU cores%s with %d %s.\n" " This will cause considerable performance loss!", sbuf2, nthreads_hw_avail, sbuf1, nppn*modth.gnth, sbuf); } } }
/* Check the process affinity mask and if it is found to be non-zero, * will honor it and disable mdrun internal affinity setting. * Note that this will only work on Linux as we use a GNU feature. */ void gmx_check_thread_affinity_set(FILE *fplog, const t_commrec *cr, gmx_hw_opt_t *hw_opt, int ncpus, gmx_bool bAfterOpenmpInit) { #ifdef HAVE_SCHED_GETAFFINITY cpu_set_t mask_current; int i, ret, cpu_count, cpu_set; gmx_bool bAllSet; assert(hw_opt); if (hw_opt->thread_affinity == threadaffOFF) { /* internal affinity setting is off, don't bother checking process affinity */ return; } CPU_ZERO(&mask_current); if ((ret = sched_getaffinity(0, sizeof(cpu_set_t), &mask_current)) != 0) { /* failed to query affinity mask, will just return */ if (debug) { fprintf(debug, "Failed to query affinity mask (error %d)", ret); } return; } /* Before proceeding with the actual check, make sure that the number of * detected CPUs is >= the CPUs in the current set. * We need to check for CPU_COUNT as it was added only in glibc 2.6. */ #ifdef CPU_COUNT if (ncpus < CPU_COUNT(&mask_current)) { if (debug) { fprintf(debug, "%d CPUs detected, but %d was returned by CPU_COUNT", ncpus, CPU_COUNT(&mask_current)); } return; } #endif /* CPU_COUNT */ bAllSet = TRUE; for (i = 0; (i < ncpus && i < CPU_SETSIZE); i++) { bAllSet = bAllSet && (CPU_ISSET(i, &mask_current) != 0); } if (!bAllSet) { if (hw_opt->thread_affinity == threadaffAUTO) { if (!bAfterOpenmpInit) { md_print_warn(cr, fplog, "Non-default thread affinity set, disabling internal thread affinity"); } else { md_print_warn(cr, fplog, "Non-default thread affinity set probably by the OpenMP library,\n" "disabling internal thread affinity"); } hw_opt->thread_affinity = threadaffOFF; } else { /* Only warn once, at the last check (bAfterOpenmpInit==TRUE) */ if (bAfterOpenmpInit) { md_print_warn(cr, fplog, "Overriding thread affinity set outside %s\n", ShortProgram()); } } if (debug) { fprintf(debug, "Non-default affinity mask found\n"); } } else { if (debug) { fprintf(debug, "Default affinity mask found\n"); } } #endif /* HAVE_SCHED_GETAFFINITY */ }
int main(int argc,char *argv[]) { const char *desc[] = { "[TT]do_multiprot[tt] ", "reads a trajectory file and aligns it to a reference structure ", "each time frame", "calling the multiprot program. This allows you to use a reference", "structure whose sequence is different than that of the protein in the ", "trajectory, since the alignment is based on the geometry, not sequence.", "The output of [TT]do_multiprot[tt] includes the rmsd and the number of residues", "on which it was calculated.", "[PAR]", "An aligned trajectory file is generated with the [TT]-ox[tt] option.[PAR]", "With the [TT]-cr[tt] option, the number of hits in the alignment is given", "per residue. This number can be between 0 and the number of frames, and", "indicates the structural conservation of this residue.[PAR]", "If you do not have the [TT]multiprot[tt] program, get it. [TT]do_multiprot[tt] assumes", "that the [TT]multiprot[tt] executable is [TT]/usr/local/bin/multiprot[tt]. If this is ", "not the case, then you should set an environment variable [BB]MULTIPROT[bb]", "pointing to the [TT]multiprot[tt] executable, e.g.: [PAR]", "[TT]setenv MULTIPROT /usr/MultiProtInstall/multiprot.Linux[tt][PAR]", "Note that at the current implementation only binary alignment (your", "molecule to a reference) is supported. In addition, note that the ", "by default [TT]multiprot[tt] aligns the two proteins on their C-alpha carbons.", "and that this depends on the [TT]multiprot[tt] parameters which are not dealt ", "with here. Thus, the C-alpha carbons is expected to give the same " "results as choosing the whole protein and will be slightly faster.[PAR]", "For information about [TT]multiprot[tt], see:", "http://bioinfo3d.cs.tau.ac.il/MultiProt/.[PAR]" }; static bool bVerbose; t_pargs pa[] = { { "-v", FALSE, etBOOL, {&bVerbose}, "HIDDENGenerate miles of useless information" } }; const char *bugs[] = { "The program is very slow, since multiprot is run externally" }; t_trxstatus *status; t_trxstatus *trxout=NULL; FILE *tapein,*fo,*frc,*tmpf,*out=NULL,*fres=NULL; const char *fnRef; const char *fn="2_sol.res"; t_topology top; int ePBC; t_atoms *atoms,ratoms,useatoms; t_trxframe fr; t_pdbinfo p; int nres,nres2,nr0; real t; int i,j,natoms,nratoms,nframe=0,model_nr=-1; int cur_res,prev_res; int nout; t_countres *countres=NULL; matrix box,rbox; int gnx; char *grpnm,*ss_str; atom_id *index; rvec *xp,*x,*xr; char pdbfile[32],refpdb[256],title[256],rtitle[256],filemode[5]; char out_title[256]; char multiprot[256],*mptr; int ftp; int outftp=-1; real rmsd; bool bTrjout,bCountres; const char *TrjoutFile=NULL; output_env_t oenv; static rvec translation={0,0,0},rotangles={0,0,0}; gmx_rmpbc_t gpbc=NULL; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efSTX, "-r", NULL , ffREAD }, { efXVG, "-o", "rmss", ffWRITE }, { efXVG, "-rc", "rescount", ffWRITE}, { efXVG, "-cr", "countres", ffOPTWR}, { efTRX, "-ox", "aligned", ffOPTWR } }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_TIME_UNIT | PCA_BE_NICE , NFILE,fnm, asize(pa),pa, asize(desc),desc, asize(bugs),bugs,&oenv ); fnRef=opt2fn("-r",NFILE,fnm); bTrjout = opt2bSet("-ox",NFILE,fnm); bCountres= opt2bSet("-cr",NFILE,fnm); if (bTrjout) { TrjoutFile = opt2fn_null("-ox",NFILE,fnm); } read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xp,NULL,box,FALSE); gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,box); atoms=&(top.atoms); ftp=fn2ftp(fnRef); get_stx_coordnum(fnRef,&nratoms); init_t_atoms(&ratoms,nratoms,TRUE); snew(xr,nratoms); read_stx_conf(fnRef,rtitle,&ratoms,xr,NULL,&ePBC,rbox); if (bVerbose) { fprintf(stderr,"Read %d atoms\n",atoms->nr); fprintf(stderr,"Read %d reference atoms\n",ratoms.nr); } if (bCountres) { snew(countres,ratoms.nres); j=0; cur_res=0; for (i=0;i<ratoms.nr;i++) { prev_res=cur_res; cur_res=ratoms.atom[i].resind; if (cur_res != prev_res) { countres[j].resnr=cur_res; countres[j].count=0; j++; } } } get_index(atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&gnx,&index,&grpnm); nres=0; nr0=-1; for(i=0; (i<gnx); i++) { if (atoms->atom[index[i]].resind != nr0) { nr0=atoms->atom[index[i]].resind; nres++; } } fprintf(stderr,"There are %d residues in your selected group\n",nres); strcpy(pdbfile,"ddXXXXXX"); gmx_tmpnam(pdbfile); if ((tmpf = fopen(pdbfile,"w")) == NULL) { sprintf(pdbfile,"%ctmp%cfilterXXXXXX",DIR_SEPARATOR,DIR_SEPARATOR); gmx_tmpnam(pdbfile); if ((tmpf = fopen(pdbfile,"w")) == NULL) { gmx_fatal(FARGS,"Can not open tmp file %s",pdbfile); } } else { gmx_ffclose(tmpf); } if (ftp != efPDB) { strcpy(refpdb,"ddXXXXXX"); gmx_tmpnam(refpdb); strcat(refpdb,".pdb"); write_sto_conf(refpdb,rtitle,&ratoms,xr,NULL,ePBC,rbox); } else { strcpy(refpdb,fnRef); } if ((mptr=getenv("MULTIPROT")) == NULL) { mptr="/usr/local/bin/multiprot"; } if (!gmx_fexist(mptr)) { gmx_fatal(FARGS,"MULTIPROT executable (%s) does not exist (use setenv MULTIPROT)", mptr); } sprintf (multiprot,"%s %s %s > /dev/null %s", mptr, refpdb, pdbfile, "2> /dev/null"); if (bVerbose) fprintf(stderr,"multiprot cmd='%s'\n",multiprot); if (!read_first_frame(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&fr,TRX_READ_X)) gmx_fatal(FARGS,"Could not read a frame from %s",ftp2fn(efTRX,NFILE,fnm)); natoms = fr.natoms; if (bTrjout) { nout=natoms; /* open file now */ outftp=fn2ftp(TrjoutFile); if (bVerbose) fprintf(stderr,"Will write %s: %s\n",ftp2ext(ftp),ftp2desc(outftp)); strcpy(filemode,"w"); switch (outftp) { case efXTC: case efG87: case efTRR: case efTRJ: out=NULL; trxout = open_trx(TrjoutFile,filemode); break; case efGRO: case efG96: case efPDB: /* Make atoms struct for output in GRO or PDB files */ /* get memory for stuff to go in pdb file */ init_t_atoms(&useatoms,nout,FALSE); sfree(useatoms.resinfo); useatoms.resinfo=atoms->resinfo; for(i=0;(i<nout);i++) { useatoms.atomname[i]=atoms->atomname[i]; useatoms.atom[i]=atoms->atom[i]; useatoms.nres=max(useatoms.nres,useatoms.atom[i].resind+1); } useatoms.nr=nout; out=gmx_ffopen(TrjoutFile,filemode); break; } if (outftp == efG87) fprintf(gmx_fio_getfp(trx_get_fileio(trxout)),"Generated by %s. #atoms=%d, a BOX is" " stored in this file.\n",ShortProgram(),nout); } if (natoms > atoms->nr) { gmx_fatal(FARGS,"\nTrajectory does not match topology!"); } if (gnx > natoms) { gmx_fatal(FARGS,"\nTrajectory does not match selected group!"); } fo = xvgropen(opt2fn("-o",NFILE,fnm),"RMSD","Time (ps)","RMSD (nm)",oenv); frc = xvgropen(opt2fn("-rc",NFILE,fnm),"Number of Residues in the alignment","Time (ps)","Residues",oenv); do { t = output_env_conv_time(oenv,fr.time); gmx_rmpbc(gpbc,natoms,fr.box,fr.x); tapein=gmx_ffopen(pdbfile,"w"); write_pdbfile_indexed(tapein,NULL,atoms,fr.x,ePBC,fr.box,' ',-1,gnx,index,NULL,TRUE); gmx_ffclose(tapein); system(multiprot); remove(pdbfile); process_multiprot_output(fn, &rmsd, &nres2,rotangles,translation,bCountres,countres); fprintf(fo,"%12.7f",t); fprintf(fo," %12.7f\n",rmsd); fprintf(frc,"%12.7f",t); fprintf(frc,"%12d\n",nres2); if (bTrjout) { rotate_conf(natoms,fr.x,NULL,rotangles[XX],rotangles[YY],rotangles[ZZ]); for(i=0; i<natoms; i++) { rvec_inc(fr.x[i],translation); } switch(outftp) { case efTRJ: case efTRR: case efG87: case efXTC: write_trxframe(trxout,&fr,NULL); break; case efGRO: case efG96: case efPDB: sprintf(out_title,"Generated by do_multiprot : %s t= %g %s", title,output_env_conv_time(oenv,fr.time),output_env_get_time_unit(oenv)); switch(outftp) { case efGRO: write_hconf_p(out,out_title,&useatoms,prec2ndec(fr.prec), fr.x,NULL,fr.box); break; case efPDB: fprintf(out,"REMARK GENERATED BY DO_MULTIPROT\n"); sprintf(out_title,"%s t= %g %s",title,output_env_conv_time(oenv,fr.time),output_env_get_time_unit(oenv)); /* if reading from pdb, we want to keep the original model numbering else we write the output frame number plus one, because model 0 is not allowed in pdb */ if (ftp==efPDB && fr.step > model_nr) { model_nr = fr.step; } else { model_nr++; } write_pdbfile(out,out_title,&useatoms,fr.x,ePBC,fr.box,' ',model_nr,NULL,TRUE); break; case efG96: fr.title = out_title; fr.bTitle = (nframe == 0); fr.bAtoms = FALSE; fr.bStep = TRUE; fr.bTime = TRUE; write_g96_conf(out,&fr,-1,NULL); } break; } } nframe++; } while(read_next_frame(oenv,status,&fr)); if (bCountres) { fres= xvgropen(opt2fn("-cr",NFILE,fnm),"Number of frames in which the residues are aligned to","Residue","Number",oenv); for (i=0;i<ratoms.nres;i++) { fprintf(fres,"%10d %12d\n",countres[i].resnr,countres[i].count); } gmx_ffclose(fres); } gmx_ffclose(fo); gmx_ffclose(frc); fprintf(stderr,"\n"); close_trj(status); if (trxout != NULL) { close_trx(trxout); } else if (out != NULL) { gmx_ffclose(out); } view_all(oenv,NFILE, fnm); sfree(xr); if (bCountres) { sfree(countres); } free_t_atoms(&ratoms,TRUE); if (bTrjout) { if (outftp==efPDB || outftp==efGRO || outftp==efG96) { free_t_atoms(&useatoms,TRUE); } } gmx_thanx(stderr); return 0; }
/*! * Thread affinity set by the OpenMP library can conflict with the GROMACS * internal affinity setting. * * While GNU OpenMP does not set affinity by default, the Intel OpenMP library * does. This conflicts with the internal affinity (especially thread-MPI) * setting, results in incorrectly locked threads, and causes dreadful performance. * * The KMP_AFFINITY environment variable is used by Intel, GOMP_CPU_AFFINITY * by the GNU compilers (Intel also honors it well). If any of the variables * is set, we honor it, disable the internal pinning, and warn the user. * When using Intel OpenMP, we will disable affinity if the user did not set it * anually through one of the aforementioned environment variables. * * Note that the Intel OpenMP affinity disabling iwll only take effect if this * function is called before the OpenMP library gets initialized which happens * when the first call is made into a compilation unit that contains OpenMP * pragmas. */ void gmx_omp_check_thread_affinity(FILE *fplog, const t_commrec *cr, gmx_hw_opt_t *hw_opt) { gmx_bool bKmpAffinitySet, bGompCpuAffinitySet; char *kmp_env, *gomp_env; /* no need to worry if internal thread pinning is turned off */ if (!hw_opt->bThreadPinning) { return; } #if defined(GMX_OPENMP) /* We assume that the affinity setting is available on all platforms * gcc supports. Even if this is not the case (e.g. Mac OS) the user * will only get a warning.*/ bGompCpuAffinitySet = FALSE; gomp_env = NULL; #if defined(__GNUC__) gomp_env = getenv("GOMP_CPU_AFFINITY"); bGompCpuAffinitySet = (gomp_env != NULL); #endif /* __GNUC__ */ bKmpAffinitySet = FALSE; #if defined(__INTEL_COMPILER) kmp_env = getenv("KMP_AFFINITY"); bKmpAffinitySet = (kmp_env != NULL); /* disable Intel OpenMP affinity if neither KMP_AFFINITY nor * GOMP_CPU_AFFINITY is set (Intel uses the GNU env. var as well) */ if (!bKmpAffinitySet && !bGompCpuAffinitySet) { int retval; #ifdef _MSC_VER /* Windows not POSIX */ retval = _putenv_s("KMP_AFFINITY", "disabled"); #else /* POSIX */ retval = setenv("KMP_AFFINITY", "disabled", 0); #endif /* _MSC_VER */ if (debug) { fprintf(debug, "Disabling Intel OpenMP affinity by setting the KMP_AFFINITY=disabled env. var.\n"); } if (retval != 0) { gmx_warning("Disabling Intel OpenMp affinity setting failed!"); } } /* turn off internal pinning KMP_AFFINITY != "disabled" */ if (bKmpAffinitySet && (gmx_strncasecmp(kmp_env, "disabled", 8) != 0)) { md_print_warn(cr, fplog, "WARNING: KMP_AFFINITY set, will turn off %s internal affinity\n" " setting as the two can conflict and cause performance degradation.\n" " To keep using the %s internal affinity setting, set the\n" " KMP_AFFINITY=disabled environment variable.", ShortProgram(), ShortProgram()); hw_opt->bThreadPinning = FALSE; } #endif /* __INTEL_COMPILER */ #if defined(__INTEL_COMPILER) || defined(__GNUC__) /* turn off internal pinning f GOMP_CPU_AFFINITY is set & non-empty */ if (bGompCpuAffinitySet && gomp_env != NULL && gomp_env != '\0') { md_print_warn(cr, fplog, "WARNING: GOMP_CPU_AFFINITY set, will turn off %s internal affinity\n" " setting as the two can conflict and cause performance degradation.\n" " To keep using the %s internal affinity setting, unset the\n" " GOMP_CPU_AFFINITY environment variable.", ShortProgram(), ShortProgram()); hw_opt->bThreadPinning = FALSE; } #endif /* __INTEL_COMPILER || __GNUC__ */ #endif /* GMX_OPENMP */ }