TrajectoryAnalysisModule *createTrajectoryAnalysisModule(const char *name) { size_t len = strlen(name); int match_i = -1; for (int i = 0; modules[i].name != NULL; ++i) { if (gmx_strncasecmp(name, modules[i].name, len) == 0) { if (strlen(modules[i].name) == len) { match_i = i; break; } else if (match_i == -1) { match_i = i; } else { return NULL; } } } if (match_i != -1) { return modules[match_i].creator(); } return NULL; }
static gmx_bool comp_name(char *name, char *search) { while (name[0] != '\0' && search[0] != '\0') { switch (search[0]) { case '?': /* Always matches */ break; case '*': if (search[1] != '\0') { printf("WARNING: Currently '*' is only supported at the end of an expression\n"); return FALSE; } else { return TRUE; } break; default: /* Compare a single character */ if (( bCase && strncmp(name, search, 1)) || (!bCase && gmx_strncasecmp(name, search, 1))) { return FALSE; } } name++; search++; } return (name[0] == '\0' && (search[0] == '\0' || search[0] == '*')); }
static gmx_bool atomname_cmp_nr(const char *anm,t_hack *hack,int *nr) { if (hack->nr == 1) { *nr = 0; return (gmx_strcasecmp(anm,hack->nname) == 0); } else { if (isdigit(anm[strlen(anm)-1])) { *nr = anm[strlen(anm)-1] - '0'; } else { *nr = 0; } if (*nr <= 0 || *nr > hack->nr) { return FALSE; } else { return (strlen(anm) == strlen(hack->nname) + 1 && gmx_strncasecmp(anm,hack->nname,strlen(hack->nname)) == 0); } } }
static void process_pull_dim(char *dim_buf, ivec dim, const t_pull_coord *pcrd) { int ndim, d, nchar; char *ptr, pulldim1[STRLEN]; ptr = dim_buf; ndim = 0; for (d = 0; d < DIM; d++) { if (sscanf(ptr, "%s%n", pulldim1, &nchar) != 1) { gmx_fatal(FARGS, "Less than 3 pull dimensions given in pull_dim: '%s'", dim_buf); } if (gmx_strncasecmp(pulldim1, "N", 1) == 0) { dim[d] = 0; } else if (gmx_strncasecmp(pulldim1, "Y", 1) == 0) { dim[d] = 1; ndim++; } else { gmx_fatal(FARGS, "Please use Y(ES) or N(O) for pull_dim only (not %s)", pulldim1); } ptr += nchar; } if (ndim == 0) { gmx_fatal(FARGS, "All entries in pull dim are N"); } if ((pcrd->eGeom == epullgDIHEDRAL) && (ndim < 3)) { gmx_fatal(FARGS, "Pull geometry dihedral is only useful with pull-dim = Y Y Y"); } if ((pcrd->eGeom == epullgANGLE || pcrd->eGeom == epullgANGLEAXIS ) && (ndim < 2)) { gmx_fatal(FARGS, "Pull geometry %s is only useful with pull-dim = Y for at least 2 dimensions", EPULLGEOM(pcrd->eGeom)); } }
static gmx_bool is_bond(int nnm, t_nm2type nmt[], char *ai, char *aj, real blen) { int i, j; for (i = 0; (i < nnm); i++) { for (j = 0; (j < nmt[i].nbonds); j++) { if ((((gmx_strncasecmp(ai, nmt[i].elem, 1) == 0) && (gmx_strncasecmp(aj, nmt[i].bond[j], 1) == 0)) || ((gmx_strncasecmp(ai, nmt[i].bond[j], 1) == 0) && (gmx_strncasecmp(aj, nmt[i].elem, 1) == 0))) && (fabs(blen-nmt[i].blen[j]) <= 0.1*nmt[i].blen[j])) { return TRUE; } } } return FALSE; }
static int search_str2(int nstr,char **str,char *key) { int i,n; int keylen = strlen(key); /* Linear search */ n=0; while( (n<keylen) && ((key[n]<'0') || (key[n]>'9')) ) n++; for(i=0; (i<nstr); i++) if (gmx_strncasecmp(str[i],key,n)==0) return i; return -1; }
static void process_pull_dim(char *dim_buf, ivec dim) { int ndim, d, nchar, c; char *ptr, pulldim1[STRLEN]; t_pull_coord *pcrd; ptr = dim_buf; ndim = 0; for (d = 0; d < DIM; d++) { if (sscanf(ptr, "%s%n", pulldim1, &nchar) != 1) { gmx_fatal(FARGS, "Less than 3 pull dimensions given in pull_dim: '%s'", dim_buf); } if (gmx_strncasecmp(pulldim1, "N", 1) == 0) { dim[d] = 0; } else if (gmx_strncasecmp(pulldim1, "Y", 1) == 0) { dim[d] = 1; ndim++; } else { gmx_fatal(FARGS, "Please use Y(ES) or N(O) for pull_dim only (not %s)", pulldim1); } ptr += nchar; } if (ndim == 0) { gmx_fatal(FARGS, "All entries in pull dim are N"); } }
static gmx_bool enernm_equal(const char *nm1,const char *nm2) { int len1,len2; len1 = strlen(nm1); len2 = strlen(nm2); /* Remove " (bar)" at the end of a name */ if (len1 > 6 && strcmp(nm1+len1-6," (bar)") == 0) { len1 -= 6; } if (len2 > 6 && strcmp(nm2+len2-6," (bar)") == 0) { len2 -= 6; } return (len1 == len2 && gmx_strncasecmp(nm1,nm2,len1) == 0); }
/* Compares if the strins match except for a sign at the end * of (only) one of the two. */ static int neq_str_sign(const char *a1, const char *a2) { int l1, l2, lm; l1 = (int)strlen(a1); l2 = (int)strlen(a2); lm = std::min(l1, l2); if (lm >= 1 && ((l1 == l2+1 && is_sign(a1[l1-1])) || (l2 == l1+1 && is_sign(a2[l2-1]))) && gmx_strncasecmp(a1, a2, lm) == 0) { return lm; } else { return 0; } }
void read_resall(char *rrdb, int *nrtpptr, t_restp **rtp, gpp_atomtype_t atype, t_symtab *tab, gmx_bool bAllowOverrideRTP) { FILE *in; char filebase[STRLEN], line[STRLEN], header[STRLEN]; int i, nrtp, maxrtp, bt, nparam; int dum1, dum2, dum3; t_restp *rrtp, *header_settings; gmx_bool bNextResidue, bError; int firstrtp; fflib_filename_base(rrdb, filebase, STRLEN); in = fflib_open(rrdb); if (debug) { fprintf(debug, "%9s %5s", "Residue", "atoms"); for (i = 0; i < ebtsNR; i++) { fprintf(debug, " %10s", btsNames[i]); } fprintf(debug, "\n"); } snew(header_settings, 1); /* these bonded parameters will overwritten be when * * there is a [ bondedtypes ] entry in the .rtp file */ header_settings->rb[ebtsBONDS].type = 1; /* normal bonds */ header_settings->rb[ebtsANGLES].type = 1; /* normal angles */ header_settings->rb[ebtsPDIHS].type = 1; /* normal dihedrals */ header_settings->rb[ebtsIDIHS].type = 2; /* normal impropers */ header_settings->rb[ebtsEXCLS].type = 1; /* normal exclusions */ header_settings->rb[ebtsCMAP].type = 1; /* normal cmap torsions */ header_settings->bKeepAllGeneratedDihedrals = FALSE; header_settings->nrexcl = 3; header_settings->bGenerateHH14Interactions = TRUE; header_settings->bRemoveDihedralIfWithImproper = TRUE; /* Column 5 & 6 aren't really bonded types, but we include * them here to avoid introducing a new section: * Column 5 : This controls the generation of dihedrals from the bonding. * All possible dihedrals are generated automatically. A value of * 1 here means that all these are retained. A value of * 0 here requires generated dihedrals be removed if * * there are any dihedrals on the same central atoms * specified in the residue topology, or * * there are other identical generated dihedrals * sharing the same central atoms, or * * there are other generated dihedrals sharing the * same central bond that have fewer hydrogen atoms * Column 6: Number of bonded neighbors to exclude. * Column 7: Generate 1,4 interactions between two hydrogen atoms * Column 8: Remove proper dihedrals if centered on the same bond * as an improper dihedral */ get_a_line(in, line, STRLEN); if (!get_header(line, header)) { gmx_fatal(FARGS, "in .rtp file at line:\n%s\n", line); } if (gmx_strncasecmp("bondedtypes", header, 5) == 0) { get_a_line(in, line, STRLEN); if ((nparam = sscanf(line, "%d %d %d %d %d %d %d %d", &header_settings->rb[ebtsBONDS].type, &header_settings->rb[ebtsANGLES].type, &header_settings->rb[ebtsPDIHS].type, &header_settings->rb[ebtsIDIHS].type, &dum1, &header_settings->nrexcl, &dum2, &dum3)) < 4) { gmx_fatal(FARGS, "need 4 to 8 parameters in the header of .rtp file %s at line:\n%s\n", rrdb, line); } header_settings->bKeepAllGeneratedDihedrals = (dum1 != 0); header_settings->bGenerateHH14Interactions = (dum2 != 0); header_settings->bRemoveDihedralIfWithImproper = (dum3 != 0); get_a_line(in, line, STRLEN); if (nparam < 5) { fprintf(stderr, "Using default: not generating all possible dihedrals\n"); header_settings->bKeepAllGeneratedDihedrals = FALSE; } if (nparam < 6) { fprintf(stderr, "Using default: excluding 3 bonded neighbors\n"); header_settings->nrexcl = 3; } if (nparam < 7) { fprintf(stderr, "Using default: generating 1,4 H--H interactions\n"); header_settings->bGenerateHH14Interactions = TRUE; } if (nparam < 8) { fprintf(stderr, "Using default: removing proper dihedrals found on the same bond as a proper dihedral\n"); header_settings->bRemoveDihedralIfWithImproper = TRUE; } } else { fprintf(stderr, "Reading .rtp file without '[ bondedtypes ]' directive,\n" "Will proceed as if the entry was:\n"); print_resall_header(stderr, header_settings); } /* We don't know the current size of rrtp, but simply realloc immediately */ nrtp = *nrtpptr; rrtp = *rtp; maxrtp = nrtp; while (!feof(in)) { if (nrtp >= maxrtp) { maxrtp += 100; srenew(rrtp, maxrtp); } /* Initialise rtp entry structure */ rrtp[nrtp] = *header_settings; if (!get_header(line, header)) { gmx_fatal(FARGS, "in .rtp file at line:\n%s\n", line); } rrtp[nrtp].resname = gmx_strdup(header); rrtp[nrtp].filebase = gmx_strdup(filebase); get_a_line(in, line, STRLEN); bError = FALSE; bNextResidue = FALSE; do { if (!get_header(line, header)) { bError = TRUE; } else { bt = get_bt(header); if (bt != NOTSET) { /* header is an bonded directive */ bError = !read_bondeds(bt, in, line, &rrtp[nrtp]); } else if (gmx_strncasecmp("atoms", header, 5) == 0) { /* header is the atoms directive */ bError = !read_atoms(in, line, &(rrtp[nrtp]), tab, atype); } else { /* else header must be a residue name */ bNextResidue = TRUE; } } if (bError) { gmx_fatal(FARGS, "in .rtp file in residue %s at line:\n%s\n", rrtp[nrtp].resname, line); } } while (!feof(in) && !bNextResidue); if (rrtp[nrtp].natom == 0) { gmx_fatal(FARGS, "No atoms found in .rtp file in residue %s\n", rrtp[nrtp].resname); } if (debug) { fprintf(debug, "%3d %5s %5d", nrtp+1, rrtp[nrtp].resname, rrtp[nrtp].natom); for (i = 0; i < ebtsNR; i++) { fprintf(debug, " %10d", rrtp[nrtp].rb[i].nb); } fprintf(debug, "\n"); } firstrtp = -1; for (i = 0; i < nrtp; i++) { if (gmx_strcasecmp(rrtp[i].resname, rrtp[nrtp].resname) == 0) { firstrtp = i; } } if (firstrtp == -1) { nrtp++; fprintf(stderr, "\rResidue %d", nrtp); fflush(stderr); } else { if (firstrtp >= *nrtpptr) { gmx_fatal(FARGS, "Found a second entry for '%s' in '%s'", rrtp[nrtp].resname, rrdb); } if (bAllowOverrideRTP) { fprintf(stderr, "\n"); fprintf(stderr, "Found another rtp entry for '%s' in '%s', ignoring this entry and keeping the one from '%s.rtp'\n", rrtp[nrtp].resname, rrdb, rrtp[firstrtp].filebase); /* We should free all the data for this entry. * The current code gives a lot of dangling pointers. */ clear_t_restp(&rrtp[nrtp]); } else { gmx_fatal(FARGS, "Found rtp entries for '%s' in both '%s' and '%s'. If you want the first definition to override the second one, set the -rtpo option of pdb2gmx.", rrtp[nrtp].resname, rrtp[firstrtp].filebase, rrdb); } } } gmx_ffclose(in); /* give back unused memory */ srenew(rrtp, nrtp); fprintf(stderr, "\nSorting it all out...\n"); qsort(rrtp, nrtp, (size_t)sizeof(rrtp[0]), comprtp); check_rtp(nrtp, rrtp, rrdb); *nrtpptr = nrtp; *rtp = rrtp; }
int gmx_fprintf_pdb_atomline(FILE * fp, enum PDB_record record, int atom_seq_number, const char * atom_name, char alternate_location, const char * res_name, char chain_id, int res_seq_number, char res_insertion_code, real x, real y, real z, real occupancy, real b_factor, const char * element) { char tmp_atomname[6], tmp_resname[6]; gmx_bool start_name_in_col13; int n; if (record != epdbATOM && record != epdbHETATM) { gmx_fatal(FARGS, "Can only print PDB atom lines as ATOM or HETATM records"); } /* Format atom name */ if (atom_name != NULL) { /* If the atom name is an element name with two chars, it should start already in column 13. * Otherwise it should start in column 14, unless the name length is 4 chars. */ if ( (element != NULL) && (std::strlen(element) >= 2) && (gmx_strncasecmp(atom_name, element, 2) == 0) ) { start_name_in_col13 = TRUE; } else { start_name_in_col13 = (std::strlen(atom_name) >= 4); } sprintf(tmp_atomname, start_name_in_col13 ? "" : " "); std::strncat(tmp_atomname, atom_name, 4); tmp_atomname[5] = '\0'; } else { tmp_atomname[0] = '\0'; } /* Format residue name */ std::strncpy(tmp_resname, (res_name != NULL) ? res_name : "", 4); /* Make sure the string is terminated if strlen was > 4 */ tmp_resname[4] = '\0'; /* String is properly terminated, so now we can use strcat. By adding a * space we can write it right-justified, and if the original name was * three characters or less there will be a space added on the right side. */ std::strcat(tmp_resname, " "); /* Truncate integers so they fit */ atom_seq_number = atom_seq_number % 100000; res_seq_number = res_seq_number % 10000; n = fprintf(fp, "%-6s%5d %-4.4s%c%4.4s%c%4d%c %8.3f%8.3f%8.3f%6.2f%6.2f %2s\n", pdbtp[record], atom_seq_number, tmp_atomname, alternate_location, tmp_resname, chain_id, res_seq_number, res_insertion_code, x, y, z, occupancy, b_factor, (element != NULL) ? element : ""); return n; }
gmx_bool gmx_omp_check_thread_affinity(char **message) { bool shouldSetAffinity = true; *message = NULL; #ifdef 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. */ #if defined(__GNUC__) || defined(__INTEL_COMPILER) const char *programName; try { programName = gmx::getProgramContext().displayName(); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; const char *const gomp_env = getenv("GOMP_CPU_AFFINITY"); const bool bGompCpuAffinitySet = (gomp_env != NULL); /* turn off internal pinning if GOMP_CPU_AFFINITY is set & non-empty */ if (bGompCpuAffinitySet && *gomp_env != '\0') { try { std::string buf = gmx::formatString( "NOTE: 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.", programName, programName); *message = gmx_strdup(buf.c_str()); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; shouldSetAffinity = false; } #endif /* __GNUC__ || __INTEL_COMPILER */ #if defined(__INTEL_COMPILER) const char *const kmp_env = getenv("KMP_AFFINITY"); const bool 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)) { try { std::string buf = gmx::formatString( "NOTE: 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.", programName, programName); *message = gmx_strdup(buf.c_str()); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; shouldSetAffinity = false; } #endif /* __INTEL_COMPILER */ #endif /* GMX_OPENMP */ return shouldSetAffinity; }
/* Read a number of arguments from the command line. * For etINT, etREAL and etCHAR an extra argument is read (when present) * for etBOOL the gmx_boolean option is changed to the negate value */ static void get_pargs(int *argc, char *argv[], int nparg, t_pargs pa[]) { int i, j, k, match; gmx_bool *bKeep; char buf[32]; char *ptr; snew(bKeep, *argc+1); bKeep[0] = TRUE; bKeep[*argc] = TRUE; for (i = 1; (i < *argc); i++) { bKeep[i] = TRUE; for (j = 0; (j < nparg); j++) { if (pa[j].type == etBOOL) { sprintf(buf, "-no%s", pa[j].option+1); if (strcmp(pa[j].option, argv[i]) == 0) { *pa[j].u.b = TRUE; pa[j].bSet = TRUE; bKeep[i] = FALSE; } else if (strcmp(buf, argv[i]) == 0) { *pa[j].u.b = FALSE; pa[j].bSet = TRUE; bKeep[i] = FALSE; } } else if (strcmp(pa[j].option, argv[i]) == 0) { if (pa[j].bSet) { fprintf(stderr, "Setting option %s more than once!\n", pa[j].option); } pa[j].bSet = TRUE; bKeep[i] = FALSE; switch (pa[j].type) { case etINT: *pa[j].u.i = iscan(*argc, argv, &i); break; case etINT64: *pa[j].u.is = istepscan(*argc, argv, &i); break; case etTIME: case etREAL: *pa[j].u.r = dscan(*argc, argv, &i); break; case etSTR: *(pa[j].u.c) = sscan(*argc, argv, &i); break; case etENUM: match = -1; ptr = sscan(*argc, argv, &i); for (k = 1; (pa[j].u.c[k] != NULL); k++) { /* only check ptr against beginning of pa[j].u.c[k] */ if (gmx_strncasecmp(ptr, pa[j].u.c[k], strlen(ptr)) == 0) { if ( ( match == -1 ) || ( strlen(pa[j].u.c[k]) < strlen(pa[j].u.c[match]) ) ) { match = k; } } } if (match != -1) { pa[j].u.c[0] = pa[j].u.c[match]; } else { gmx_fatal(FARGS, "Invalid argument %s for option %s", ptr, pa[j].option); } break; case etRVEC: (*pa[j].u.rv)[0] = dscan(*argc, argv, &i); if ( (i+1 == *argc) || ( (argv[i+1][0] == '-') && !isdigit(argv[i+1][1]) ) ) { (*pa[j].u.rv)[1] = (*pa[j].u.rv)[2] = (*pa[j].u.rv)[0]; } else { bKeep[i] = FALSE; (*pa[j].u.rv)[1] = dscan(*argc, argv, &i); if ( (i+1 == *argc) || ( (argv[i+1][0] == '-') && !isdigit(argv[i+1][1]) ) ) { gmx_fatal(FARGS, "%s: vector must have 1 or 3 real parameters", pa[j].option); } bKeep[i] = FALSE; (*pa[j].u.rv)[2] = dscan(*argc, argv, &i); } break; default: gmx_fatal(FARGS, "Invalid type %d in pargs", pa[j].type); } /* i may be incremented, so set it to not keep */ bKeep[i] = FALSE; } } } /* Remove used entries */ for (i = j = 0; (i <= *argc); i++) { if (bKeep[i]) { argv[j++] = argv[i]; } } (*argc) = j-1; sfree(bKeep); }
void make_pull_coords(t_pull *pull) { int ndim, d, nchar, c; char *ptr, pulldim1[STRLEN]; t_pull_coord *pcrd; ptr = pulldim; ndim = 0; for (d = 0; d < DIM; d++) { if (sscanf(ptr, "%s%n", pulldim1, &nchar) != 1) { gmx_fatal(FARGS, "Less than 3 pull dimensions given in pull_dim: '%s'", pulldim); } if (gmx_strncasecmp(pulldim1, "N", 1) == 0) { pull->dim[d] = 0; } else if (gmx_strncasecmp(pulldim1, "Y", 1) == 0) { pull->dim[d] = 1; ndim++; } else { gmx_fatal(FARGS, "Please use Y(ES) or N(O) for pull_dim only (not %s)", pulldim1); } ptr += nchar; } if (ndim == 0) { gmx_fatal(FARGS, "All entries in pull_dim are N"); } for (c = 0; c < pull->ncoord; c++) { pcrd = &pull->coord[c]; if (pcrd->group[0] < 0 || pcrd->group[0] >= pull->ngroup || pcrd->group[1] < 0 || pcrd->group[1] >= pull->ngroup) { gmx_fatal(FARGS, "Pull group index in pull-coord%d-groups out of range, should be between %d and %d", c+1, 0, pull->ngroup+1); } if (pcrd->group[0] == pcrd->group[1]) { gmx_fatal(FARGS, "Identical pull group indices in pull-coord%d-groups", c+1); } if (pull->eGeom == epullgCYL && pcrd->group[0] != 1) { gmx_fatal(FARGS, "With pull geometry %s, the first pull group should always be 1", EPULLGEOM(pull->eGeom)); } if (pull->eGeom != epullgDIST) { for (d = 0; d < DIM; d++) { if (pcrd->vec[d] != 0 && pull->dim[d] == 0) { gmx_fatal(FARGS, "ERROR: pull-group%d-vec has non-zero %c-component while pull_dim for the %c-dimension is N\n", c+1, 'x'+d, 'x'+d); } } } if ((pull->eGeom == epullgDIR || pull->eGeom == epullgCYL) && norm2(pcrd->vec) == 0) { gmx_fatal(FARGS, "pull-group%d-vec can not be zero with geometry %s", c+1, EPULLGEOM(pull->eGeom)); } } }
void read_resall(char *rrdb, int *nrtpptr, t_restp **rtp, gpp_atomtype_t atype, t_symtab *tab, gmx_bool bAllowOverrideRTP) { FILE *in; char filebase[STRLEN],*ptr,line[STRLEN],header[STRLEN]; int i,nrtp,maxrtp,bt,nparam; int dum1,dum2,dum3; t_restp *rrtp; gmx_bool bNextResidue,bError; int bts[ebtsNR]; gmx_bool bAlldih; int nrexcl; gmx_bool HH14; gmx_bool bRemoveDih; int firstrtp; fflib_filename_base(rrdb,filebase,STRLEN); in = fflib_open(rrdb); if (debug) { fprintf(debug,"%9s %5s", "Residue", "atoms"); for(i=0; i<ebtsNR; i++) fprintf(debug," %10s",btsNames[i]); fprintf(debug,"\n"); } /* these bonded parameters will overwritten be when * * there is a [ bondedtypes ] entry in the .rtp file */ bts[ebtsBONDS] = 1; /* normal bonds */ bts[ebtsANGLES] = 1; /* normal angles */ bts[ebtsPDIHS] = 1; /* normal dihedrals */ bts[ebtsIDIHS] = 2; /* normal impropers */ bts[ebtsEXCLS] = 1; /* normal exclusions */ bts[ebtsCMAP] = 1; /* normal cmap torsions */ bAlldih = FALSE; nrexcl = 3; HH14 = TRUE; bRemoveDih = TRUE; /* Column 5 & 6 aren't really bonded types, but we include * them here to avoid introducing a new section: * Column 5: 1 means generate all dihedrals, 0 not. * Column 6: Number of bonded neighbors to exclude. * Coulmn 7: Generate 1,4 interactions between pairs of hydrogens * Column 8: Remove impropers over the same bond as a proper dihedral */ get_a_line(in,line,STRLEN); if (!get_header(line,header)) gmx_fatal(FARGS,"in .rtp file at line:\n%s\n",line); if (gmx_strncasecmp("bondedtypes",header,5)==0) { get_a_line(in,line,STRLEN); if ((nparam=sscanf(line,"%d %d %d %d %d %d %d %d", &bts[ebtsBONDS],&bts[ebtsANGLES], &bts[ebtsPDIHS],&bts[ebtsIDIHS], &dum1,&nrexcl,&dum2,&dum3)) < 4 ) { gmx_fatal(FARGS,"need at least 4 (up to 8) parameters in .rtp file at line:\n%s\n",line); } bAlldih = (dum1 != 0); HH14 = (dum2 != 0); bRemoveDih = (dum3 != 0); get_a_line(in,line,STRLEN); if(nparam<5) { fprintf(stderr,"Using default: not generating all possible dihedrals\n"); bAlldih = FALSE; } if(nparam<6) { fprintf(stderr,"Using default: excluding 3 bonded neighbors\n"); nrexcl = 3; } if(nparam<7) { fprintf(stderr,"Using default: generating 1,4 H--H interactions\n"); HH14 = TRUE; } if(nparam<8) { fprintf(stderr,"Using default: removing impropers on same bond as a proper\n"); bRemoveDih = TRUE; } } else { fprintf(stderr, "Reading .rtp file without '[ bondedtypes ]' directive,\n" "Will proceed as if the entry\n" "\n" "\n[ bondedtypes ]" "\n; bonds angles dihedrals impropers all_dihedrals nr_exclusions HH14 remove_dih" "\n %3d %3d %3d %3d %3d %3d %3d %3d" "\n" "was present at the beginning of %s", bts[0],bts[1],bts[2],bts[3], bAlldih ? 1 : 0,nrexcl,HH14,bRemoveDih,rrdb); } /* We don't know the current size of rrtp, but simply realloc immediately */ nrtp = *nrtpptr; rrtp = *rtp; maxrtp = nrtp; while (!feof(in)) { if (nrtp >= maxrtp) { maxrtp+=100; srenew(rrtp,maxrtp); } clear_t_restp(&rrtp[nrtp]); if (!get_header(line,header)) gmx_fatal(FARGS,"in .rtp file at line:\n%s\n",line); rrtp[nrtp].resname = strdup(header); rrtp[nrtp].filebase = strdup(filebase); /* Set the bonded types */ rrtp[nrtp].bAlldih = bAlldih; rrtp[nrtp].nrexcl = nrexcl; rrtp[nrtp].HH14 = HH14; rrtp[nrtp].bRemoveDih = bRemoveDih; for(i=0; i<ebtsNR; i++) { rrtp[nrtp].rb[i].type = bts[i]; } get_a_line(in,line,STRLEN); bError=FALSE; bNextResidue=FALSE; do { if (!get_header(line,header)) { bError = TRUE; } else { bt = get_bt(header); if (bt != NOTSET) { /* header is an bonded directive */ bError = !read_bondeds(bt,in,line,&rrtp[nrtp]); } else if (gmx_strncasecmp("atoms",header,5) == 0) { /* header is the atoms directive */ bError = !read_atoms(in,line,&(rrtp[nrtp]),tab,atype); } else { /* else header must be a residue name */ bNextResidue = TRUE; } } if (bError) gmx_fatal(FARGS,"in .rtp file in residue %s at line:\n%s\n", rrtp[nrtp].resname,line); } while (!feof(in) && !bNextResidue); if (rrtp[nrtp].natom == 0) gmx_fatal(FARGS,"No atoms found in .rtp file in residue %s\n", rrtp[nrtp].resname); if (debug) { fprintf(debug,"%3d %5s %5d", nrtp+1,rrtp[nrtp].resname,rrtp[nrtp].natom); for(i=0; i<ebtsNR; i++) fprintf(debug," %10d",rrtp[nrtp].rb[i].nb); fprintf(debug,"\n"); } firstrtp = -1; for(i=0; i<nrtp; i++) { if (gmx_strcasecmp(rrtp[i].resname,rrtp[nrtp].resname) == 0) { firstrtp = i; } } if (firstrtp == -1) { nrtp++; fprintf(stderr,"\rResidue %d",nrtp); } else { if (firstrtp >= *nrtpptr) { gmx_fatal(FARGS,"Found a second entry for '%s' in '%s'", rrtp[nrtp].resname,rrdb); } if (bAllowOverrideRTP) { fprintf(stderr,"\n"); fprintf(stderr,"Found another rtp entry for '%s' in '%s', ignoring this entry and keeping the one from '%s.rtp'\n", rrtp[nrtp].resname,rrdb,rrtp[firstrtp].filebase); /* We should free all the data for this entry. * The current code gives a lot of dangling pointers. */ clear_t_restp(&rrtp[nrtp]); } else { gmx_fatal(FARGS,"Found rtp entries for '%s' in both '%s' and '%s'. If you want the first definition to override the second one, set the -rtpo option of pdb2gmx.",rrtp[nrtp].resname,rrtp[firstrtp].filebase,rrdb); } } } ffclose(in); /* give back unused memory */ srenew(rrtp,nrtp); fprintf(stderr,"\nSorting it all out...\n"); qsort(rrtp,nrtp,(size_t)sizeof(rrtp[0]),comprtp); check_rtp(nrtp,rrtp,rrdb); *nrtpptr = nrtp; *rtp = rrtp; }
static gmx_bool calc_vsite3out_param(gpp_atomtype_t atype, t_param *param, t_atoms *at, int nrbond, t_mybonded *bonds, int nrang, t_mybonded *angles) { /* i = virtual site | ,k * j = 1st bonded heavy atom | i-j * k,l = 2nd bonded atoms | `l * NOTE: i is out of the j-k-l plane! */ gmx_bool bXH3,bError,bSwapParity; real bij,bjk,bjl,aijk,aijl,akjl,pijk,pijl,a,b,c; /* check if this is part of a NH2-umbrella, NH3 or CH3 group, * i.e. if atom k and l are dummy masses (MNH* or MCH3*) */ if (debug) { int i; for (i=0; i<4; i++) fprintf(debug,"atom %u type %s ", param->a[i]+1,get_atomtype_name(at->atom[param->a[i]].type,atype)); fprintf(debug,"\n"); } bXH3 = ( (gmx_strncasecmp(get_atomtype_name(at->atom[param->AK].type,atype),"MNH",3)==0) && (gmx_strncasecmp(get_atomtype_name(at->atom[param->AL].type,atype),"MNH",3)==0) ) || ( (gmx_strncasecmp(get_atomtype_name(at->atom[param->AK].type,atype),"MCH3",4)==0) && (gmx_strncasecmp(get_atomtype_name(at->atom[param->AL].type,atype),"MCH3",4)==0) ); /* check if construction parity must be swapped */ bSwapParity = ( param->C1 == -1 ); bjk = get_bond_length(nrbond, bonds, param->AJ, param->AK); bjl = get_bond_length(nrbond, bonds, param->AJ, param->AL); bError = (bjk==NOTSET) || (bjl==NOTSET); if (bXH3) { /* now we get some XH3 group specific construction */ /* note: we call the heavy atom 'C' and the X atom 'N' */ real bMM,bCM,bCN,bNH,aCNH,dH,rH,rHx,rHy,dM,rM; int aN; /* check if bonds from heavy atom (j) to dummy masses (k,l) are equal: */ bError = bError || (bjk!=bjl); /* the X atom (C or N) in the XH3 group is the first after the masses: */ aN = max(param->AK,param->AL)+1; /* get all bondlengths and angles: */ bMM = get_bond_length(nrbond, bonds, param->AK, param->AL); bCM = bjk; bCN = get_bond_length(nrbond, bonds, param->AJ, aN); bNH = get_bond_length(nrbond, bonds, aN, param->AI); aCNH= get_angle (nrang, angles, param->AJ, aN, param->AI); bError = bError || (bMM==NOTSET) || (bCN==NOTSET) || (bNH==NOTSET) || (aCNH==NOTSET); /* calculate */ dH = bCN - bNH * cos(aCNH); rH = bNH * sin(aCNH); /* we assume the H's are symmetrically distributed */ rHx = rH*cos(DEG2RAD*30); rHy = rH*sin(DEG2RAD*30); rM = 0.5*bMM; dM = sqrt( sqr(bCM) - sqr(rM) ); a = 0.5*( (dH/dM) - (rHy/rM) ); b = 0.5*( (dH/dM) + (rHy/rM) ); c = rHx / (2*dM*rM); } else { /* this is the general construction */ bij = get_bond_length(nrbond, bonds, param->AI, param->AJ); aijk= get_angle (nrang, angles, param->AI, param->AJ, param->AK); aijl= get_angle (nrang, angles, param->AI, param->AJ, param->AL); akjl= get_angle (nrang, angles, param->AK, param->AJ, param->AL); bError = bError || (bij==NOTSET) || (aijk==NOTSET) || (aijl==NOTSET) || (akjl==NOTSET); pijk = cos(aijk)*bij; pijl = cos(aijl)*bij; a = ( pijk + (pijk*cos(akjl)-pijl) * cos(akjl) / sqr(sin(akjl)) ) / bjk; b = ( pijl + (pijl*cos(akjl)-pijk) * cos(akjl) / sqr(sin(akjl)) ) / bjl; c = - sqrt( sqr(bij) - ( sqr(pijk) - 2*pijk*pijl*cos(akjl) + sqr(pijl) ) / sqr(sin(akjl)) ) / ( bjk*bjl*sin(akjl) ); } param->C0 = a; param->C1 = b; if (bSwapParity) param->C2 = -c; else param->C2 = c; if (debug) fprintf(debug,"params for vsite3out %u: %g %g %g\n", param->AI+1,param->C0,param->C1,param->C2); return bError; }
static gmx_bool calc_vsite3_param(gpp_atomtype_t atype, t_param *param, t_atoms *at, int nrbond, t_mybonded *bonds, int nrang, t_mybonded *angles ) { /* i = virtual site | ,k * j = 1st bonded heavy atom | i-j * k,l = 2nd bonded atoms | `l */ gmx_bool bXH3,bError; real bjk,bjl,a=-1,b=-1; /* check if this is part of a NH3 , NH2-umbrella or CH3 group, * i.e. if atom k and l are dummy masses (MNH* or MCH3*) */ if (debug) { int i; for (i=0; i<4; i++) fprintf(debug,"atom %u type %s ", param->a[i]+1, get_atomtype_name(at->atom[param->a[i]].type,atype)); fprintf(debug,"\n"); } bXH3 = ( (gmx_strncasecmp(get_atomtype_name(at->atom[param->AK].type,atype),"MNH",3)==0) && (gmx_strncasecmp(get_atomtype_name(at->atom[param->AL].type,atype),"MNH",3)==0) ) || ( (gmx_strncasecmp(get_atomtype_name(at->atom[param->AK].type,atype),"MCH3",4)==0) && (gmx_strncasecmp(get_atomtype_name(at->atom[param->AL].type,atype),"MCH3",4)==0) ); bjk = get_bond_length(nrbond, bonds, param->AJ, param->AK); bjl = get_bond_length(nrbond, bonds, param->AJ, param->AL); bError = (bjk==NOTSET) || (bjl==NOTSET); if (bXH3) { /* now we get some XH2/XH3 group specific construction */ /* note: we call the heavy atom 'C' and the X atom 'N' */ real bMM,bCM,bCN,bNH,aCNH,dH,rH,dM,rM; int aN; /* check if bonds from heavy atom (j) to dummy masses (k,l) are equal: */ bError = bError || (bjk!=bjl); /* the X atom (C or N) in the XH2/XH3 group is the first after the masses: */ aN = max(param->AK,param->AL)+1; /* get common bonds */ bMM = get_bond_length(nrbond, bonds, param->AK, param->AL); bCM = bjk; bCN = get_bond_length(nrbond, bonds, param->AJ, aN); bError = bError || (bMM==NOTSET) || (bCN==NOTSET); /* calculate common things */ rM = 0.5*bMM; dM = sqrt( sqr(bCM) - sqr(rM) ); /* are we dealing with the X atom? */ if ( param->AI == aN ) { /* this is trivial */ a = b = 0.5 * bCN/dM; } else { /* get other bondlengths and angles: */ bNH = get_bond_length(nrbond, bonds, aN, param->AI); aCNH= get_angle (nrang, angles, param->AJ, aN, param->AI); bError = bError || (bNH==NOTSET) || (aCNH==NOTSET); /* calculate */ dH = bCN - bNH * cos(aCNH); rH = bNH * sin(aCNH); a = 0.5 * ( dH/dM + rH/rM ); b = 0.5 * ( dH/dM - rH/rM ); } } else gmx_fatal(FARGS,"calc_vsite3_param not implemented for the general case " "(atom %d)",param->AI+1); param->C0 = a; param->C1 = b; if (debug) fprintf(debug,"params for vsite3 %u: %g %g\n", param->AI+1,param->C0,param->C1); return bError; }
static void analyse_prot(const char ** restype, t_atoms *atoms, t_blocka *gb, char ***gn, gmx_bool bASK, gmx_bool bVerb) { /* lists of atomnames to be used in constructing index groups: */ static const char *pnoh[] = { "H", "HN" }; static const char *pnodum[] = { "MN1", "MN2", "MCB1", "MCB2", "MCG1", "MCG2", "MCD1", "MCD2", "MCE1", "MCE2", "MNZ1", "MNZ2" }; static const char *calpha[] = { "CA" }; static const char *bb[] = { "N", "CA", "C" }; static const char *mc[] = { "N", "CA", "C", "O", "O1", "O2", "OC1", "OC2", "OT", "OXT" }; static const char *mcb[] = { "N", "CA", "CB", "C", "O", "O1", "O2", "OC1", "OC2", "OT", "OXT" }; static const char *mch[] = { "N", "CA", "C", "O", "O1", "O2", "OC1", "OC2", "OT", "OXT", "H1", "H2", "H3", "H", "HN" }; static const t_gmx_help_make_index_group constructing_data[] = {{ NULL, 0, "Protein", TRUE, -1, -1}, { pnoh, asize(pnoh), "Protein-H", TRUE, 0, -1}, { calpha, asize(calpha), "C-alpha", FALSE, -1, -1}, { bb, asize(bb), "Backbone", FALSE, -1, -1}, { mc, asize(mc), "MainChain", FALSE, -1, -1}, { mcb, asize(mcb), "MainChain+Cb", FALSE, -1, -1}, { mch, asize(mch), "MainChain+H", FALSE, -1, -1}, { mch, asize(mch), "SideChain", TRUE, -1, -1}, { mch, asize(mch), "SideChain-H", TRUE, 11, -1}, { pnodum, asize(pnodum), "Prot-Masses", TRUE, -1, 0}, }; const int num_index_groups = asize(constructing_data); int n, j; atom_id *aid; int nra, nnpres, npres; gmx_bool match; char ndx_name[STRLEN], *atnm; int i; if (bVerb) { printf("Analysing Protein...\n"); } snew(aid, atoms->nr); /* calculate the number of protein residues */ npres = 0; for (i = 0; (i < atoms->nres); i++) { if (0 == gmx_strcasecmp(restype[i], "Protein")) { npres++; } } /* find matching or complement atoms */ for (i = 0; (i < (int)num_index_groups); i++) { nra = 0; for (n = 0; (n < atoms->nr); n++) { if (0 == gmx_strcasecmp(restype[atoms->atom[n].resind], "Protein")) { match = FALSE; for (j = 0; (j < constructing_data[i].num_defining_atomnames); j++) { /* skip digits at beginning of atomname, e.g. 1H */ atnm = *atoms->atomname[n]; while (isdigit(atnm[0])) { atnm++; } if ( (constructing_data[i].wholename == -1) || (j < constructing_data[i].wholename) ) { if (0 == gmx_strcasecmp(constructing_data[i].defining_atomnames[j], atnm)) { match = TRUE; } } else { if (0 == gmx_strncasecmp(constructing_data[i].defining_atomnames[j], atnm, strlen(constructing_data[i].defining_atomnames[j]))) { match = TRUE; } } } if (constructing_data[i].bTakeComplement != match) { aid[nra++] = n; } } } /* if we want to add this group always or it differs from previous group, add it: */ if (-1 == constructing_data[i].compareto || !grp_cmp(gb, nra, aid, constructing_data[i].compareto-i) ) { add_grp(gb, gn, nra, aid, constructing_data[i].group_name); } } if (bASK) { for (i = 0; (i < (int)num_index_groups); i++) { printf("Split %12s into %5d residues (y/n) ? ", constructing_data[i].group_name, npres); if (gmx_ask_yesno(bASK)) { int resind; nra = 0; for (n = 0; ((atoms->atom[n].resind < npres) && (n < atoms->nr)); ) { resind = atoms->atom[n].resind; for (; ((atoms->atom[n].resind == resind) && (n < atoms->nr)); n++) { match = FALSE; for (j = 0; (j < constructing_data[i].num_defining_atomnames); j++) { if (0 == gmx_strcasecmp(constructing_data[i].defining_atomnames[j], *atoms->atomname[n])) { match = TRUE; } } if (constructing_data[i].bTakeComplement != match) { aid[nra++] = n; } } /* copy the residuename to the tail of the groupname */ if (nra > 0) { t_resinfo *ri; ri = &atoms->resinfo[resind]; sprintf(ndx_name, "%s_%s%d%c", constructing_data[i].group_name, *ri->name, ri->nr, ri->ic == ' ' ? '\0' : ri->ic); add_grp(gb, gn, nra, aid, ndx_name); nra = 0; } } } } printf("Make group with sidechain and C=O swapped (y/n) ? "); if (gmx_ask_yesno(bASK)) { /* Make swap sidechain C=O index */ int resind, hold; nra = 0; for (n = 0; ((atoms->atom[n].resind < npres) && (n < atoms->nr)); ) { resind = atoms->atom[n].resind; hold = -1; for (; ((atoms->atom[n].resind == resind) && (n < atoms->nr)); n++) { if (strcmp("CA", *atoms->atomname[n]) == 0) { aid[nra++] = n; hold = nra; nra += 2; } else if (strcmp("C", *atoms->atomname[n]) == 0) { if (hold == -1) { gmx_incons("Atom naming problem"); } aid[hold] = n; } else if (strcmp("O", *atoms->atomname[n]) == 0) { if (hold == -1) { gmx_incons("Atom naming problem"); } aid[hold+1] = n; } else if (strcmp("O1", *atoms->atomname[n]) == 0) { if (hold == -1) { gmx_incons("Atom naming problem"); } aid[hold+1] = n; } else { aid[nra++] = n; } } } /* copy the residuename to the tail of the groupname */ if (nra > 0) { add_grp(gb, gn, nra, aid, "SwapSC-CO"); nra = 0; } } } sfree(aid); }
void make_pull_groups(t_pull *pull, char **pgnames, t_blocka *grps, char **gnames) { int d, nchar, g, ig = -1, i; char *ptr, pulldim1[STRLEN]; t_pullgrp *pgrp; ptr = pulldim; i = 0; for (d = 0; d < DIM; d++) { if (sscanf(ptr, "%s%n", pulldim1, &nchar) != 1) { gmx_fatal(FARGS, "Less than 3 pull dimensions given in pull_dim: '%s'", pulldim); } if (gmx_strncasecmp(pulldim1, "N", 1) == 0) { pull->dim[d] = 0; } else if (gmx_strncasecmp(pulldim1, "Y", 1) == 0) { pull->dim[d] = 1; i++; } else { gmx_fatal(FARGS, "Please use Y(ES) or N(O) for pull_dim only (not %s)", pulldim1); } ptr += nchar; } if (i == 0) { gmx_fatal(FARGS, "All entries in pull_dim are N"); } for (g = 0; g < pull->ngrp+1; g++) { pgrp = &pull->grp[g]; if (g == 0 && strcmp(pgnames[g], "") == 0) { pgrp->nat = 0; } else { ig = search_string(pgnames[g], grps->nr, gnames); pgrp->nat = grps->index[ig+1] - grps->index[ig]; } if (pgrp->nat > 0) { fprintf(stderr, "Pull group %d '%s' has %d atoms\n", g, pgnames[g], pgrp->nat); snew(pgrp->ind, pgrp->nat); for (i = 0; i < pgrp->nat; i++) { pgrp->ind[i] = grps->a[grps->index[ig]+i]; } if (pull->eGeom == epullgCYL && g == 0 && pgrp->nweight > 0) { gmx_fatal(FARGS, "Weights are not supported for the reference group with cylinder pulling"); } if (pgrp->nweight > 0 && pgrp->nweight != pgrp->nat) { gmx_fatal(FARGS, "Number of weights (%d) for pull group %d '%s' does not match the number of atoms (%d)", pgrp->nweight, g, pgnames[g], pgrp->nat); } if (pgrp->nat == 1) { /* No pbc is required for this group */ pgrp->pbcatom = -1; } else { if (pgrp->pbcatom > 0) { pgrp->pbcatom -= 1; } else if (pgrp->pbcatom == 0) { pgrp->pbcatom = pgrp->ind[(pgrp->nat-1)/2]; } else { /* Use cosine weighting */ pgrp->pbcatom = -1; } } if (g > 0 && pull->eGeom != epullgDIST) { for (d = 0; d < DIM; d++) { if (pgrp->vec[d] != 0 && pull->dim[d] == 0) { gmx_fatal(FARGS, "ERROR: pull_vec%d has non-zero %c-component while pull_dim in N\n", g, 'x'+d); } } } if ((pull->eGeom == epullgDIR || pull->eGeom == epullgCYL) && g > 0 && norm2(pgrp->vec) == 0) { gmx_fatal(FARGS, "pull_vec%d can not be zero with geometry %s", g, EPULLGEOM(pull->eGeom)); } if ((pull->eGeom == epullgPOS) && pgrp->rate != 0 && g > 0 && norm2(pgrp->vec) == 0) { gmx_fatal(FARGS, "pull_vec%d can not be zero with geometry %s and non-zero rate", g, EPULLGEOM(pull->eGeom)); } } else { if (g == 0) { if (pull->eGeom == epullgCYL) { gmx_fatal(FARGS, "Absolute reference groups are not supported with geometry %s", EPULLGEOM(pull->eGeom)); } } else { gmx_fatal(FARGS, "Pull group %d '%s' is empty", g, pgnames[g]); } pgrp->pbcatom = -1; } } }
static void analyse_prot(const char ** restype,t_atoms *atoms, t_blocka *gb,char ***gn,gmx_bool bASK,gmx_bool bVerb) { /* atomnames to be used in constructing index groups: */ static const char *pnoh[] = { "H" }; static const char *pnodum[] = { "MN1", "MN2", "MCB1", "MCB2", "MCG1", "MCG2", "MCD1", "MCD2", "MCE1", "MCE2", "MNZ1", "MNZ2" }; static const char *calpha[] = { "CA" }; static const char *bb[] = { "N","CA","C" }; static const char *mc[] = { "N","CA","C","O","O1","O2","OC1","OC2","OT","OXT" }; static const char *mcb[] = { "N","CA","CB","C","O","O1","O2","OC1","OC2","OT","OXT" }; static const char *mch[] = { "N","CA","C","O","O1","O2","OC1","OC2","OT","OXT", "H1","H2","H3","H" }; /* array of arrays of atomnames: */ static const char **chains[] = { NULL,pnoh,calpha,bb,mc,mcb,mch,mch,mch,pnodum }; #define NCH asize(chains) /* array of sizes of arrays of atomnames: */ const int sizes[NCH] = { 0, asize(pnoh), asize(calpha), asize(bb), asize(mc), asize(mcb), asize(mch), asize(mch), asize(mch), asize(pnodum) }; /* descriptive names of index groups */ const char *ch_name[NCH] = { "Protein", "Protein-H", "C-alpha", "Backbone", "MainChain", "MainChain+Cb", "MainChain+H", "SideChain", "SideChain-H", "Prot-Masses" }; /* construct index group containing (TRUE) or excluding (FALSE) given atom names */ const gmx_bool complement[NCH] = { TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }; const int wholename[NCH] = { -1, 0,-1,-1,-1,-1,-1,-1, 11,-1 }; /* the index in wholename gives the first item in the arrays of * atomtypes that should be tested with 'gmx_strncasecmp' in stead of * gmx_strcasecmp, or -1 if all items should be tested with strcasecmp * This is comparable to using a '*' wildcard at the end of specific * atom names, but that is more involved to implement... */ /* only add index group if it differs from the specified one, specify -1 to always add group */ const int compareto[NCH] = { -1,-1,-1,-1,-1,-1,-1,-1,-1, 0 }; int n,j; atom_id *aid; int nra,nnpres,npres; gmx_bool match; char ndx_name[STRLEN],*atnm; int i; if (bVerb) { printf("Analysing Protein...\n"); } snew(aid,atoms->nr); /* calculate the number of protein residues */ npres=0; for(i=0; (i<atoms->nres); i++) if (!gmx_strcasecmp(restype[i],"Protein")) { npres++; } /* find matching or complement atoms */ for(i=0; (i<(int)NCH); i++) { nra=0; for(n=0; (n<atoms->nr); n++) { if (!gmx_strcasecmp(restype[atoms->atom[n].resind],"Protein")) { match=FALSE; for(j=0; (j<sizes[i]); j++) { /* skip digits at beginning of atomname, e.g. 1H */ atnm=*atoms->atomname[n]; while (isdigit(atnm[0])) atnm++; if ( (wholename[i]==-1) || (j<wholename[i]) ) { if (gmx_strcasecmp(chains[i][j],atnm) == 0) match=TRUE; } else { if (gmx_strncasecmp(chains[i][j],atnm,strlen(chains[i][j])) == 0) match=TRUE; } } if (match != complement[i]) aid[nra++]=n; } } /* if we want to add this group always or it differs from previous group, add it: */ if ( compareto[i] == -1 || !grp_cmp(gb,nra,aid,compareto[i]-i) ) add_grp(gb,gn,nra,aid,ch_name[i]); } if (bASK) { for(i=0; (i<(int)NCH); i++) { printf("Split %12s into %5d residues (y/n) ? ",ch_name[i],npres); if (gmx_ask_yesno(bASK)) { int resind; nra = 0; for(n=0;((atoms->atom[n].resind < npres) && (n<atoms->nr));) { resind = atoms->atom[n].resind; for(;((atoms->atom[n].resind==resind) && (n<atoms->nr));n++) { match=FALSE; for(j=0;(j<sizes[i]); j++) if (gmx_strcasecmp(chains[i][j],*atoms->atomname[n]) == 0) match=TRUE; if (match != complement[i]) aid[nra++]=n; } /* copy the residuename to the tail of the groupname */ if (nra > 0) { t_resinfo *ri; ri = &atoms->resinfo[resind]; sprintf(ndx_name,"%s_%s%d%c", ch_name[i],*ri->name,ri->nr,ri->ic==' ' ? '\0' : ri->ic); add_grp(gb,gn,nra,aid,ndx_name); nra = 0; } } } } printf("Make group with sidechain and C=O swapped (y/n) ? "); if (gmx_ask_yesno(bASK)) { /* Make swap sidechain C=O index */ int resind,hold; nra = 0; for(n=0;((atoms->atom[n].resind < npres) && (n<atoms->nr));) { resind = atoms->atom[n].resind; hold = -1; for(;((atoms->atom[n].resind==resind) && (n<atoms->nr));n++) if (strcmp("CA",*atoms->atomname[n]) == 0) { aid[nra++]=n; hold=nra; nra+=2; } else if (strcmp("C",*atoms->atomname[n]) == 0) { if (hold == -1) gmx_incons("Atom naming problem"); aid[hold]=n; } else if (strcmp("O",*atoms->atomname[n]) == 0) { if (hold == -1) gmx_incons("Atom naming problem"); aid[hold+1]=n; } else if (strcmp("O1",*atoms->atomname[n]) == 0) { if (hold == -1) gmx_incons("Atom naming problem"); aid[hold+1]=n; } else aid[nra++]=n; } /* copy the residuename to the tail of the groupname */ if (nra > 0) { add_grp(gb,gn,nra,aid,"SwapSC-CO"); nra = 0; } } } sfree(aid); }
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; }
static char *xvgrstr(const char *gmx, const output_env_t oenv, char *buf, int buflen) { /* Supported greek letter names and corresponding xmgrace/xmgr symbols */ const char *sym[] = { "beta", "chi", "delta", "eta", "lambda", "mu", "omega", "phi", "psi", "rho", "theta", NULL }; const char symc[] = { 'b', 'c', 'd', 'h', 'l', 'm', 'w', 'f', 'y', 'r', 'q', '\0' }; int xvgf; gmx_bool bXVGR; int g, b, i; char c; xvgf = output_env_get_xvg_format(oenv); bXVGR = (xvgf == exvgXMGRACE || xvgf == exvgXMGR); g = 0; b = 0; while (gmx[g] != '\0') { /* Check with the largest string we have ("lambda"), add one for \0 */ if (b + 6 + 1 >= buflen) { gmx_fatal(FARGS, "Output buffer length in xvgstr (%d) too small to process xvg input string '%s'", buflen, gmx); } if (gmx[g] == '\\') { g++; if (gmx[g] == 's') { /* Subscript */ if (bXVGR) { buf[b++] = '\\'; buf[b++] = 's'; } else { buf[b++] = '_'; } g++; } else if (gmx[g] == 'S') { /* Superscript */ if (bXVGR) { buf[b++] = '\\'; buf[b++] = 'S'; } else { buf[b++] = '^'; } g++; } else if (gmx[g] == 'N') { /* End sub/superscript */ if (bXVGR) { buf[b++] = '\\'; buf[b++] = 'N'; } else { if (gmx[g+1] != ' ') { buf[b++] = ' '; } } g++; } else if (gmx[g] == '4') { /* Backward compatibility for xmgr normal font "\4" */ switch (xvgf) { case exvgXMGRACE: sprintf(buf+b, "%s", "\\f{}"); break; case exvgXMGR: sprintf(buf+b, "%s", "\\4"); break; default: buf[b] = '\0'; break; } g++; b = strlen(buf); } else if (gmx[g] == '8') { /* Backward compatibility for xmgr symbol font "\8" */ switch (xvgf) { case exvgXMGRACE: sprintf(buf+b, "%s", "\\x"); break; case exvgXMGR: sprintf(buf+b, "%s", "\\8"); break; default: buf[b] = '\0'; break; } g++; b = strlen(buf); } else { /* Check for special symbol */ i = 0; while (sym[i] != NULL && gmx_strncasecmp(sym[i], gmx+g, strlen(sym[i])) != 0) { i++; } if (sym[i] != NULL) { c = symc[i]; if (isupper(gmx[g])) { c = toupper(c); } switch (xvgf) { case exvgXMGRACE: sprintf(buf+b, "%s%c%s", "\\x", c, "\\f{}"); break; case exvgXMGR: sprintf(buf+b, "%s%c%s", "\\8", c, "\\4"); break; default: strncat(buf+b, gmx+g, strlen(sym[i])); b += strlen(sym[i]); if (gmx[g+strlen(sym[i])] != ' ') { buf[b++] = ' '; } buf[b] = '\0'; break; } g += strlen(sym[i]); b = strlen(buf); } else { /* Unknown escape sequence, this should not happen. * We do not generate a fatal error, since that might * stop otherwise functioning code from working. * Copy the backslash to the output and continue processing. */ buf[b++] = '\\'; } } } else { buf[b++] = gmx[g++]; } } buf[b++] = '\0'; return buf; }
gmx_bool get_libdir(char *libdir) { #define GMX_BINNAME_MAX 512 char bin_name[GMX_BINNAME_MAX]; char buf[GMX_BINNAME_MAX]; char full_path[GMX_PATH_MAX+GMX_BINNAME_MAX]; char system_path[GMX_PATH_MAX]; char *dir,*ptr,*s,*pdum; gmx_bool found=FALSE; int i; if (Program() != NULL) { /* First - detect binary name */ if (strlen(Program()) >= GMX_BINNAME_MAX) { gmx_fatal(FARGS,"The name of the binary is longer than the allowed buffer size (%d):\n'%s'",GMX_BINNAME_MAX,Program()); } strncpy(bin_name,Program(),GMX_BINNAME_MAX-1); /* On windows & cygwin we need to add the .exe extension * too, or we wont be able to detect that the file exists */ #if (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64 || defined __CYGWIN__ || defined __CYGWIN32__) if(strlen(bin_name)<3 || gmx_strncasecmp(bin_name+strlen(bin_name)-4,".exe",4)) strcat(bin_name,".exe"); #endif /* Only do the smart search part if we got a real name */ if (NULL!=bin_name && strncmp(bin_name,"GROMACS",GMX_BINNAME_MAX)) { if (!strchr(bin_name,DIR_SEPARATOR)) { /* No slash or backslash in name means it must be in the path - search it! */ /* Add the local dir since it is not in the path on windows */ #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__) pdum=_getcwd(system_path,sizeof(system_path)-1); #else pdum=getcwd(system_path,sizeof(system_path)-1); #endif sprintf(full_path,"%s%c%s",system_path,DIR_SEPARATOR,bin_name); found = gmx_fexist(full_path); if (!found && (s=getenv("PATH")) != NULL) { char *dupped; dupped=gmx_strdup(s); s=dupped; while(!found && (dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL) { sprintf(full_path,"%s%c%s",dir,DIR_SEPARATOR,bin_name); found = gmx_fexist(full_path); } sfree(dupped); } if (!found) { return FALSE; } } else if (!filename_is_absolute(bin_name)) { /* name contains directory separators, but * it does not start at the root, i.e. * name is relative to the current dir */ #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__) pdum=_getcwd(buf,sizeof(buf)-1); #else pdum=getcwd(buf,sizeof(buf)-1); #endif sprintf(full_path,"%s%c%s",buf,DIR_SEPARATOR,bin_name); } else { strncpy(full_path,bin_name,GMX_PATH_MAX); } /* Now we should have a full path and name in full_path, * but on unix it might be a link, or a link to a link to a link.. */ #if (!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64) while( (i=readlink(full_path,buf,sizeof(buf)-1)) > 0 ) { buf[i]='\0'; /* If it doesn't start with "/" it is relative */ if (buf[0]!=DIR_SEPARATOR) { strncpy(strrchr(full_path,DIR_SEPARATOR)+1,buf,GMX_PATH_MAX); } else strncpy(full_path,buf,GMX_PATH_MAX); } #endif /* Remove the executable name - it always contains at least one slash */ *(strrchr(full_path,DIR_SEPARATOR)+1)='\0'; /* Now we have the full path to the gromacs executable. * Use it to find the library dir. */ found=FALSE; while(!found && ( (ptr=strrchr(full_path,DIR_SEPARATOR)) != NULL ) ) { *ptr='\0'; found=search_subdirs(full_path,libdir); } } } /* End of smart searching. If we didn't find it in our parent tree, * or if the program name wasn't set, at least try some standard * locations before giving up, in case we are running from e.g. * a users home directory. This only works on unix or cygwin... */ #if ((!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64) || defined __CYGWIN__ || defined __CYGWIN32__) if(!found) found=search_subdirs("/usr/local",libdir); if(!found) found=search_subdirs("/usr",libdir); if(!found) found=search_subdirs("/opt",libdir); #endif return found; }
/*! * 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 */ }