/*! \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 */
}
Example #2
0
//! 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;
}
Example #4
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));
            }
        }
    }
}
Example #5
0
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));
    }
}
Example #6
0
/*! \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);
}
Example #7
0
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();
}
Example #8
0
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();
}
Example #9
0
/*!
 * \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, &param[0]);
    n2 = init_comparison_value(&d->right, &param[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);
        }
    }
}
Example #10
0
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);
    }
}
Example #11
0
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"));
    }
}
Example #12
0
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);
    }
}
Example #13
0
 bool match(const char * /*value*/) const
 {
     // Should never be reached.
     GMX_THROW(NotImplementedError(
                       "GROMACS is compiled without regular expression support"));
 }
Example #14
0
 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();
}
Example #17
0
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;
}
Example #19
0
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();
}
Example #20
0
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);
    }
}
Example #21
0
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_);
    }
}
Example #22
0
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_;
}