Ejemplo n.º 1
0
/*! \brief Print chi-squared value and the parameters */
static void print_chi2_params(FILE        *fp,
                              const int    eFitFn,
                              const double fitparms[],
                              const char  *label,
                              const int    nfitpnts,
                              const double x[],
                              const double y[])
{
    int    i;
    double chi2 = 0;

    for (i = 0; (i < nfitpnts); i++)
    {
        double yfit = lmcurves[eFitFn](x[i], fitparms);
        chi2 += gmx::square(y[i] - yfit);
    }
    fprintf(fp, "There are %d data points, %d parameters, %s chi2 = %g\nparams:",
            nfitpnts, effnNparams(eFitFn), label, chi2);
    for (i = 0; (i < effnNparams(eFitFn)); i++)
    {
        fprintf(fp, "  %10g", fitparms[i]);
    }
    fprintf(fp, "\n");
}
Ejemplo n.º 2
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.º 3
0
real fit_acf(int ncorr, int fitfn, const gmx_output_env_t *oenv, gmx_bool bVerbose,
             real tbeginfit, real tendfit, real dt, real c1[], real *fit)
{
    double      fitparm[3];
    double      tStart, tail_corr, sum, sumtot = 0, c_start, ct_estimate;
    real       *sig;
    int         i, j, jmax, nf_int;
    gmx_bool    bPrint;

    bPrint = bVerbose || bDebugMode();

    if (bPrint)
    {
        printf("COR:\n");
    }

    if (tendfit <= 0)
    {
        tendfit = ncorr*dt;
    }
    nf_int = std::min(ncorr, (int)(tendfit/dt));
    sum    = print_and_integrate(debug, nf_int, dt, c1, NULL, 1);

    if (bPrint)
    {
        printf("COR: Correlation time (plain integral from %6.3f to %6.3f ps) = %8.5f ps\n",
               0.0, dt*nf_int, sum);
        printf("COR: Relaxation times are computed as fit to an exponential:\n");
        printf("COR:   %s\n", effnDescription(fitfn));
        printf("COR: Fit to correlation function from %6.3f ps to %6.3f ps, results in a\n", tbeginfit, std::min(ncorr*dt, tendfit));
    }

    tStart = 0;
    if (bPrint)
    {
        printf("COR:%11s%11s%11s%11s%11s%11s%11s\n",
               "Fit from", "Integral", "Tail Value", "Sum (ps)", " a1 (ps)",
               (effnNparams(fitfn) >= 2) ? " a2 ()" : "",
               (effnNparams(fitfn) >= 3) ? " a3 (ps)" : "");
    }

    snew(sig, ncorr);

    if (tbeginfit > 0)
    {
        jmax = 3;
    }
    else
    {
        jmax = 1;
    }
    for (j = 0; ((j < jmax) && (tStart < tendfit) && (tStart < ncorr*dt)); j++)
    {
        /* Estimate the correlation time for better fitting */
        c_start     = -1;
        ct_estimate = 0;
        for (i = 0; (i < ncorr) && (dt*i < tStart || c1[i] > 0); i++)
        {
            if (c_start < 0)
            {
                if (dt*i >= tStart)
                {
                    c_start     = c1[i];
                    ct_estimate = 0.5*c1[i];
                }
            }
            else
            {
                ct_estimate += c1[i];
            }
        }
        if (c_start > 0)
        {
            ct_estimate *= dt/c_start;
        }
        else
        {
            /* The data is strange, so we need to choose somehting */
            ct_estimate = tendfit;
        }
        if (debug)
        {
            fprintf(debug, "tStart %g ct_estimate: %g\n", tStart, ct_estimate);
        }

        if (fitfn == effnEXPEXP)
        {
            fitparm[0] = 0.002*ncorr*dt;
            fitparm[1] = 0.95;
            fitparm[2] = 0.2*ncorr*dt;
        }
        else
        {
            /* Good initial guess, this increases the probability of convergence */
            fitparm[0] = ct_estimate;
            fitparm[1] = 1.0;
            fitparm[2] = 1.0;
        }

        /* Generate more or less appropriate sigma's */
        for (i = 0; i < ncorr; i++)
        {
            sig[i] = sqrt(ct_estimate+dt*i);
        }

        nf_int    = std::min(ncorr, (int)((tStart+1e-4)/dt));
        sum       = print_and_integrate(debug, nf_int, dt, c1, NULL, 1);
        tail_corr = do_lmfit(ncorr, c1, sig, dt, NULL, tStart, tendfit, oenv,
                             bDebugMode(), fitfn, fitparm, 0, NULL);
        sumtot = sum+tail_corr;
        if (fit && ((jmax == 1) || (j == 1)))
        {
            double mfp[3];
            for (i = 0; (i < 3); i++)
            {
                mfp[i] = fitparm[i];
            }
            for (i = 0; (i < ncorr); i++)
            {
                fit[i] = lmcurves[fitfn](i*dt, mfp);
            }
        }
        if (bPrint)
        {
            printf("COR:%11.4e%11.4e%11.4e%11.4e", tStart, sum, tail_corr, sumtot);
            for (i = 0; (i < effnNparams(fitfn)); i++)
            {
                printf(" %11.4e", fitparm[i]);
            }
            printf("\n");
        }
        tStart += tbeginfit;
    }
    sfree(sig);

    return sumtot;
}
Ejemplo n.º 4
0
real do_lmfit(int ndata, real c1[], real sig[], real dt, real *x0,
              real begintimefit, real endtimefit, const gmx_output_env_t *oenv,
              gmx_bool bVerbose, int eFitFn, double fitparms[], int fix,
              const char *fn_fitted)
{
    FILE    *fp;
    int      i, j, nfitpnts;
    double   integral, ttt;
    double  *x, *y, *dy;

    if (0 != fix)
    {
        fprintf(stderr, "Using fixed parameters in curve fitting is temporarily not working.\n");
    }
    if (debug)
    {
        fprintf(debug, "There are %d points to fit %d vars!\n", ndata, effnNparams(eFitFn));
        fprintf(debug, "Fit to function %d from %g through %g, dt=%g\n",
                eFitFn, begintimefit, endtimefit, dt);
    }

    snew(x, ndata);
    snew(y, ndata);
    snew(dy, ndata);
    j    = 0;
    for (i = 0; i < ndata; i++)
    {
        ttt = x0 ? x0[i] : dt*i;
        if (ttt >= begintimefit && ttt <= endtimefit)
        {
            x[j]  = ttt;
            y[j]  = c1[i];
            if (NULL == sig)
            {
                // No weighting if all values are divided by 1.
                dy[j] = 1;
            }
            else
            {
                dy[j] = std::max(1.0e-7, (double)sig[i]);
            }
            if (debug)
            {
                fprintf(debug, "j= %d, i= %d, x= %g, y= %g, dy=%g, ttt=%g\n",
                        j, i, x[j], y[j], dy[j], ttt);
            }
            j++;
        }
    }
    nfitpnts = j;
    integral = 0;
    if (nfitpnts < effnNparams(eFitFn))
    {
        fprintf(stderr, "Not enough (%d) data points for fitting, dt = %g!\n",
                nfitpnts, dt);
    }
    else
    {
        gmx_bool bSuccess;

        if (bVerbose)
        {
            print_chi2_params(stdout, eFitFn, fitparms, "initial", nfitpnts, x, y);
        }
        initiate_fit_params(eFitFn, fitparms);

        bSuccess = lmfit_exp(nfitpnts, x, y, dy, fitparms, bVerbose, eFitFn, fix);
        extract_fit_params(eFitFn, fitparms);

        if (!bSuccess)
        {
            fprintf(stderr, "Fit failed!\n");
        }
        else
        {
            if (bVerbose)
            {
                print_chi2_params(stdout, eFitFn, fitparms, "final", nfitpnts, x, y);
            }
            switch (eFitFn)
            {
                case effnEXP1:
                    integral = fitparms[0]*myexp(begintimefit, 1,  fitparms[0]);
                    break;
                case effnEXP2:
                    integral = fitparms[0]*myexp(begintimefit, fitparms[1],  fitparms[0]);
                    break;
                case effnEXPEXP:
                    integral = (fitparms[0]*myexp(begintimefit, fitparms[1],  fitparms[0]) +
                                fitparms[2]*myexp(begintimefit, 1-fitparms[1], fitparms[2]));
                    break;
                case effnEXP5:
                case effnEXP7:
                case effnEXP9:
                    integral = 0;
                    for (i = 0; (i < (effnNparams(eFitFn)-1)/2); i++)
                    {
                        integral += fitparms[2*i]*myexp(begintimefit, fitparms[2*i+1], fitparms[2*i]);
                    }
                    break;
                default:
                    /* Do numerical integration */
                    integral = 0;
                    for (i = 0; (i < nfitpnts-1); i++)
                    {
                        double y0 = lmcurves[eFitFn](x[i], fitparms);
                        double y1 = lmcurves[eFitFn](x[i+1], fitparms);
                        integral += (x[i+1]-x[i])*(y1+y0)*0.5;
                    }
                    break;
            }

            if (bVerbose)
            {
                printf("FIT: Integral of fitted function: %g\n", integral);
                if ((effnEXP5 == eFitFn) || (effnEXP7 == eFitFn) || (effnEXP9 == eFitFn))
                {
                    printf("FIT: Note that the constant term is not taken into account when computing integral.\n");
                }
            }
            /* Generate debug output */
            if (NULL != fn_fitted)
            {
                fp = xvgropen(fn_fitted, "Data + Fit", "Time (ps)",
                              "Data (t)", oenv);
                for (i = 0; (i < effnNparams(eFitFn)); i++)
                {
                    fprintf(fp, "# fitparms[%d] = %g\n", i, fitparms[i]);
                }
                for (j = 0; (j < nfitpnts); j++)
                {
                    real ttt = x0 ? x0[j] : dt*j;
                    fprintf(fp, "%10.5e  %10.5e  %10.5e\n",
                            x[j], y[j], (lmcurves[eFitFn])(ttt, fitparms));
                }
                xvgrclose(fp);
            }
        }
    }

    sfree(x);
    sfree(y);
    sfree(dy);

    return integral;
}
Ejemplo n.º 5
0
/*! \brief Process the fitting parameters to get output parameters.
 *
 * See comment at the previous function.
 */
static void extract_fit_params(int    eFitFn,
                               double params[])
{
    int i, nparm;

    nparm = effnNparams(eFitFn);

    switch (eFitFn)
    {
        case effnVAC:
            params[0] = fabs(params[0]);
            break;
        case effnEXP1:
        case effnEXP2:
        case effnEXPEXP:
            params[0] = fabs(params[0]);
            if (nparm > 2)
            {
                /* Back conversion of parameters from the fitted difference
                 * to the absolute value.
                 */
                params[2] = fabs(params[2])+params[0];
            }
            break;
        case effnEXP5:
        case effnEXP7:
        case effnEXP9:
            params[1] = fabs(params[1]);
            if (nparm > 3)
            {
                /* See comment under effnEXPEXP */
                params[3] = fabs(params[3])+params[1];
                if (nparm > 5)
                {
                    /* See comment under effnEXPEXP */
                    params[5] = fabs(params[5])+params[3];
                    if (nparm > 7)
                    {
                        /* See comment under effnEXPEXP */
                        params[7] = fabs(params[7])+params[5];
                    }
                }
            }
            break;
        case effnERREST:
            params[0] = fabs(params[0]);
            if (params[1] < 0)
            {
                params[1] = 0;
            }
            else if (params[1] > 1)
            {
                params[1] = 1;
            }
            /* See comment under effnEXPEXP */
            params[2] = params[0]+fabs(params[2]);
            break;
        case effnPRES:
            for (i = 1; (i < nparm); i++)
            {
                params[i] = fabs(params[i]);
            }
            break;
        default:
            break;
    }
}
Ejemplo n.º 6
0
/*! \brief Ensure the fitting parameters are well-behaved.
 *
 * In order to make sure that fitting behaves according to the
 * constraint that time constants are positive and increasing
 * we enforce this here by setting all time constants to their
 * absolute value and by adding e.g. |a_0| to |a_2|. This is
 * done in conjunction with the fitting functions themselves.
 * When there are multiple time constants we make sure that
 * the successive time constants are at least double the
 * previous ones and during fitting we enforce the they remain larger.
 * It may very well help the convergence of the fitting routine.
 */
static void initiate_fit_params(int    eFitFn,
                                double params[])
{
    int i, nparm;

    nparm = effnNparams(eFitFn);

    switch (eFitFn)
    {
        case effnVAC:
            GMX_ASSERT(params[0] >= 0, "parameters should be >= 0");
            break;
        case effnEXP1:
        case effnEXP2:
        case effnEXPEXP:
            GMX_ASSERT(params[0] >= 0, "parameters should be >= 0");
            if (nparm > 2)
            {
                GMX_ASSERT(params[2] >= 0, "parameters should be >= 0");
                /* In order to maintain params[2] >= params[0] in the final
                 * result, we fit the difference between the two, that is
                 * params[2]-params[0] and in the add add in params[0]
                 * again.
                 */
                params[2] = std::max(fabs(params[2])-params[0], params[0]);
            }
            break;
        case effnEXP5:
        case effnEXP7:
        case effnEXP9:
            GMX_ASSERT(params[1] >= 0, "parameters should be >= 0");
            params[1] = fabs(params[1]);
            if (nparm > 3)
            {
                GMX_ASSERT(params[3] >= 0, "parameters should be >= 0");
                /* See comment under effnEXPEXP */
                params[3] = std::max(fabs(params[3])-params[1], params[1]);
                if (nparm > 5)
                {
                    GMX_ASSERT(params[5] >= 0, "parameters should be >= 0");
                    /* See comment under effnEXPEXP */
                    params[5] = std::max(fabs(params[5])-params[3], params[3]);
                    if (nparm > 7)
                    {
                        GMX_ASSERT(params[7] >= 0, "parameters should be >= 0");
                        /* See comment under effnEXPEXP */
                        params[7] = std::max(fabs(params[7])-params[5], params[5]);
                    }
                }
            }
            break;
        case effnERREST:
            GMX_ASSERT(params[0] >= 0, "parameters should be >= 0");
            GMX_ASSERT(params[1] >= 0 && params[1] <= 1, "parameter 1 should in 0 .. 1");
            GMX_ASSERT(params[2] >= 0, "parameters should be >= 0");
            /* See comment under effnEXPEXP */
            params[2] = fabs(params[2])-params[0];
            break;
        case effnPRES:
            for (i = 1; (i < nparm); i++)
            {
                GMX_ASSERT(params[i] >= 0, "parameters should be >= 0");
            }
            break;
        default:
            break;
    }
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
int gmx_dielectric(int argc, char *argv[])
{
    const char  *desc[] = {
        "[THISMODULE] calculates frequency dependent dielectric constants",
        "from the autocorrelation function of the total dipole moment in",
        "your simulation. This ACF can be generated by [gmx-dipoles].",
        "The functional forms of the available functions are:[PAR]",
        "One parameter:    y = [EXP]-a[SUB]1[sub] x[exp],[BR]",
        "Two parameters:   y = a[SUB]2[sub] [EXP]-a[SUB]1[sub] x[exp],[BR]",
        "Three parameters: y = a[SUB]2[sub] [EXP]-a[SUB]1[sub] x[exp] + (1 - a[SUB]2[sub]) [EXP]-a[SUB]3[sub] x[exp].[BR]",
        "Start values for the fit procedure can be given on the command line.",
        "It is also possible to fix parameters at their start value, use [TT]-fix[tt]",
        "with the number of the parameter you want to fix.",
        "[PAR]",
        "Three output files are generated, the first contains the ACF,",
        "an exponential fit to it with 1, 2 or 3 parameters, and the",
        "numerical derivative of the combination data/fit.",
        "The second file contains the real and imaginary parts of the",
        "frequency-dependent dielectric constant, the last gives a plot",
        "known as the Cole-Cole plot, in which the imaginary",
        "component is plotted as a function of the real component.",
        "For a pure exponential relaxation (Debye relaxation) the latter",
        "plot should be one half of a circle."
    };
    t_filenm     fnm[] = {
        { efXVG, "-f", "dipcorr", ffREAD  },
        { efXVG, "-d", "deriv",  ffWRITE },
        { efXVG, "-o", "epsw",   ffWRITE },
        { efXVG, "-c", "cole",   ffWRITE }
    };
#define NFILE asize(fnm)
    output_env_t oenv;
    int          i, j, nx, ny, nxtail, eFitFn, nfitparm;
    real         dt, integral, fitintegral, fac, rffac;
    double      *fitparms;
    double     **yd;
    real       **y;
    const char  *legend[] = { "Correlation", "Std. Dev.", "Fit", "Combined", "Derivative" };
    static int   fix      = 0, bX = 1, nsmooth = 3;
    static real  tendInt  = 5.0, tbegin = 5.0, tend = 500.0;
    static real  A        = 0.5, tau1 = 10.0, tau2 = 1.0, eps0 = 80, epsRF = 78.5, tail = 500.0;
    real         lambda;
    t_pargs      pa[] = {
        { "-x1",  FALSE, etBOOL, {&bX},
          "use first column as [IT]x[it]-axis rather than first data set" },
        { "-eint", FALSE, etREAL, {&tendInt},
          "Time to end the integration of the data and start to use the fit"},
        { "-bfit", FALSE, etREAL, {&tbegin},
          "Begin time of fit" },
        { "-efit", FALSE, etREAL, {&tend},
          "End time of fit" },
        { "-tail", FALSE, etREAL, {&tail},
          "Length of function including data and tail from fit" },
        { "-A", FALSE, etREAL, {&A},
          "Start value for fit parameter A" },
        { "-tau1", FALSE, etREAL, {&tau1},
          "Start value for fit parameter [GRK]tau[grk]1" },
        { "-tau2", FALSE, etREAL, {&tau2},
          "Start value for fit parameter [GRK]tau[grk]2" },
        { "-eps0", FALSE, etREAL, {&eps0},
          "[GRK]epsilon[grk]0 of your liquid" },
        { "-epsRF", FALSE, etREAL, {&epsRF},
          "[GRK]epsilon[grk] of the reaction field used in your simulation. A value of 0 means infinity." },
        { "-fix", FALSE, etINT,  {&fix},
          "Fix parameters at their start values, A (2), tau1 (1), or tau2 (4)" },
        { "-ffn",    FALSE, etENUM, {s_ffn},
          "Fit function" },
        { "-nsmooth", FALSE, etINT, {&nsmooth},
          "Number of points for smoothing" }
    };

    if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW,
                           NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }
    please_cite(stdout, "Spoel98a");
    printf("WARNING: non-polarizable models can never yield an infinite\n"
           "dielectric constant that is different from 1. This is incorrect\n"
           "in the reference given above (Spoel98a).\n\n");


    nx     = read_xvg(opt2fn("-f", NFILE, fnm), &yd, &ny);
    dt     = yd[0][1] - yd[0][0];
    nxtail = min(tail/dt, nx);

    printf("Read data set containing %d colums and %d rows\n", ny, nx);
    printf("Assuming (from data) that timestep is %g, nxtail = %d\n",
           dt, nxtail);
    snew(y, 6);
    for (i = 0; (i < ny); i++)
    {
        snew(y[i], max(nx, nxtail));
    }
    for (i = 0; (i < nx); i++)
    {
        y[0][i] = yd[0][i];
        for (j = 1; (j < ny); j++)
        {
            y[j][i] = yd[j][i];
        }
    }
    if (nxtail > nx)
    {
        for (i = nx; (i < nxtail); i++)
        {
            y[0][i] = dt*i+y[0][0];
            for (j = 1; (j < ny); j++)
            {
                y[j][i] = 0.0;
            }
        }
        nx = nxtail;
    }


    /* We have read a file WITHOUT standard deviations, so we make our own... */
    if (ny == 2)
    {
        printf("Creating standard deviation numbers ...\n");
        srenew(y, 3);
        snew(y[2], nx);

        fac = 1.0/((real)nx);
        for (i = 0; (i < nx); i++)
        {
            y[2][i] = fac;
        }
    }

    eFitFn   = sffn2effn(s_ffn);
    nfitparm = effnNparams(eFitFn);
    snew(fitparms, 4);
    fitparms[0] = tau1;
    if (nfitparm > 1)
    {
        fitparms[1] = A;
    }
    if (nfitparm > 2)
    {
        fitparms[2] = tau2;
    }


    snew(y[3], nx);
    snew(y[4], nx);
    snew(y[5], nx);

    integral = print_and_integrate(NULL, calc_nbegin(nx, y[0], tbegin),
                                   dt, y[1], NULL, 1);
    integral += do_lmfit(nx, y[1], y[2], dt, y[0], tbegin, tend,
                         oenv, TRUE, eFitFn, fitparms, fix);
    for (i = 0; i < nx; i++)
    {
        y[3][i] = fit_function(eFitFn, fitparms, y[0][i]);
    }

    if (epsRF == 0)
    {
        /* This means infinity! */
        lambda = 0;
        rffac  = 1;
    }
    else
    {
        lambda = (eps0 - 1.0)/(2*epsRF - 1.0);
        rffac  = (2*epsRF+eps0)/(2*epsRF+1);
    }
    printf("DATA INTEGRAL: %5.1f, tauD(old) = %5.1f ps, "
           "tau_slope = %5.1f, tau_slope,D = %5.1f ps\n",
           integral, integral*rffac, fitparms[0], fitparms[0]*rffac);

    printf("tau_D from tau1 = %8.3g , eps(Infty) = %8.3f\n",
           fitparms[0]*(1 + fitparms[1]*lambda),
           1 + ((1 - fitparms[1])*(eps0 - 1))/(1 + fitparms[1]*lambda));

    fitintegral = numerical_deriv(nx, y[0], y[1], y[3], y[4], y[5], tendInt, nsmooth);
    printf("FIT INTEGRAL (tau_M): %5.1f, tau_D = %5.1f\n",
           fitintegral, fitintegral*rffac);

    /* Now we have the negative gradient of <Phi(0) Phi(t)> */
    write_xvg(opt2fn("-d", NFILE, fnm), "Data", nx-1, 6, y, legend, oenv);

    /* Do FFT and analysis */
    do_four(opt2fn("-o", NFILE, fnm), opt2fn("-c", NFILE, fnm),
            nx-1, y[0], y[5], eps0, epsRF, oenv);

    do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy");
    do_view(oenv, opt2fn("-c", NFILE, fnm), NULL);
    do_view(oenv, opt2fn("-d", NFILE, fnm), "-nxy");

    return 0;
}
Ejemplo n.º 9
0
static void do_fit(FILE *out, int n, gmx_bool bYdy,
                   int ny, real *x0, real **val,
                   int npargs, t_pargs *ppa, const gmx_output_env_t *oenv,
                   const char *fn_fitted)
{
    real   *c1 = NULL, *sig = NULL;
    double *fitparm;
    real    tendfit, tbeginfit;
    int     i, efitfn, nparm;

    efitfn = get_acffitfn();
    nparm  = effnNparams(efitfn);
    fprintf(out, "Will fit to the following function:\n");
    fprintf(out, "%s\n", effnDescription(efitfn));
    c1 = val[n];
    if (bYdy)
    {
        c1  = val[n];
        sig = val[n+1];
        fprintf(out, "Using two columns as y and sigma values\n");
    }
    else
    {
        snew(sig, ny);
    }
    if (opt2parg_bSet("-beginfit", npargs, ppa))
    {
        tbeginfit = opt2parg_real("-beginfit", npargs, ppa);
    }
    else
    {
        tbeginfit = x0[0];
    }
    if (opt2parg_bSet("-endfit", npargs, ppa))
    {
        tendfit   = opt2parg_real("-endfit", npargs, ppa);
    }
    else
    {
        tendfit   = x0[ny-1];
    }

    snew(fitparm, nparm);
    switch (efitfn)
    {
        case effnEXP1:
            fitparm[0] = 0.5;
            break;
        case effnEXP2:
            fitparm[0] = 0.5;
            fitparm[1] = c1[0];
            break;
        case effnEXPEXP:
            fitparm[0] = 1.0;
            fitparm[1] = 0.5*c1[0];
            fitparm[2] = 10.0;
            break;
        case effnEXP5:
            fitparm[0] = fitparm[2] = 0.5*c1[0];
            fitparm[1] = 10;
            fitparm[3] = 40;
            fitparm[4] = 0;
            break;
        case effnEXP7:
            fitparm[0] = fitparm[2] = fitparm[4] = 0.33*c1[0];
            fitparm[1] = 1;
            fitparm[3] = 10;
            fitparm[5] = 100;
            fitparm[6] = 0;
            break;
        case effnEXP9:
            fitparm[0] = fitparm[2] = fitparm[4] = fitparm[6] = 0.25*c1[0];
            fitparm[1] = 0.1;
            fitparm[3] = 1;
            fitparm[5] = 10;
            fitparm[7] = 100;
            fitparm[8] = 0;
            break;
        default:
            fprintf(out, "Warning: don't know how to initialize the parameters\n");
            for (i = 0; (i < nparm); i++)
            {
                fitparm[i] = 1;
            }
    }
    fprintf(out, "Starting parameters:\n");
    for (i = 0; (i < nparm); i++)
    {
        fprintf(out, "a%-2d = %12.5e\n", i+1, fitparm[i]);
    }
    if (do_lmfit(ny, c1, sig, 0, x0, tbeginfit, tendfit,
                 oenv, bDebugMode(), efitfn, fitparm, 0,
                 fn_fitted) > 0)
    {
        for (i = 0; (i < nparm); i++)
        {
            fprintf(out, "a%-2d = %12.5e\n", i+1, fitparm[i]);
        }
    }
    else
    {
        fprintf(out, "No solution was found\n");
    }
}