static int search_einp(int ninp, const t_inpfile *inp, const char *name) { int i; if (inp==NULL) return -1; for(i=0; i<ninp; i++) if (gmx_strcasecmp_min(name,inp[i].name) == 0) return i; return -1; }
int get_eeenum(int *ninp, t_inpfile **inp, const char *name, const char **defs, warninp_t wi) { int ii, i, j; int n = 0; char buf[STRLEN]; ii = get_einp(ninp, inp, name); if (ii == -1) { (*inp)[(*ninp)-1].value = strdup(defs[0]); return 0; } for (i = 0; (defs[i] != NULL); i++) { if (gmx_strcasecmp_min(defs[i], (*inp)[ii].value) == 0) { break; } } if (defs[i] == NULL) { n += sprintf(buf, "Invalid enum '%s' for variable %s, using '%s'\n", (*inp)[ii].value, name, defs[0]); n += sprintf(buf+n, "Next time use one of:"); j = 0; while (defs[j]) { n += sprintf(buf+n, " '%s'", defs[j]); j++; } if (wi != NULL) { warning_error(wi, buf); } else { fprintf(stderr, "%s\n", buf); } (*inp)[ii].value = strdup(defs[0]); return 0; } return i; }
int find_group(char s[], int ngrps, char **grpname) { int aa, i, n; char string[STRLEN]; gmx_bool bMultiple; bMultiple = FALSE; n = strlen(s); aa=NOTSET; /* first look for whole name match */ if (aa==NOTSET) for(i=0; i<ngrps; i++) if (gmx_strcasecmp_min(s,grpname[i])==0) { if(aa!=NOTSET) bMultiple = TRUE; aa=i; } /* second look for first string match */ if (aa==NOTSET) for(i=0; i<ngrps; i++) if (gmx_strncasecmp_min(s,grpname[i],n)==0) { if(aa!=NOTSET) bMultiple = TRUE; aa=i; } /* last look for arbitrary substring match */ if (aa==NOTSET) { upstring(s); minstring(s); for(i=0; i<ngrps; i++) { strcpy(string, grpname[i]); upstring(string); minstring(string); if (strstr(string,s)!=NULL) { if(aa!=NOTSET) bMultiple = TRUE; aa=i; } } } if (bMultiple) { printf("Error: Multiple groups '%s' selected\n", s); aa=NOTSET; } return aa; }
void replace_inp_entry(int ninp,t_inpfile *inp,const char *old_entry,const char *new_entry) { int i; for(i=0; (i<ninp); i++) { if (gmx_strcasecmp_min(old_entry,inp[i].name) == 0) { if (new_entry) { fprintf(stderr,"Replacing old mdp entry '%s' by '%s'\n", inp[i].name,new_entry); sfree(inp[i].name); inp[i].name = strdup(new_entry); } else { fprintf(stderr,"Ignoring obsolete mdp entry '%s'\n", inp[i].name); inp[i].bObsolete = TRUE; } } } }
t_inpfile *read_inpfile(const char *fn, int *ninp, char **cppopts, warninp_t wi) { FILE *in; char buf[STRLEN], lbuf[STRLEN], rbuf[STRLEN], warn_buf[STRLEN]; char *ptr, *cptr; t_inpfile *inp = NULL; int nin, lc, i, j, k; /* setting cppopts from command-line options would be cooler */ gmx_bool allow_override = FALSE; if (debug) { fprintf(debug, "Reading MDP file %s\n", fn); } in = ffopen(fn, "r"); nin = lc = 0; do { ptr = fgets2(buf, STRLEN-1, in); lc++; set_warning_line(wi, fn, lc); if (ptr) { /* Strip comment */ if ((cptr = strchr(buf, COMMENTSIGN)) != NULL) { *cptr = '\0'; } /* Strip spaces */ trim(buf); for (j = 0; (buf[j] != '=') && (buf[j] != '\0'); j++) { ; } if (buf[j] == '\0') { if (j > 0) { if (debug) { fprintf(debug, "No = on line %d in file %s, ignored\n", lc, fn); } } } else { for (i = 0; (i < j); i++) { lbuf[i] = buf[i]; } lbuf[i] = '\0'; trim(lbuf); if (lbuf[0] == '\0') { if (debug) { fprintf(debug, "Empty left hand side on line %d in file %s, ignored\n", lc, fn); } } else { for (i = j+1, k = 0; (buf[i] != '\0'); i++, k++) { rbuf[k] = buf[i]; } rbuf[k] = '\0'; trim(rbuf); if (rbuf[0] == '\0') { if (debug) { fprintf(debug, "Empty right hand side on line %d in file %s, ignored\n", lc, fn); } } else { /* Now finally something sensible */ int found_index; /* first check whether we hit the 'multiple_entries' option */ if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptName], lbuf) == 0) { /* we now check whether to allow overrides from here or not */ if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptNo], rbuf) == 0) { allow_override = FALSE; } else if (gmx_strcasecmp_min(eMultentOpt_names[eMultentOptLast], rbuf) == 0) { allow_override = TRUE; } else { sprintf(warn_buf, "Parameter \"%s\" should either be %s or %s\n", lbuf, eMultentOpt_names[eMultentOptNo], eMultentOpt_names[eMultentOptLast]); warning_error(wi, warn_buf); } } else { /* it is a regular option; check for duplicates */ found_index = search_einp(nin, inp, lbuf); if (found_index == -1) { /* add a new item */ srenew(inp, ++nin); inp[nin-1].inp_count = 1; inp[nin-1].count = 0; inp[nin-1].bObsolete = FALSE; inp[nin-1].bSet = FALSE; inp[nin-1].name = strdup(lbuf); inp[nin-1].value = strdup(rbuf); } else { if (!allow_override) { sprintf(warn_buf, "Parameter \"%s\" doubly defined (and multiple assignments not allowed)\n", lbuf); warning_error(wi, warn_buf); } else { /* override */ sfree(inp[found_index].value); inp[found_index].value = strdup(rbuf); sprintf(warn_buf, "Overriding existing parameter \"%s\" with value \"%s\"\n", lbuf, rbuf); warning_note(wi, warn_buf); } } } } } } } } while (ptr); ffclose(in); if (debug) { fprintf(debug, "Done reading MDP file, there were %d entries in there\n", nin); } *ninp = nin; return inp; }
nb_kernel_t * nb_kernel_list_findkernel(FILE gmx_unused * log, const char * arch, const char * electrostatics, const char * electrostatics_modifier, const char * vdw, const char * vdw_modifier, const char * geometry, const char * other, const char * vf) { int i; unsigned int index; nb_kernel_info_t * kernelinfo_ptr; if (kernel_list_hash_size == 0) { return NULL; } index = nb_kernel_hash_func(arch, electrostatics, electrostatics_modifier, vdw, vdw_modifier, geometry, other, vf) % kernel_list_hash_size; kernelinfo_ptr = NULL; while ( (i = kernel_list_hash[index]) != -1) { if (!gmx_strcasecmp_min(kernel_list[i].architecture, arch) && !gmx_strcasecmp_min(kernel_list[i].electrostatics, electrostatics) && !gmx_strcasecmp_min(kernel_list[i].electrostatics_modifier, electrostatics_modifier) && !gmx_strcasecmp_min(kernel_list[i].vdw, vdw) && !gmx_strcasecmp_min(kernel_list[i].vdw_modifier, vdw_modifier) && !gmx_strcasecmp_min(kernel_list[i].geometry, geometry) && !gmx_strcasecmp_min(kernel_list[i].other, other) && !gmx_strcasecmp_min(kernel_list[i].vf, vf)) { kernelinfo_ptr = kernel_list+i; break; } index = (index+1) % kernel_list_hash_size; } if (debug && kernelinfo_ptr != NULL) { fprintf(debug, "NB kernel %s() with architecture '%s' used for neighborlist with\n" " Elec: '%s', Modifier: '%s'\n" " Vdw: '%s', Modifier: '%s'\n" " Geom: '%s', Other: '%s', Calc: '%s'\n\n", kernelinfo_ptr->kernelname, arch, electrostatics, electrostatics_modifier, vdw, vdw_modifier, geometry, other, vf); } /* If we did not find any kernel the pointer will still be NULL */ return (kernelinfo_ptr != NULL) ? kernelinfo_ptr->kernelptr : NULL; }
void gmx_nonbonded_set_kernel_pointers(FILE *log, t_nblist *nl) { const char * elec; const char * elec_mod; const char * vdw; const char * vdw_mod; const char * geom; const char * other; const char * vf; struct { const char * arch; int simd_padding_width; } arch_and_padding[] = { /* Single precision */ #if (defined GMX_SIMD_X86_AVX_256_OR_HIGHER) && !(defined GMX_DOUBLE) { "avx_256_single", 8 }, #endif #if (defined GMX_SIMD_X86_AVX_128_FMA) && !(defined GMX_DOUBLE) { "avx_128_fma_single", 4 }, #endif #if (defined GMX_SIMD_X86_SSE4_1) && !(defined GMX_DOUBLE) { "sse4_1_single", 4 }, #endif #if (defined GMX_SIMD_X86_SSE2) && !(defined GMX_DOUBLE) { "sse2_single", 4 }, #endif /* Double precision */ #if (defined GMX_SIMD_X86_AVX_256_OR_HIGHER && defined GMX_DOUBLE) { "avx_256_double", 4 }, #endif #if (defined GMX_SIMD_X86_AVX_128_FMA && defined GMX_DOUBLE) /* Sic. Double precision 2-way SIMD does not require neighbor list padding, * since the kernels execute a loop unrolled a factor 2, followed by * a possible single odd-element epilogue. */ { "avx_128_fma_double", 1 }, #endif #if (defined GMX_SIMD_X86_SSE2 && defined GMX_DOUBLE) /* No padding - see comment above */ { "sse2_double", 1 }, #endif #if (defined GMX_SIMD_X86_SSE4_1 && defined GMX_DOUBLE) /* No padding - see comment above */ { "sse4_1_double", 1 }, #endif #if (defined GMX_SIMD_SPARC64_HPC_ACE && defined GMX_DOUBLE) /* No padding - see comment above */ { "sparc64_hpc_ace_double", 1 }, #endif { "c", 1 }, }; int narch = asize(arch_and_padding); int i; if (nonbonded_setup_done == FALSE) { /* We typically call this setup routine before starting timers, * but if that has not been done for whatever reason we do it now. */ gmx_nonbonded_setup(NULL, FALSE); } /* Not used yet */ other = ""; nl->kernelptr_vf = NULL; nl->kernelptr_v = NULL; nl->kernelptr_f = NULL; elec = gmx_nbkernel_elec_names[nl->ielec]; elec_mod = eintmod_names[nl->ielecmod]; vdw = gmx_nbkernel_vdw_names[nl->ivdw]; vdw_mod = eintmod_names[nl->ivdwmod]; geom = gmx_nblist_geometry_names[nl->igeometry]; if (nl->type == GMX_NBLIST_INTERACTION_ADRESS) { nl->kernelptr_vf = (void *) gmx_nb_generic_adress_kernel; nl->kernelptr_f = (void *) gmx_nb_generic_adress_kernel; nl->simd_padding_width = 1; return; } if (nl->type == GMX_NBLIST_INTERACTION_FREE_ENERGY) { nl->kernelptr_vf = (void *) gmx_nb_free_energy_kernel; nl->kernelptr_f = (void *) gmx_nb_free_energy_kernel; nl->simd_padding_width = 1; } else if (!gmx_strcasecmp_min(geom, "CG-CG")) { nl->kernelptr_vf = (void *) gmx_nb_generic_cg_kernel; nl->kernelptr_f = (void *) gmx_nb_generic_cg_kernel; nl->simd_padding_width = 1; } else { /* Try to find a specific kernel first */ for (i = 0; i < narch && nl->kernelptr_vf == NULL; i++) { nl->kernelptr_vf = (void *) nb_kernel_list_findkernel(log, arch_and_padding[i].arch, elec, elec_mod, vdw, vdw_mod, geom, other, "PotentialAndForce"); nl->simd_padding_width = arch_and_padding[i].simd_padding_width; } for (i = 0; i < narch && nl->kernelptr_f == NULL; i++) { nl->kernelptr_f = (void *) nb_kernel_list_findkernel(log, arch_and_padding[i].arch, elec, elec_mod, vdw, vdw_mod, geom, other, "Force"); nl->simd_padding_width = arch_and_padding[i].simd_padding_width; /* If there is not force-only optimized kernel, is there a potential & force one? */ if (nl->kernelptr_f == NULL) { nl->kernelptr_f = (void *) nb_kernel_list_findkernel(NULL, arch_and_padding[i].arch, elec, elec_mod, vdw, vdw_mod, geom, other, "PotentialAndForce"); nl->simd_padding_width = arch_and_padding[i].simd_padding_width; } } /* Give up. If this was a water kernel, leave the pointer as NULL, which * will disable water optimization in NS. If it is a particle kernel, set * the pointer to the generic NB kernel. */ if (nl->kernelptr_vf == NULL && !gmx_strcasecmp_min(geom, "Particle-Particle")) { nl->kernelptr_vf = (void *) gmx_nb_generic_kernel; nl->kernelptr_f = (void *) gmx_nb_generic_kernel; nl->simd_padding_width = 1; if (debug) { fprintf(debug, "WARNING - Slow generic NB kernel used for neighborlist with\n" " Elec: '%s', Modifier: '%s'\n" " Vdw: '%s', Modifier: '%s'\n" " Geom: '%s', Other: '%s'\n\n", elec, elec_mod, vdw, vdw_mod, geom, other); } } } return; }