Ejemplo n.º 1
0
bool lmfit_exp(int          nfit,
               const double x[],
               const double y[],
               const double dy[],
               double       parm[], // NOLINT(readability-non-const-parameter)
               bool         bVerbose,
               int          eFitFn,
               int          nfix)
{
    if ((eFitFn < 0) || (eFitFn >= effnNR))
    {
        fprintf(stderr, "fitfn = %d, should be in the range 0..%d\n",
                eFitFn, effnNR-1);
        return false;
    }
#if HAVE_LMFIT
    double             chisq, ochisq;
    gmx_bool           bCont;
    int                j;
    int                maxiter = 100;
    lm_control_struct  control;
    lm_status_struct  *status;
    int                nparam = effnNparams(eFitFn);
    int                p2;
    gmx_bool           bSkipLast;

    /* Using default control structure for double precision fitting that
     * comes with the lmfit package (i.e. from the include file).
     */
    control            = lm_control_double;
    control.verbosity  = (bVerbose ? 1 : 0);
    control.n_maxpri   = 0;
    control.m_maxpri   = 0;

    snew(status, 1);
    /* Initial params */
    chisq  = 1e12;
    j      = 0;
    if (bVerbose)
    {
        printf("%4s  %10s  Parameters\n", "Step", "chi^2");
    }
    /* Check whether we have to skip some params */
    if (nfix > 0)
    {
        do
        {
            p2        = 1 << (nparam-1);
            bSkipLast = ((p2 & nfix) == p2);
            if (bSkipLast)
            {
                nparam--;
                nfix -= p2;
            }
        }
        while ((nparam > 0) && (bSkipLast));
        if (bVerbose)
        {
            printf("Using %d out of %d parameters\n", nparam, effnNparams(eFitFn));
        }
    }
    do
    {
        ochisq = chisq;
        gmx_lmcurve(nparam, parm, nfit, x, y, dy,
                    lmcurves[eFitFn], &control, status);
        chisq = gmx::square(status->fnorm);
        if (bVerbose)
        {
            printf("status: fnorm = %g, nfev = %d, userbreak = %d\noutcome = %s\n",
                   status->fnorm, status->nfev, status->userbreak,
                   lm_infmsg[status->outcome]);
        }
        if (bVerbose)
        {
            int mmm;
            printf("%4d  %8g", j, chisq);
            for (mmm = 0; (mmm < effnNparams(eFitFn)); mmm++)
            {
                printf("  %8g", parm[mmm]);
            }
            printf("\n");
        }
        j++;
        bCont = (fabs(ochisq - chisq) > fabs(control.ftol*chisq));
    }
    while (bCont && (j < maxiter));

    sfree(status);
#else
    gmx_fatal(FARGS, "This build of GROMACS was not configured with support "
              "for lmfit, so the requested fitting cannot be performed. "
              "See the install guide for instructions on how to build "
              "GROMACS with lmfit supported.");
    GMX_UNUSED_VALUE(nfit);
    GMX_UNUSED_VALUE(x);
    GMX_UNUSED_VALUE(y);
    GMX_UNUSED_VALUE(dy);
    GMX_UNUSED_VALUE(parm);
    GMX_UNUSED_VALUE(bVerbose);
    GMX_UNUSED_VALUE(eFitFn);
    GMX_UNUSED_VALUE(nfix);
#endif
    return true;
}
Ejemplo n.º 2
0
/*! \brief lmfit_exp supports fitting of different functions
 *
 * This routine calls the Levenberg-Marquardt non-linear fitting
 * routine for fitting a data set with errors to a target function.
 * Fitting routines included in gromacs in src/external/lmfit.
 */
static gmx_bool lmfit_exp(int          nfit,
                          const double x[],
                          const double y[],
                          const double dy[],
                          double       parm[],
                          gmx_bool     bVerbose,
                          int          eFitFn,
                          int          nfix)
{
    double             chisq, ochisq;
    gmx_bool           bCont;
    int                j;
    int                maxiter = 100;
    lm_control_struct  control;
    lm_status_struct  *status;
    int                nparam = effnNparams(eFitFn);
    int                p2;
    gmx_bool           bSkipLast;

    if ((eFitFn < 0) || (eFitFn >= effnNR))
    {
        fprintf(stderr, "fitfn = %d, should be in the range 0..%d\n",
                eFitFn, effnNR-1);
        return FALSE;
    }
    /* Using default control structure for double precision fitting that
     * comes with the lmfit package (i.e. from the include file).
     */
    control            = lm_control_double;
    control.verbosity  = (bVerbose ? 1 : 0);
    control.n_maxpri   = 0;
    control.m_maxpri   = 0;

    snew(status, 1);
    /* Initial params */
    chisq  = 1e12;
    j      = 0;
    if (bVerbose)
    {
        printf("%4s  %10s  Parameters\n", "Step", "chi^2");
    }
    /* Check whether we have to skip some params */
    if (nfix > 0)
    {
        do
        {
            p2        = 1 << (nparam-1);
            bSkipLast = ((p2 & nfix) == p2);
            if (bSkipLast)
            {
                nparam--;
                nfix -= p2;
            }
        }
        while ((nparam > 0) && (bSkipLast));
        if (bVerbose)
        {
            printf("Using %d out of %d parameters\n", nparam, effnNparams(eFitFn));
        }
    }
    do
    {
        ochisq = chisq;
        gmx_lmcurve(nparam, parm, nfit, x, y, dy,
                    lmcurves[eFitFn], &control, status);
        chisq = gmx::square(status->fnorm);
        if (bVerbose)
        {
            printf("status: fnorm = %g, nfev = %d, userbreak = %d\noutcome = %s\n",
                   status->fnorm, status->nfev, status->userbreak,
                   lm_infmsg[status->outcome]);
        }
        if (bVerbose)
        {
            int mmm;
            printf("%4d  %8g", j, chisq);
            for (mmm = 0; (mmm < effnNparams(eFitFn)); mmm++)
            {
                printf("  %8g", parm[mmm]);
            }
            printf("\n");
        }
        j++;
        bCont = (fabs(ochisq - chisq) > fabs(control.ftol*chisq));
    }
    while (bCont && (j < maxiter));

    sfree(status);

    return TRUE;
}