/*! \brief * Processes a selection method token. */ static int init_method_token(YYSTYPE *yylval, YYLTYPE *yylloc, const gmx::SelectionParserSymbol *symbol, bool bPosMod, gmx_sel_lexer_t *state) { gmx_ana_selmethod_t *method = symbol->methodValue(); /* If the previous token was not KEYWORD_POS, return EMPTY_POSMOD * before the actual method to work around a limitation in Bison. */ if (!bPosMod && method->type != POS_VALUE) { state->nextMethodSymbol = symbol; _gmx_sel_lexer_add_token(yylloc, NULL, 0, state); return EMPTY_POSMOD; } _gmx_sel_lexer_add_token(yylloc, symbol->name().c_str(), -1, state); yylval->meth = method; if (!(method->flags & SMETH_MODIFIER) && method->nparams == 0) { /* Keyword */ switch (method->type) { case INT_VALUE: case REAL_VALUE: state->bMatchOf = true; return KEYWORD_NUMERIC; case STR_VALUE: return KEYWORD_STR; case GROUP_VALUE: return KEYWORD_GROUP; default: GMX_THROW(gmx::InternalError("Unsupported keyword type")); } } else { /* Method with parameters or a modifier */ if (method->flags & SMETH_MODIFIER) { /* Remove all methods from the stack */ state->msp = -1; if (method->param[1].name == NULL) { state->nextparam = &method->param[1]; } } else { if (method->param[0].name == NULL) { state->nextparam = &method->param[0]; } } ++state->msp; if (state->msp >= state->mstack_alloc) { state->mstack_alloc += 10; srenew(state->mstack, state->mstack_alloc); } state->mstack[state->msp] = method; if (method->flags & SMETH_MODIFIER) { return MODIFIER; } switch (method->type) { case INT_VALUE: return METHOD_NUMERIC; case REAL_VALUE: return METHOD_NUMERIC; case POS_VALUE: return METHOD_POS; case GROUP_VALUE: return METHOD_GROUP; default: --state->msp; GMX_THROW(gmx::InternalError("Unsupported method type")); } } return INVALID; /* Should not be reached */ }
//! This function is documented in the header file void findGpus(gmx_gpu_info_t *gpu_info) { cl_uint ocl_platform_count; cl_platform_id *ocl_platform_ids; cl_device_type req_dev_type = CL_DEVICE_TYPE_GPU; ocl_platform_ids = nullptr; if (getenv("GMX_OCL_FORCE_CPU") != nullptr) { req_dev_type = CL_DEVICE_TYPE_CPU; } while (true) { cl_int status = clGetPlatformIDs(0, nullptr, &ocl_platform_count); if (CL_SUCCESS != status) { GMX_THROW(gmx::InternalError(gmx::formatString("An unexpected value %d was returned from clGetPlatformIDs: ", status) + ocl_get_error_string(status))); } if (1 > ocl_platform_count) { // TODO this should have a descriptive error message that we only support one OpenCL platform break; } snew(ocl_platform_ids, ocl_platform_count); status = clGetPlatformIDs(ocl_platform_count, ocl_platform_ids, nullptr); if (CL_SUCCESS != status) { GMX_THROW(gmx::InternalError(gmx::formatString("An unexpected value %d was returned from clGetPlatformIDs: ", status) + ocl_get_error_string(status))); } for (unsigned int i = 0; i < ocl_platform_count; i++) { cl_uint ocl_device_count; /* If requesting req_dev_type devices fails, just go to the next platform */ if (CL_SUCCESS != clGetDeviceIDs(ocl_platform_ids[i], req_dev_type, 0, nullptr, &ocl_device_count)) { continue; } if (1 <= ocl_device_count) { gpu_info->n_dev += ocl_device_count; } } if (1 > gpu_info->n_dev) { break; } snew(gpu_info->gpu_dev, gpu_info->n_dev); { int device_index; cl_device_id *ocl_device_ids; snew(ocl_device_ids, gpu_info->n_dev); device_index = 0; for (unsigned int i = 0; i < ocl_platform_count; i++) { cl_uint ocl_device_count; /* If requesting req_dev_type devices fails, just go to the next platform */ if (CL_SUCCESS != clGetDeviceIDs(ocl_platform_ids[i], req_dev_type, gpu_info->n_dev, ocl_device_ids, &ocl_device_count)) { continue; } if (1 > ocl_device_count) { break; } for (unsigned int j = 0; j < ocl_device_count; j++) { gpu_info->gpu_dev[device_index].ocl_gpu_id.ocl_platform_id = ocl_platform_ids[i]; gpu_info->gpu_dev[device_index].ocl_gpu_id.ocl_device_id = ocl_device_ids[j]; gpu_info->gpu_dev[device_index].device_name[0] = 0; clGetDeviceInfo(ocl_device_ids[j], CL_DEVICE_NAME, sizeof(gpu_info->gpu_dev[device_index].device_name), gpu_info->gpu_dev[device_index].device_name, nullptr); gpu_info->gpu_dev[device_index].device_version[0] = 0; clGetDeviceInfo(ocl_device_ids[j], CL_DEVICE_VERSION, sizeof(gpu_info->gpu_dev[device_index].device_version), gpu_info->gpu_dev[device_index].device_version, nullptr); gpu_info->gpu_dev[device_index].device_vendor[0] = 0; clGetDeviceInfo(ocl_device_ids[j], CL_DEVICE_VENDOR, sizeof(gpu_info->gpu_dev[device_index].device_vendor), gpu_info->gpu_dev[device_index].device_vendor, nullptr); gpu_info->gpu_dev[device_index].compute_units = 0; clGetDeviceInfo(ocl_device_ids[j], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(gpu_info->gpu_dev[device_index].compute_units), &(gpu_info->gpu_dev[device_index].compute_units), nullptr); gpu_info->gpu_dev[device_index].adress_bits = 0; clGetDeviceInfo(ocl_device_ids[j], CL_DEVICE_ADDRESS_BITS, sizeof(gpu_info->gpu_dev[device_index].adress_bits), &(gpu_info->gpu_dev[device_index].adress_bits), nullptr); gpu_info->gpu_dev[device_index].vendor_e = get_vendor_id(gpu_info->gpu_dev[device_index].device_vendor); gpu_info->gpu_dev[device_index].stat = is_gmx_supported_gpu_id(gpu_info->gpu_dev + device_index); if (egpuCompatible == gpu_info->gpu_dev[device_index].stat) { gpu_info->n_dev_compatible++; } device_index++; } } gpu_info->n_dev = device_index; /* Dummy sort of devices - AMD first, then NVIDIA, then Intel */ // TODO: Sort devices based on performance. if (0 < gpu_info->n_dev) { int last = -1; for (int i = 0; i < gpu_info->n_dev; i++) { if (OCL_VENDOR_AMD == gpu_info->gpu_dev[i].vendor_e) { last++; if (last < i) { gmx_device_info_t ocl_gpu_info; ocl_gpu_info = gpu_info->gpu_dev[i]; gpu_info->gpu_dev[i] = gpu_info->gpu_dev[last]; gpu_info->gpu_dev[last] = ocl_gpu_info; } } } /* if more than 1 device left to be sorted */ if ((gpu_info->n_dev - 1 - last) > 1) { for (int i = 0; i < gpu_info->n_dev; i++) { if (OCL_VENDOR_NVIDIA == gpu_info->gpu_dev[i].vendor_e) { last++; if (last < i) { gmx_device_info_t ocl_gpu_info; ocl_gpu_info = gpu_info->gpu_dev[i]; gpu_info->gpu_dev[i] = gpu_info->gpu_dev[last]; gpu_info->gpu_dev[last] = ocl_gpu_info; } } } } } sfree(ocl_device_ids); } break; } sfree(ocl_platform_ids); }
int CommandLineHelpModule::run(int argc, char *argv[]) { // Add internal topics lazily here. addTopic(HelpTopicPointer(new CommandsHelpTopic(*impl_))); const char *const exportFormats[] = { "rst", "completion" }; std::string exportFormat; Options options(NULL, NULL); options.addOption(StringOption("export").store(&exportFormat) .enumValue(exportFormats)); CommandLineParser(&options).parse(&argc, argv); if (!exportFormat.empty()) { boost::scoped_ptr<HelpExportInterface> exporter; if (exportFormat == "rst") { exporter.reset(new HelpExportReStructuredText(*impl_)); } else if (exportFormat == "completion") { exporter.reset(new HelpExportCompletion(*impl_)); } else { GMX_THROW(NotImplementedError("This help format is not implemented")); } impl_->exportHelp(exporter.get()); return 0; } File &outputFile = impl_->outputRedirector_->standardOutput(); HelpLinks links(eHelpOutputFormat_Console); initProgramLinks(&links, *impl_); boost::scoped_ptr<CommandLineHelpContext> context( new CommandLineHelpContext(&outputFile, eHelpOutputFormat_Console, &links)); context->setShowHidden(impl_->bHidden_); if (impl_->moduleOverride_ != NULL) { context->setModuleDisplayName(impl_->programContext_.displayName()); impl_->moduleOverride_->writeHelp(*context); return 0; } impl_->context_ = context.get(); HelpManager helpManager(*impl_->rootTopic_, context->writerContext()); try { for (int i = 1; i < argc; ++i) { helpManager.enterTopic(argv[i]); } } catch (const InvalidInputError &ex) { fprintf(stderr, "%s\n", ex.what()); return 2; } helpManager.writeCurrentTopic(); return 0; }
void SelectionCollection::compile() { if (impl_->sc_.top == NULL && requiresTopology()) { GMX_THROW(InconsistentInputError("Selection requires topology information, but none provided")); } if (!impl_->bExternalGroupsSet_) { setIndexGroups(NULL); } if (impl_->debugLevel_ >= 1) { printTree(stderr, false); } SelectionCompiler compiler; compiler.compile(this); if (impl_->debugLevel_ >= 1) { std::fprintf(stderr, "\n"); printTree(stderr, false); std::fprintf(stderr, "\n"); impl_->sc_.pcc.printTree(stderr); std::fprintf(stderr, "\n"); } impl_->sc_.pcc.initEvaluation(); if (impl_->debugLevel_ >= 1) { impl_->sc_.pcc.printTree(stderr); std::fprintf(stderr, "\n"); } // TODO: It would be nicer to associate the name of the selection option // (if available) to the error message. SelectionDataList::const_iterator iter; for (iter = impl_->sc_.sel.begin(); iter != impl_->sc_.sel.end(); ++iter) { const internal::SelectionData &sel = **iter; if (sel.hasFlag(efSelection_OnlyAtoms)) { if (!sel.hasOnlyAtoms()) { std::string message = formatString( "Selection '%s' does not evaluate to individual atoms. " "This is not allowed in this context.", sel.selectionText()); GMX_THROW(InvalidInputError(message)); } } if (sel.hasFlag(efSelection_DisallowEmpty)) { if (sel.posCount() == 0) { std::string message = formatString( "Selection '%s' never matches any atoms.", sel.selectionText()); GMX_THROW(InvalidInputError(message)); } } } }
void CommandLineParser::parse(int *argc, char *argv[]) { ExceptionInitializer errors("Invalid command-line options"); std::string currentContext; bool bInOption = false; impl_->assigner_.start(); int newi = 1; for (int i = 1; i != *argc; ++i) { const char *const arg = argv[i]; const char *const optionName = impl_->toOptionName(arg); if (optionName != NULL) { if (bInOption) { try { impl_->assigner_.finishOption(); } catch (UserInputError &ex) { ex.prependContext(currentContext); errors.addCurrentExceptionAsNested(); } } currentContext = "In command-line option " + std::string(arg); try { bInOption = impl_->assigner_.tryStartOption(optionName); if (!bInOption) { currentContext.clear(); if (!impl_->bSkipUnknown_) { std::string message = "Unknown command-line option " + std::string(arg); GMX_THROW(InvalidInputError(message)); } } } catch (UserInputError &ex) { // If tryStartOption() throws, make sure that the rest gets // ignored. // TODO: Consider whether we should remove the option from the // command line nonetheless, as it is recognized, but just // invalid. bInOption = false; ex.prependContext(currentContext); errors.addCurrentExceptionAsNested(); currentContext.clear(); } } else if (bInOption) { try { impl_->assigner_.appendValue(arg); } // TODO: Consider if some types of exceptions would be better left // unhandled. catch (GromacsException &ex) { ex.prependContext(currentContext); errors.addCurrentExceptionAsNested(); } } // Remove recognized options if applicable. if (!bInOption && impl_->bSkipUnknown_) { argv[newi] = argv[i]; ++newi; } } // Update the argc count if argv was modified. if (impl_->bSkipUnknown_) { *argc = newi; argv[newi] = NULL; } // Finish the last option. if (bInOption) { try { impl_->assigner_.finishOption(); } catch (UserInputError &ex) { ex.prependContext(currentContext); errors.addCurrentExceptionAsNested(); } } impl_->assigner_.finish(); if (errors.hasNestedExceptions()) { // TODO: This exception type may not always be appropriate. GMX_THROW(InvalidInputError(errors)); } }
/*! \brief Handles writing the OpenCL JIT compilation log to \c fplog. * * If \c fplog is non-null and either the GMX_OCL_DUMP_LOG environment * variable is set or the compilation failed, then the OpenCL * compilation log is written. * * \param fplog Open file pointer to log file * \param program OpenCL program that was compiled * \param deviceId Id of the device for which compilation took place * \param kernelFilename File name containing the kernel * \param preprocessorOptions String containing the preprocessor command-line options used for the build * \param buildFailed Whether the OpenCL build succeeded * * \throws std::bad_alloc if out of memory */ static void writeOclBuildLog(FILE *fplog, cl_program program, cl_device_id deviceId, const std::string &kernelFilename, const std::string &preprocessorOptions, bool buildFailed) { bool writeOutput = ((fplog != nullptr) && (buildFailed || (getenv("GMX_OCL_DUMP_LOG") != nullptr))); if (!writeOutput) { return; } // Get build log string size size_t buildLogSize; cl_int cl_error = clGetProgramBuildInfo(program, deviceId, CL_PROGRAM_BUILD_LOG, 0, NULL, &buildLogSize); if (cl_error != CL_SUCCESS) { GMX_THROW(InternalError("Could not get OpenCL program build log size, error was " + ocl_get_error_string(cl_error))); } char *buildLog = nullptr; unique_cptr<char> buildLogGuard; if (buildLogSize != 0) { /* Allocate memory to fit the build log, it can be very large in case of errors */ snew(buildLog, buildLogSize); buildLogGuard.reset(buildLog); /* Get the actual compilation log */ cl_error = clGetProgramBuildInfo(program, deviceId, CL_PROGRAM_BUILD_LOG, buildLogSize, buildLog, NULL); if (cl_error != CL_SUCCESS) { GMX_THROW(InternalError("Could not get OpenCL program build log, error was " + ocl_get_error_string(cl_error))); } } std::string message; if (buildFailed) { message += "Compilation of source file " + kernelFilename + " failed!\n"; } else { message += "Compilation of source file " + kernelFilename + " was successful!\n"; } message += "-- Used build options: " + preprocessorOptions + "\n"; message += "--------------LOG START---------------\n"; message += buildLog; message += "---------------LOG END----------------\n";; fputs(message.c_str(), fplog); }
std::string DataFileFinder::findFile(const DataFileOptions &options) const { if (options.bCurrentDir_ && Path::exists(options.filename_)) { return options.filename_; } if (impl_ != nullptr) { std::vector<std::string>::const_iterator i; for (i = impl_->searchPath_.begin(); i != impl_->searchPath_.end(); ++i) { // TODO: Deal with an empty search path entry more reasonably. std::string testPath = Path::join(*i, options.filename_); // TODO: Consider skipping directories. if (Path::exists(testPath)) { return testPath; } } } const std::string &defaultPath = Impl::getDefaultPath(); if (!defaultPath.empty()) { std::string testPath = Path::join(defaultPath, options.filename_); if (Path::exists(testPath)) { return testPath; } } if (options.bThrow_) { const char *const envName = (impl_ != nullptr ? impl_->envName_ : nullptr); const bool bEnvIsSet = (impl_ != nullptr ? impl_->bEnvIsSet_ : false); std::string message( formatString("Library file '%s' not found", options.filename_)); if (options.bCurrentDir_) { message.append(" in current dir nor"); } if (bEnvIsSet) { message.append(formatString(" in your %s path nor", envName)); } message.append(" in the default directories.\nThe following paths were searched:"); if (options.bCurrentDir_) { message.append("\n "); message.append(Path::getWorkingDirectory()); message.append(" (current dir)"); } if (impl_ != nullptr) { std::vector<std::string>::const_iterator i; for (i = impl_->searchPath_.begin(); i != impl_->searchPath_.end(); ++i) { message.append("\n "); message.append(*i); } } if (!defaultPath.empty()) { message.append("\n "); message.append(defaultPath); message.append(" (default)"); } if (!bEnvIsSet && envName != nullptr) { message.append( formatString("\nYou can set additional directories to search " "with the %s path variable.", envName)); } GMX_THROW(FileIOError(message)); } return std::string(); }
void Angle::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc, TrajectoryAnalysisModuleData *pdata) { AnalysisDataHandle *dh = pdata->dataHandle("angle"); std::vector<Selection *> sel1 = pdata->parallelSelections(_sel1); std::vector<Selection *> sel2 = pdata->parallelSelections(_sel2); checkSelections(sel1, sel2); rvec v1, v2; rvec c1, c2; switch (_g2type[0]) { case 'z': clear_rvec(v2); v2[ZZ] = 1.0; clear_rvec(c2); break; case 's': copy_rvec(_sel2[0]->x(0), c2); break; } dh->startFrame(frnr, fr.time); int incr1 = _bSplit1 ? 1 : _natoms1; int incr2 = _bSplit2 ? 1 : _natoms2; int ngrps = _bMulti ? _sel1.size() : 1; for (int g = 0; g < ngrps; ++g) { real ave = 0.0; int n = 0; int i, j; for (i = j = 0; i < sel1[g]->posCount(); i += incr1) { rvec x[4]; real angle; copy_pos(sel1, _bSplit1, _natoms1, g, i, x); switch (_g1type[0]) { case 'a': if (pbc) { pbc_dx(pbc, x[0], x[1], v1); pbc_dx(pbc, x[2], x[1], v2); } else { rvec_sub(x[0], x[1], v1); rvec_sub(x[2], x[1], v2); } angle = gmx_angle(v1, v2); break; case 'd': { rvec dx[3]; if (pbc) { pbc_dx(pbc, x[0], x[1], dx[0]); pbc_dx(pbc, x[2], x[1], dx[1]); pbc_dx(pbc, x[2], x[3], dx[2]); } else { rvec_sub(x[0], x[1], dx[0]); rvec_sub(x[2], x[1], dx[1]); rvec_sub(x[2], x[3], dx[2]); } cprod(dx[0], dx[1], v1); cprod(dx[1], dx[2], v2); angle = gmx_angle(v1, v2); real ipr = iprod(dx[0], v2); if (ipr < 0) { angle = -angle; } break; } case 'v': case 'p': calc_vec(_natoms1, x, pbc, v1, c1); switch (_g2type[0]) { case 'v': case 'p': copy_pos(sel2, _bSplit2, _natoms2, 0, j, x); calc_vec(_natoms2, x, pbc, v2, c2); j += incr2; break; case 't': // FIXME: This is not parallelizable. if (frnr == 0) { copy_rvec(v1, _vt0[n]); } copy_rvec(_vt0[n], v2); break; case 'z': c1[XX] = c1[YY] = 0.0; break; case 's': if (pbc) { pbc_dx(pbc, c1, c2, v2); } else { rvec_sub(c1, c2, v2); } break; default: GMX_THROW(InternalError("invalid -g2 value")); } angle = gmx_angle(v1, v2); break; default: GMX_THROW(InternalError("invalid -g1 value")); } angle *= RAD2DEG; real dist = 0.0; if (_bDumpDist) { if (pbc) { rvec dx; pbc_dx(pbc, c2, c1, dx); dist = norm(dx); } else { dist = sqrt(distance2(c1, c2)); } } if (_bAll) { dh->addPoint(n + 1, angle); } ave += angle; ++n; } if (n > 0) { ave /= n; } dh->addPoint(g, ave); } dh->finishFrame(); }
/*! * \param[in] top Not used. * \param[in] npar Not used (should be 5). * \param[in] param Method parameters (should point to \ref smparams_compare). * \param[in] data Should point to a \c t_methoddata_compare. * \returns 0 if the input data is valid, -1 on error. */ static void init_compare(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data) { t_methoddata_compare *d = (t_methoddata_compare *)data; int n1, n2; /* Store the values */ n1 = init_comparison_value(&d->left, ¶m[0]); n2 = init_comparison_value(&d->right, ¶m[3]); if (n1 == 0 || n2 == 0) { GMX_THROW(gmx::InternalError("One of the values for comparison missing")); } /* Store the comparison type */ d->cmpt = comparison_type(d->cmpop); if (d->cmpt == CMP_INVALID) { GMX_THROW(gmx::InternalError("Invalid comparison type")); } /* Convert the values to the same type */ /* TODO: Currently, there are no dynamic integer-valued selection methods, * which means that only the branches with convert_int_real() will ever be * taken. It should be considered whether it is necessary to support these * other cases at all. */ if ((d->left.flags & CMP_REALVAL) && !(d->right.flags & CMP_REALVAL)) { if (d->left.flags & d->right.flags & CMP_DYNAMICVAL) { /* Nothing can be done */ } else if (!(d->right.flags & CMP_DYNAMICVAL)) { convert_int_real(n2, &d->right); } else /* d->left is static */ { convert_real_int(n1, &d->left, d->cmpt, false); } } else if (!(d->left.flags & CMP_REALVAL) && (d->right.flags & CMP_REALVAL)) { if (d->left.flags & d->right.flags & CMP_DYNAMICVAL) { /* Reverse the sides to place the integer on the right */ int flags; d->left.r = d->right.r; d->right.r = NULL; d->right.i = d->left.i; d->left.i = NULL; flags = d->left.flags; d->left.flags = d->right.flags; d->right.flags = flags; d->cmpt = reverse_comparison_type(d->cmpt); } else if (!(d->left.flags & CMP_DYNAMICVAL)) { convert_int_real(n1, &d->left); } else /* d->right is static */ { convert_real_int(n2, &d->right, d->cmpt, true); } } }
void Angle::initOptionsDone(TrajectoryAnalysisSettings *settings) { // Validity checks. bool bSingle = (_g1type[0] == 'a' || _g1type[0] == 'd'); if (bSingle && _g2type[0] != 'n') { GMX_THROW(InconsistentInputError("Cannot use a second group (-g2) with " "-g1 angle or dihedral")); } if (bSingle && _options.isSet("group2")) { GMX_THROW(InconsistentInputError("Cannot provide a second selection " "(-group2) with -g1 angle or dihedral")); } if (!bSingle && _g2type[0] == 'n') { GMX_THROW(InconsistentInputError("Should specify a second group (-g2) " "if the first group is not an angle or a dihedral")); } if (bSingle && _bDumpDist) { GMX_THROW(InconsistentInputError("Cannot calculate distances with -g1 angle or dihedral")); // _bDumpDist = false; } if (_bMulti && !bSingle) { GMX_THROW(InconsistentInputError("-mult can only be combined with -g1 angle or dihedral")); } if (_bMulti && _bSplit1) { GMX_THROW(InconsistentInputError("-mult can not be combined with -split1")); } if (_bMulti && _bAll) { GMX_THROW(InconsistentInputError("-mult and -all are mutually exclusive options")); } if (_bAll) { _sel1Adj->setOnlyStatic(true); } // Set up the number of positions per angle. switch (_g1type[0]) { case 'a': _natoms1 = 3; break; case 'd': _natoms1 = 4; break; case 'v': _natoms1 = 2; break; case 'p': _natoms1 = 3; break; default: GMX_THROW(InternalError("invalid -g1 value")); } switch (_g2type[0]) { case 'n': _natoms2 = 0; break; case 'v': _natoms2 = 2; break; case 'p': _natoms2 = 3; break; case 't': _natoms2 = 0; break; case 'z': _natoms2 = 0; break; case 's': _natoms2 = 1; break; default: GMX_THROW(InternalError("invalid -g2 value")); } if (_natoms2 == 0 && _options.isSet("group2")) { GMX_THROW(InconsistentInputError("Cannot provide a second selection (-group2) with -g2 t0 or z")); } if (!_bMulti) { _sel1Adj->setValueCount(_bSplit1 ? _natoms1 : 1); } if (_natoms2 > 0) { _sel2Adj->setValueCount(_bSplit2 ? _natoms2 : 1); } }
void Angle::checkSelections(const std::vector<Selection *> &sel1, const std::vector<Selection *> &sel2) const { if (_bMulti) { for (size_t g = 0; g < sel1.size(); ++g) { if (sel1[g]->posCount() % _natoms1 != 0) { GMX_THROW(InconsistentInputError(formatString( "Number of positions in selection %d not divisible by %d", static_cast<int>(g + 1), _natoms1))); } } return; } int na1 = sel1[0]->posCount(); int na2 = (_natoms2 > 0) ? sel2[0]->posCount() : 0; if (!_bSplit1 && _natoms1 > 1 && na1 % _natoms1 != 0) { GMX_THROW(InconsistentInputError(formatString( "Number of positions in the first group not divisible by %d", _natoms1))); } if (!_bSplit2 && _natoms2 > 1 && na2 % _natoms2 != 0) { GMX_THROW(InconsistentInputError(formatString( "Number of positions in the second group not divisible by %d", _natoms2))); } if (_bSplit1) { for (int g = 1; g < _natoms1; ++g) { if (sel1[g]->posCount() != na1) { GMX_THROW(InconsistentInputError( "All selections in the first group should contain " "the same number of positions")); } } } else { na1 /= _natoms1; } if (_natoms2 > 1) { if (_bSplit2) { for (int g = 1; g < _natoms2; ++g) { if (sel2[g]->posCount() != na2) { GMX_THROW(InconsistentInputError( "All selections in the second group should contain " "the same number of positions")); } } } else { na2 /= _natoms2; } } if (_natoms1 > 0 && _natoms2 > 1 && na1 != na2) { GMX_THROW(InconsistentInputError( "Number of vectors defined by the two groups are not the same")); } if (_g2type[0] == 's' && sel2[0]->posCount() != 1) { GMX_THROW(InconsistentInputError( "The second group should contain a single position with -g2 sphnorm")); } }
void TrajectoryAnalysisRunnerCommon::initFirstFrame() { // Return if we have already initialized the trajectory. if (impl_->fr) { return; } time_unit_t time_unit = static_cast<time_unit_t>(impl_->settings_.timeUnit() + 1); output_env_init(&impl_->oenv_, getProgramContext(), time_unit, FALSE, exvgNONE, 0); int frflags = impl_->settings_.frflags(); frflags |= TRX_NEED_X; snew(impl_->fr, 1); const TopologyInformation &top = impl_->topInfo_; if (hasTrajectory()) { if (!read_first_frame(impl_->oenv_, &impl_->status_, impl_->trjfile_.c_str(), impl_->fr, frflags)) { GMX_THROW(FileIOError("Could not read coordinates from trajectory")); } impl_->bTrajOpen_ = true; if (top.hasTopology() && impl_->fr->natoms > top.topology()->atoms.nr) { GMX_THROW(InconsistentInputError(formatString( "Trajectory (%d atoms) does not match topology (%d atoms)", impl_->fr->natoms, top.topology()->atoms.nr))); } } else { // Prepare a frame from topology information. // TODO: Initialize more of the fields. if (frflags & (TRX_NEED_V)) { GMX_THROW(NotImplementedError("Velocity reading from a topology not implemented")); } if (frflags & (TRX_NEED_F)) { GMX_THROW(InvalidInputError("Forces cannot be read from a topology")); } impl_->fr->flags = frflags; impl_->fr->natoms = top.topology()->atoms.nr; impl_->fr->bX = TRUE; snew(impl_->fr->x, impl_->fr->natoms); memcpy(impl_->fr->x, top.xtop_, sizeof(*impl_->fr->x) * impl_->fr->natoms); impl_->fr->bBox = TRUE; copy_mat(const_cast<rvec *>(top.boxtop_), impl_->fr->box); } set_trxframe_ePBC(impl_->fr, top.ePBC()); if (top.hasTopology() && impl_->settings_.hasRmPBC()) { impl_->gpbc_ = gmx_rmpbc_init(&top.topology()->idef, top.ePBC(), impl_->fr->natoms); } }
bool match(const char * /*value*/) const { // Should never be reached. GMX_THROW(NotImplementedError( "GROMACS is compiled without regular expression support")); }
explicit Impl(const std::string & /*value*/) { GMX_THROW(NotImplementedError( "GROMACS is compiled without regular expression support")); }
int _gmx_sel_lexer_process_identifier(YYSTYPE *yylval, YYLTYPE *yylloc, char *yytext, size_t yyleng, gmx_sel_lexer_t *state) { /* Check if the identifier matches with a parameter name */ if (state->msp >= 0) { gmx_ana_selparam_t *param = NULL; bool bBoolNo = false; int sp = state->msp; while (!param && sp >= 0) { int i; for (i = 0; i < state->mstack[sp]->nparams; ++i) { /* Skip NULL parameters and too long parameters */ if (state->mstack[sp]->param[i].name == NULL || strlen(state->mstack[sp]->param[i].name) > yyleng) { continue; } if (!strncmp(state->mstack[sp]->param[i].name, yytext, yyleng)) { param = &state->mstack[sp]->param[i]; break; } /* Check separately for a 'no' prefix on boolean parameters */ if (state->mstack[sp]->param[i].val.type == NO_VALUE && yyleng > 2 && yytext[0] == 'n' && yytext[1] == 'o' && !strncmp(state->mstack[sp]->param[i].name, yytext+2, yyleng-2)) { param = &state->mstack[sp]->param[i]; bBoolNo = true; break; } } if (!param) { --sp; } } if (param) { if (param->val.type == NO_VALUE && !bBoolNo) { state->bMatchBool = true; } if (sp < state->msp) { state->neom = state->msp - sp - 1; state->nextparam = param; state->bBoolNo = bBoolNo; return END_OF_METHOD; } _gmx_sel_lexer_add_token(yylloc, param->name, -1, state); return init_param_token(yylval, param, bBoolNo); } } /* Check if the identifier matches with a symbol */ const gmx::SelectionParserSymbol *symbol = state->sc->symtab->findSymbol(std::string(yytext, yyleng), false); /* If there is no match, return the token as a string */ if (!symbol) { yylval->str = gmx_strndup(yytext, yyleng); _gmx_sel_lexer_add_token(yylloc, yytext, yyleng, state); return IDENTIFIER; } gmx::SelectionParserSymbol::SymbolType symtype = symbol->type(); /* For method symbols, we need some extra processing. */ if (symtype == gmx::SelectionParserSymbol::MethodSymbol) { return init_method_token(yylval, yylloc, symbol, state->prev_pos_kw > 0, state); } _gmx_sel_lexer_add_token(yylloc, symbol->name().c_str(), -1, state); /* Reserved symbols should have been caught earlier */ if (symtype == gmx::SelectionParserSymbol::ReservedSymbol) { GMX_THROW(gmx::InternalError(gmx::formatString( "Mismatch between tokenizer and reserved symbol table (for '%s')", symbol->name().c_str()))); } /* For variable symbols, return the type of the variable value */ if (symtype == gmx::SelectionParserSymbol::VariableSymbol) { gmx::SelectionTreeElementPointer var = symbol->variableValue(); /* Return simple tokens for constant variables */ if (var->type == SEL_CONST) { switch (var->v.type) { case INT_VALUE: yylval->i = var->v.u.i[0]; return TOK_INT; case REAL_VALUE: yylval->r = var->v.u.r[0]; return TOK_REAL; case POS_VALUE: break; default: GMX_THROW(gmx::InternalError("Unsupported variable type")); } } yylval->sel = new gmx::SelectionTreeElementPointer(var); switch (var->v.type) { case INT_VALUE: return VARIABLE_NUMERIC; case REAL_VALUE: return VARIABLE_NUMERIC; case POS_VALUE: return VARIABLE_POS; case GROUP_VALUE: return VARIABLE_GROUP; default: delete yylval->sel; GMX_THROW(gmx::InternalError("Unsupported variable type")); return INVALID; } /* This position should not be reached. */ } /* For position symbols, we need to return KEYWORD_POS, but we also need * some additional handling. */ if (symtype == gmx::SelectionParserSymbol::PositionSymbol) { state->bMatchOf = true; yylval->str = gmx_strdup(symbol->name().c_str()); state->prev_pos_kw = 2; return KEYWORD_POS; } /* Should not be reached */ return INVALID; }
std::string FileNameOptionManager::completeFileName( const std::string &value, const FileNameOptionInfo &option) { const bool bAllowMissing = option.allowMissing(); const bool bInput = option.isInputFile() || option.isInputOutputFile(); // Currently, directory options are simple, and don't need any // special processing. // TODO: Consider splitting them into a separate DirectoryOption. if (option.isDirectoryOption()) { if (!impl_->bInputCheckingDisabled_ && bInput && !bAllowMissing && !Directory::exists(value)) { std::string message = formatString("Directory '%s' does not exist or is not accessible.", value.c_str()); // TODO: Get actual errno value from the attempt to open the file // to provide better feedback to the user. GMX_THROW(InvalidInputError(message)); } return value; } const int fileType = fn2ftp(value.c_str()); if (bInput && !impl_->bInputCheckingDisabled_) { if (fileType == efNR && impl_->redirector_->fileExists(value, File::throwOnError)) { ConstArrayRef<const char *> compressedExtensions(c_compressedExtensions); ConstArrayRef<const char *>::const_iterator ext; for (ext = compressedExtensions.begin(); ext != compressedExtensions.end(); ++ext) { if (endsWith(value, *ext)) { std::string newValue = value.substr(0, value.length() - std::strlen(*ext)); if (option.isValidType(fn2ftp(newValue.c_str()))) { return newValue; } else { return std::string(); } } } // VMD plugins may be able to read the file. if (option.isInputFile() && option.isTrajectoryOption()) { return value; } } else if (fileType == efNR) { const std::string processedValue = findExistingExtension(value, option, impl_->redirector_); if (!processedValue.empty()) { return processedValue; } if (bAllowMissing) { return value + option.defaultExtension(); } else if (option.isLibraryFile()) { // TODO: Treat also library files here. return value + option.defaultExtension(); } else { std::string message = formatString("File '%s' does not exist or is not accessible.\n" "The following extensions were tried to complete the file name:\n %s", value.c_str(), joinStrings(option.extensions(), ", ").c_str()); GMX_THROW(InvalidInputError(message)); } } else if (option.isValidType(fileType)) { if (option.isLibraryFile()) { // TODO: Treat also library files. } else if (!bAllowMissing) { if (!impl_->redirector_->fileExists(value, File::throwOnNotFound)) { return std::string(); } } return value; } } else // Not an input file { if (fileType == efNR) { return value + option.defaultExtension(); } else if (option.isValidType(fileType)) { return value; } } return std::string(); }
cl_program compileProgram(FILE *fplog, const std::string &kernelBaseFilename, const std::string &extraDefines, cl_context context, cl_device_id deviceId, ocl_vendor_id_t deviceVendorId) { cl_int cl_error; std::string kernelRootPath = getKernelRootPath(); GMX_RELEASE_ASSERT(fplog != nullptr, "Need a valid log file for building OpenCL programs"); /* Load OpenCL source files */ std::string kernelFilename = Path::join(kernelRootPath, kernelBaseFilename); /* Make the build options */ std::string preprocessorOptions = makePreprocessorOptions(kernelRootPath, getWarpSize(context, deviceId), deviceVendorId, extraDefines); bool buildCacheWasRead = false; std::string cacheFilename; if (useBuildCache) { cacheFilename = makeBinaryCacheFilename(kernelBaseFilename, deviceId); } /* Create OpenCL program */ cl_program program = nullptr; if (useBuildCache) { if (File::exists(cacheFilename, File::returnFalseOnError)) { /* Check if there's a valid cache available */ try { program = makeProgramFromCache(cacheFilename, context, deviceId); buildCacheWasRead = true; } catch (FileIOError &e) { // Failing to read from the cache is not a critical error formatExceptionMessageToFile(fplog, e); } } else { fprintf(fplog, "No OpenCL binary cache file was present, so will compile kernels normally.\n"); } } if (program == nullptr) { // Compile OpenCL program from source std::string kernelSource = TextReader::readFileToString(kernelFilename); if (kernelSource.empty()) { GMX_THROW(FileIOError("Error loading OpenCL code " + kernelFilename)); } const char *kernelSourcePtr = kernelSource.c_str(); size_t kernelSourceSize = kernelSource.size(); /* Create program from source code */ program = clCreateProgramWithSource(context, 1, &kernelSourcePtr, &kernelSourceSize, &cl_error); if (cl_error != CL_SUCCESS) { GMX_THROW(InternalError("Could not create OpenCL program, error was " + ocl_get_error_string(cl_error))); } } /* Build the OpenCL program, keeping the status to potentially write to the simulation log file. */ cl_int buildStatus = clBuildProgram(program, 0, NULL, preprocessorOptions.c_str(), NULL, NULL); /* Write log first, and then throw exception that the user know what is the issue even if the build fails. */ writeOclBuildLog(fplog, program, deviceId, kernelFilename, preprocessorOptions, buildStatus != CL_SUCCESS); if (buildStatus != CL_SUCCESS) { GMX_THROW(InternalError("Could not build OpenCL program, error was " + ocl_get_error_string(buildStatus))); } if (useBuildCache) { if (!buildCacheWasRead) { /* If OpenCL caching is ON, but the current cache is not valid => update it */ try { writeBinaryToCache(program, cacheFilename); } catch (GromacsException &e) { // Failing to write the cache is not a critical error formatExceptionMessageToFile(fplog, e); } } } if ((OCL_VENDOR_NVIDIA == deviceVendorId) && getenv("GMX_OCL_DUMP_INTERM_FILES")) { /* If dumping intermediate files has been requested and this is an NVIDIA card => write PTX to file */ char buffer[STRLEN]; cl_error = clGetDeviceInfo(deviceId, CL_DEVICE_NAME, sizeof(buffer), buffer, NULL); if (cl_error != CL_SUCCESS) { GMX_THROW(InternalError("Could not get OpenCL device info, error was " + ocl_get_error_string(cl_error))); } std::string ptxFilename = buffer; ptxFilename += ".ptx"; try { writeBinaryToCache(program, ptxFilename); } catch (GromacsException &e) { // Failing to write the cache is not a critical error formatExceptionMessageToFile(fplog, e); } } return program; }
ICommandLineModule * CommandLineModuleManager::Impl::processCommonOptions( CommandLineCommonOptionsHolder *optionsHolder, int *argc, char ***argv) { // Check if we are directly invoking a certain module. ICommandLineModule *module = singleModule_; // TODO: It would be nice to propagate at least the -quiet option to // the modules so that they can also be quiet in response to this. if (module == NULL) { // If not in single-module mode, process options to the wrapper binary. // TODO: Ideally, this could be done by CommandLineParser. int argcForWrapper = 1; while (argcForWrapper < *argc && (*argv)[argcForWrapper][0] == '-') { ++argcForWrapper; } if (argcForWrapper > 1) { CommandLineParser(optionsHolder->options()) .parse(&argcForWrapper, *argv); } // If no action requested and there is a module specified, process it. if (argcForWrapper < *argc && !optionsHolder->shouldIgnoreActualModule()) { const char *moduleName = (*argv)[argcForWrapper]; CommandLineModuleMap::const_iterator moduleIter = findModuleByName(moduleName); if (moduleIter == modules_.end()) { std::string message = formatString("'%s' is not a GROMACS command.", moduleName); GMX_THROW(InvalidInputError(message)); } module = moduleIter->second.get(); *argc -= argcForWrapper; *argv += argcForWrapper; // After this point, argc and argv are the same independent of // which path is taken: (*argv)[0] is the module name. } } if (module != NULL) { if (singleModule_ == NULL) { programContext_.setDisplayName(binaryName_ + " " + module->name()); } // Recognize the common options also after the module name. // TODO: It could be nicer to only recognize -h/-hidden if module is not // null. CommandLineParser(optionsHolder->options()) .skipUnknown(true).parse(argc, *argv); } if (!optionsHolder->finishOptions()) { return NULL; } // If no module specified and no other action, show the help. // Also explicitly specifying -h for the wrapper binary goes here. if (module == NULL || optionsHolder->shouldShowHelp()) { ensureHelpModuleExists(); if (module != NULL) { helpModule_->setModuleOverride(*module); } *argc = 1; module = helpModule_; } if (module == helpModule_) { helpModule_->setShowHidden(optionsHolder->shouldShowHidden()); } return module; }
void Angle::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc, TrajectoryAnalysisModuleData *pdata) { AnalysisDataHandle dh = pdata->dataHandle(angles_); const SelectionList &sel1 = pdata->parallelSelections(sel1_); const SelectionList &sel2 = pdata->parallelSelections(sel2_); checkSelections(sel1, sel2); dh.startFrame(frnr, fr.time); for (size_t g = 0; g < sel1_.size(); ++g) { rvec v1, v2; rvec c1, c2; switch (g2type_[0]) { case 'z': clear_rvec(v2); v2[ZZ] = 1.0; clear_rvec(c2); break; case 's': copy_rvec(sel2_[g].position(0).x(), c2); break; } for (int i = 0, j = 0, n = 0; i < sel1[g].posCount(); i += natoms1_, j += natoms2_, ++n) { rvec x[4]; real angle; copy_pos(sel1, natoms1_, g, i, x); switch (g1type_[0]) { case 'a': if (pbc) { pbc_dx(pbc, x[0], x[1], v1); pbc_dx(pbc, x[2], x[1], v2); } else { rvec_sub(x[0], x[1], v1); rvec_sub(x[2], x[1], v2); } angle = gmx_angle(v1, v2); break; case 'd': { rvec dx[3]; if (pbc) { pbc_dx(pbc, x[0], x[1], dx[0]); pbc_dx(pbc, x[2], x[1], dx[1]); pbc_dx(pbc, x[2], x[3], dx[2]); } else { rvec_sub(x[0], x[1], dx[0]); rvec_sub(x[2], x[1], dx[1]); rvec_sub(x[2], x[3], dx[2]); } cprod(dx[0], dx[1], v1); cprod(dx[1], dx[2], v2); angle = gmx_angle(v1, v2); real ipr = iprod(dx[0], v2); if (ipr < 0) { angle = -angle; } break; } case 'v': case 'p': calc_vec(natoms1_, x, pbc, v1, c1); switch (g2type_[0]) { case 'v': case 'p': copy_pos(sel2, natoms2_, 0, j, x); calc_vec(natoms2_, x, pbc, v2, c2); break; case 't': // FIXME: This is not parallelizable. if (frnr == 0) { copy_rvec(v1, vt0_[g][n]); } copy_rvec(vt0_[g][n], v2); break; case 'z': c1[XX] = c1[YY] = 0.0; break; case 's': if (pbc) { pbc_dx(pbc, c1, c2, v2); } else { rvec_sub(c1, c2, v2); } break; default: GMX_THROW(InternalError("invalid -g2 value")); } angle = gmx_angle(v1, v2); break; default: GMX_THROW(InternalError("invalid -g1 value")); } /* TODO: Should we also calculate distances like g_sgangle? * Could be better to leave that for a separate tool. real dist = 0.0; if (bDumpDist_) { if (pbc) { rvec dx; pbc_dx(pbc, c2, c1, dx); dist = norm(dx); } else { dist = sqrt(distance2(c1, c2)); } } */ dh.setPoint(n, angle * RAD2DEG); } } dh.finishFrame(); }
void TrajectoryAnalysisRunnerCommon::Impl::initFirstFrame() { // Return if we have already initialized the trajectory. if (fr != NULL) { return; } time_unit_t time_unit = static_cast<time_unit_t>(settings_.timeUnit() + 1); output_env_init(&oenv_, getProgramContext(), time_unit, FALSE, exvgNONE, 0); int frflags = settings_.frflags(); frflags |= TRX_NEED_X; snew(fr, 1); if (hasTrajectory()) { if (!read_first_frame(oenv_, &status_, trjfile_.c_str(), fr, frflags)) { GMX_THROW(FileIOError("Could not read coordinates from trajectory")); } bTrajOpen_ = true; if (topInfo_.hasTopology()) { const int topologyAtomCount = topInfo_.topology()->atoms.nr; if (fr->natoms > topologyAtomCount) { const std::string message = formatString("Trajectory (%d atoms) does not match topology (%d atoms)", fr->natoms, topologyAtomCount); GMX_THROW(InconsistentInputError(message)); } } } else { // Prepare a frame from topology information. // TODO: Initialize more of the fields. if (frflags & (TRX_NEED_V)) { GMX_THROW(NotImplementedError("Velocity reading from a topology not implemented")); } if (frflags & (TRX_NEED_F)) { GMX_THROW(InvalidInputError("Forces cannot be read from a topology")); } fr->natoms = topInfo_.topology()->atoms.nr; fr->bX = TRUE; snew(fr->x, fr->natoms); memcpy(fr->x, topInfo_.xtop_, sizeof(*fr->x) * fr->natoms); fr->bBox = TRUE; copy_mat(topInfo_.boxtop_, fr->box); } set_trxframe_ePBC(fr, topInfo_.ePBC()); if (topInfo_.hasTopology() && settings_.hasRmPBC()) { gpbc_ = gmx_rmpbc_init(&topInfo_.topology()->idef, topInfo_.ePBC(), fr->natoms); } }
void mapGridToDataGrid(std::vector<int> *gridpointToDatapoint, const double* const *data, int numDataPoints, const std::string &dataFilename, const Grid &grid, const std::string &correctFormatMessage) { /* Transform the data into a grid in order to map each grid point to a data point using the grid functions. */ std::vector<GridAxis> axis_; /* Count the number of points for each dimension. Each dimension has its own stride. */ int stride = 1; int numPointsCounted = 0; std::vector<int> numPoints(grid.numDimensions()); for (int d = grid.numDimensions() - 1; d >= 0; d--) { int numPointsInDim = 0; int pointIndex = 0; double firstValue = data[d][pointIndex]; do { numPointsInDim++; pointIndex += stride; } while (pointIndex < numDataPoints && !gmx_within_tol(firstValue, data[d][pointIndex], GMX_REAL_EPS)); /* The stride in dimension dimension d - 1 equals the number of points dimension d. */ stride = numPointsInDim; numPointsCounted = (numPointsCounted == 0) ? numPointsInDim : numPointsCounted*numPointsInDim; numPoints[d] = numPointsInDim; } if (numPointsCounted != numDataPoints) { std::string mesg = gmx::formatString("Could not extract data properly from %s. Wrong data format?" "\n\n%s", dataFilename.c_str(), correctFormatMessage.c_str()); GMX_THROW(InvalidInputError(mesg)); } /* The data grid has the data that was read and the properties of the AWH grid */ for (int d = 0; d < grid.numDimensions(); d++) { axis_.push_back(GridAxis(data[d][0], data[d][numDataPoints - 1], grid.axis(d).period(), numPoints[d])); } /* Map each grid point to a data point. No interpolation, just pick the nearest one. * It is assumed that the given data is uniformly spaced for each dimension. */ for (size_t m = 0; m < grid.numPoints(); m++) { /* We only define what we need for the datagrid since it's not needed here which is a bit ugly */ if (!valueIsInGrid(grid.point(m).coordValue, axis_)) { std::string mesg = gmx::formatString("%s does not contain data for all coordinate values. " "Make sure your input data covers the whole sampling domain " "and is correctly formatted. \n\n%s", dataFilename.c_str(), correctFormatMessage.c_str()); GMX_THROW(InvalidInputError(mesg)); } (*gridpointToDatapoint)[m] = getNearestIndexInGrid(grid.point(m).coordValue, axis_); } }
gmx::ArrayRef<const double> Bias::calcForceAndUpdateBias(const awh_dvec coordValue, double *awhPotential, double *potentialJump, const gmx_multisim_t *ms, double t, gmx_int64_t step, gmx_int64_t seed, FILE *fplog) { if (step < 0) { GMX_THROW(InvalidInputError("The step number is negative which is not supported by the AWH code.")); } state_.setCoordValue(grid_, coordValue); std::vector < double, AlignedAllocator < double>> &probWeightNeighbor = alignedTempWorkSpace_; /* If the convolved force is needed or this is a sampling step, * the bias in the current neighborhood needs to be up-to-date * and the probablity weights need to be calculated. */ const bool sampleCoord = params_.isSampleCoordStep(step); const bool moveUmbrella = (sampleCoord || step == 0); double convolvedBias = 0; if (params_.convolveForce || moveUmbrella || sampleCoord) { if (params_.skipUpdates()) { state_.doSkippedUpdatesInNeighborhood(params_, grid_); } convolvedBias = state_.updateProbabilityWeightsAndConvolvedBias(dimParams_, grid_, &probWeightNeighbor); if (sampleCoord) { updateForceCorrelationGrid(probWeightNeighbor, t); state_.sampleCoordAndPmf(grid_, probWeightNeighbor, convolvedBias); } } const CoordState &coordState = state_.coordState(); /* Set the bias force and get the potential contribution from this bias. * The potential jump occurs at different times depending on how * the force is applied (and how the potential is normalized). * For the convolved force it happens when the bias is updated, * for the umbrella when the umbrella is moved. */ *potentialJump = 0; double potential; if (params_.convolveForce) { state_.calcConvolvedForce(dimParams_, grid_, probWeightNeighbor, tempForce_, biasForce_); potential = -convolvedBias*params_.invBeta; } else { /* Umbrella force */ GMX_RELEASE_ASSERT(state_.points()[coordState.umbrellaGridpoint()].inTargetRegion(), "AWH bias grid point for the umbrella reference value is outside of the target region."); potential = state_.calcUmbrellaForceAndPotential(dimParams_, grid_, coordState.umbrellaGridpoint(), biasForce_); /* Moving the umbrella results in a force correction and * a new potential. The umbrella center is sampled as often as * the coordinate so we know the probability weights needed * for moving the umbrella are up-to-date. */ if (moveUmbrella) { double newPotential = state_.moveUmbrella(dimParams_, grid_, probWeightNeighbor, biasForce_, step, seed, params_.biasIndex); *potentialJump = newPotential - potential; } } /* Update the free energy estimates and bias and other history dependent method parameters */ if (params_.isUpdateFreeEnergyStep(step)) { state_.updateFreeEnergyAndAddSamplesToHistogram(dimParams_, grid_, params_, ms, t, step, fplog, &updateList_); if (params_.convolveForce) { /* The update results in a potential jump, so we need the new convolved potential. */ double newPotential = -calcConvolvedBias(coordState.coordValue())*params_.invBeta; *potentialJump = newPotential - potential; } } /* Return the potential. */ *awhPotential = potential; /* Check the sampled histograms and potentially warn user if something is suspicious */ warnForHistogramAnomalies(t, step, fplog); return biasForce_; }