Beispiel #1
0
def plot_err(axis, model, data, popt, ylim=[]):
    CAP = 1000  # Error values capped at CAP, or numpy may crash on saving plots.
    MIN = 1.0e-5  # Min value for division.
    YLIM = 25  # Limit values for y-axis.

    # Note: the 1.0*data line is important, otherwise we just get a ref to data.
    if 'u' in data:
        S = data['u'][:, 1] - MU.get_function(model, 'u')(data['u'][:, 0], *
                                                          popt)
        d = 1.0 * data['u'][:, 1]  # See note.
        np.copyto(d, MIN, where=d < MIN)
        err = 100.0 * (S / d)
        np.copyto(err, CAP, where=err > CAP)
        axis.plot(data['u'][:, 0], err, '.b', label='Uniaxial Errors')
    if 'b' in data:
        S = data['b'][:, 1] - MU.get_function(model, 'b')(data['b'][:, 0], *
                                                          popt)
        d = 1.0 * data['b'][:, 1]  # See note.
        np.copyto(d, MIN, where=d < MIN)
        err = 100.0 * (S / d)
        np.copyto(err, CAP, where=err > CAP)
        axis.plot(data['b'][:, 0], err, '.g', label='Biaxial Errors')
    if 'p' in data:
        S = data['p'][:, 1] - MU.get_function(model, 'p')(data['p'][:, 0], *
                                                          popt)
        d = 1.0 * data['p'][:, 1]  # See note.
        np.copyto(d, MIN, where=d < MIN)
        err = 100.0 * (S / d)
        np.copyto(err, CAP, where=err > CAP)
        axis.plot(data['p'][:, 0], err, '.r', label='Planar Errors')

    # Set the axis limits.
    if len(ylim) == 0 or ylim[0] == ylim[1]:
        ylim = axis.get_ylim()
        ylim = [
            ylim[0] if ylim[0] > -YLIM else -YLIM,
            ylim[1] if ylim[1] < YLIM else YLIM
        ]
    axis.set_ylim(ylim)
    axis.grid()
    axis.set_xlabel('Engineering Strain')
    axis.set_ylabel('Error (%)')
    axis.legend(loc='best', frameon=False, framealpha=0)
Beispiel #2
0
def calculate_rsquared(data, model, popt, t):
    if len(data) == 0: return 0.0
    for char in t:
        if not char in data: continue
        ydata = data[char][:, 1]
        yfit = MU.get_function(model, char)(data[char][:, 0], *popt)
        if 'yfits' in locals():
            ydatas = np.hstack((ydatas, ydata))
            yfits = np.hstack((yfits, yfit))
        else:
            ydatas = ydata
            yfits = yfit
    return CF.rsquared(ydatas, yfits)
Beispiel #3
0
def plot_data(axis, model, data, popt=[], xlim=[], ylim=[]):
    # Plot the datasets.
    if 'u' in data:
        axis.plot(data['u'][:, 0],
                  data['u'][:, 1],
                  color='aqua',
                  label='Uniaxial Data')
    if 'b' in data:
        axis.plot(data['b'][:, 0],
                  data['b'][:, 1],
                  color='lime',
                  label='Biaxial Data')
    if 'p' in data:
        axis.plot(data['p'][:, 0],
                  data['p'][:, 1],
                  color='red',
                  label='Planar Data')
    if 'v' in data:
        axis.plot(data['v'][:, 0],
                  data['v'][:, 1],
                  color='fuchsia',
                  label='Volumetric Data')

    # Find the limits.
    if len(xlim) == 0 or xlim[0] == xlim[1]:
        xlim = list(axis.get_xlim())
        xlim[1] = 1.2 * xlim[1]
    if len(ylim) == 0 or ylim[0] == ylim[1]:
        ylim = list(axis.get_ylim())
        ylim[1] = 1.2 * ylim[1]

    if len(popt) != 0:
        # Calculate the fitted lines.
        NP = 2000
        keys = ['u', 'b', 'p']
        fits = dict()
        for i, key in enumerate(keys):
            fvals = np.empty([NP, 2])
            fvals[:, 0] = np.linspace(xlim[0], xlim[1], NP)
            fvals[:, 1] = MU.get_function(model, key)(fvals[:, 0],
                                                      *popt)  # splat operator.
            fits[key] = fvals
        # Plot the fited lines.
        axis.plot(fits['u'][:, 0],
                  fits['u'][:, 1],
                  '--',
                  color='blue',
                  label='Uniaxial Fit')
        axis.plot(fits['b'][:, 0],
                  fits['b'][:, 1],
                  '--',
                  color='green',
                  label='Biaxial Fit')
        axis.plot(fits['p'][:, 0],
                  fits['p'][:, 1],
                  '--',
                  color='maroon',
                  label='Planar Fit')
        axis.set_xlim(xlim)
        axis.set_ylim(ylim)
    axis.grid()
    axis.set_xlabel('Engineering Strain')
    axis.set_ylabel(r'Nominal Stress $\left({}^N\!/{}_{mm^2}\right)$')
    L = axis.legend(loc='best', frameon=False, framealpha=0)
    for legobj in L.legendHandles:
        legobj.set_linewidth(3.0)
Beispiel #4
0
def calc_params(data,
                descr,
                model,
                method,
                poisson,
                t,
                num_points,
                params,
                ext,
                xlim=[],
                ylim=[],
                ylimerr=[]):
    maxitr = 5000  # Default = 100*(len(data[t][:,0])+1)
    nparams = len(inspect.getargspec(model.stressU)[0]) - 1
    print '---------------------------------------------------------'
    print ' Calculating fit to', MU.get_name(t), 'data'
    print '  with', num_points, 'guess(es)'
    print '  using the \'' + method + '\' fitting method'
    print '---------------------------------------------------------'
    S_best = -1.0e8
    iname = descr + '--' + model.name() + '--' + MU.get_name(t) + ext
    title = model.pname() + ' fit to ' + MU.get_name(t) + ' Data'
    for i in range(num_points):
        p0 = np.longdouble(6.0 * np.random.random_sample(nparams) - 1.0)
        print '\tStarting point ' + str(i) + ':\t', p0
        try:
            if len(t) == 1:
                mfun = MU.get_function(model, t)
                popt = CF.curve_fit1(mfun, data[t][:, 0], data[t][:, 1],
                                     method, p0, maxitr)
            elif len(t) == 2:
                mfun0 = MU.get_function(model, t[0])
                mfun1 = MU.get_function(model, t[1])
                popt = CF.curve_fit2(mfun0, data[t[0]][:, 0], data[t[0]][:, 1],
                                     mfun1, data[t[1]][:, 0], data[t[1]][:, 1],
                                     method, p0, maxitr)
            elif len(t) == 3:
                mfun0 = MU.get_function(model, t[0])
                mfun1 = MU.get_function(model, t[1])
                mfun2 = MU.get_function(model, t[2])
                popt = CF.curve_fit3(mfun0, data[t[0]][:, 0], data[t[0]][:, 1],
                                     mfun1, data[t[1]][:, 0], data[t[1]][:, 1],
                                     mfun2, data[t[2]][:, 0], data[t[2]][:, 1],
                                     method, p0, maxitr)
            else:
                print_error('Invalid fit.', True)
        except Exception:
            print '\t\tERROR:', sys.exc_info()[1]
            continue
        # TODO - check if u*a>0 for each pair. Implement as a check function in model?
        # TODO - check if sum(ui*ai) = 2*shear_modulus
        # TODO - test Drucker stability, as in Abaqus.
        # TODO - always iterate towards best global residual? Not exactly what the user is asking for...
        S = calculate_rsquared(data, model, popt, t)
        print '\t\tFinal:   ', popt
        print '\t\tLocal Rsquared: ', S
        if S <= S_best: continue
        S_best = S
        S_global = calculate_rsquared(data, model, popt, 'ubp')
        print '\t\tGlobal Rsquared:', S_global
        print '\t\t** New Best Result. Updating Plots **'
        params[t] = np.append(popt, [S_best, S_global])

        # Plot.
        D = model.compressibility(poisson, *params[t][:-2])
        create_plots(
            model, data, popt, S, D, iname, title + '\n' + args.uniaxial +
            '\n' + args.biaxial + '\n' + args.planar, xlim, ylim, ylimerr)
        MU.write_matfile(model, descr, t, params[t][:-2], D)
    if S_best != -1.0e8:
        print '\n\tBest-fit LRsquared:', params[t][-2]
        print '\tBest-fit GRsquared:', params[t][-1]
    else:
        U.print_error("No suitable fit found.", False)
    print '\n\n'
def calc_fit(act,test,cmd,expdata,matdata,testfunc,*popt):
    fig,ax = pyplot.subplots(1,2,figsize=(10,6))
    print '\n********************************************************************'
    print '** Testing with parameters: ',popt
    print '********************************************************************'
    # Get the simulation results.
    if not hasattr(calc_fit, "iter"): calc_fit.iter=0
    simdata = testfunc((calc_fit.iter,)+popt)
    if len(simdata)==0:
        print '\n********************************************************************'
        print ' Abaqus failed, we return an average error of 1000.0'
        print '********************************************************************'
        calc_fit.iter = calc_fit.iter + 1
        return 1000.0

    # Loop over multiple simulation results, if necessary.
    NP = 50
    errs = dict()
    cm = pyplot.get_cmap('jet')
    colors = [cm(float(i)/(2*len(simdata))) for i in range(2*len(simdata))]
    cidx = 0
    for T,sdata in simdata.iteritems():
        # Plot the simulation data.
        ax[0].plot(1000.0*sdata[:,0],sdata[:,1],'o-',color=colors[cidx],label='Sim '+T)

        # Interpolate the simulation results to remove zigzags and evenly space the points.
        # This is important because otherwise we may weight solutions very heavily at one point
        # in one solution, and completely differently in another.
        u,idx = np.unique(sdata[:,0],return_index=True)
        try:
            sim_smooth = np.zeros((NP,2))
            # sim_smooth[:,0] = np.linspace(min(sdata[idx,0]),max(sdata[idx,0]),NP)
            xvals = 1.0 - (np.logspace(0,np.log10(NP+1.0),NP,endpoint=True)-1.0)/(NP+1.0)
            sim_smooth[:,0] = min(sdata[idx,0]) + (max(sdata[idx,0])-min(sdata[idx,0]))*xvals
            dataF = interp.UnivariateSpline(sdata[idx,0],sdata[idx,1],k=3,s=0)
            sim_smooth[:,1] = dataF(sim_smooth[:,0])
            ax[0].plot(1000.0*sim_smooth[:,0],sim_smooth[:,1],'.--',color=colors[cidx],label='Sim '+T+' (Smoothed)')
        except:
            print '** Failed to smooth simulation data. Proceding with untouched data.'
            sim_smooth = 1.0*sdata[idx,:]

        # Interpolate the experimental results to find comparable data.
        edata = expdata[T]
        ax[0].plot(1000.0*edata[:,0],edata[:,1],'-',color=colors[cidx+1],label='Exp '+T)
        dataF = interp.UnivariateSpline(edata[:,0], edata[:,1],k=3,s=0)
        exp_smooth = np.zeros(sim_smooth.shape)
        exp_smooth[:,0] = sim_smooth[:,0]
        exp_smooth[:,1] = dataF(exp_smooth[:,0])
        ax[0].plot(1000.0*exp_smooth[:,0],exp_smooth[:,1],'.--',color=colors[cidx+1],label='Exp '+T+' (Smoothed)')

        # Make the comparison.
        # Try to handle a case where Abaqus failed early, but we have partial results.
        if max(sdata[:,0])<0.666*max(edata[:,0]):
            errs[T] = 1000.0 - 1000.0*max(sdata[:,0])/max(edata[:,0])
            print '\n********************************************************************'
            print ' Abaqus only reached',max(sdata[:,0]),' (out of '+str(max(edata[:,0]))+')!'
            print '********************************************************************'
        else:
            # errs[T] = np.linalg.norm((exp_smooth[:,1]-sim_smooth[:,1])/max(edata[:,1]))
            errs[T] = 1.0 - CH.rsquared(exp_smooth,sim_smooth)
        cidx = cidx+2

    # Plot the model uniaxial, biaxial, and planar curves.
    if cmd!='vis':
        for t in 'ubp':
            if not t in matdata: continue
            dataF = interp.interp1d(matdata[t][:,0], matdata[t][:,1], kind='nearest', bounds_error=False, fill_value=0.0)
            vals = np.zeros((NP,3))
            vals[:,0] = np.linspace(min(matdata[t][:,0]),max(matdata[t][:,0]),NP)
            vals[:,1] = dataF(vals[:,0])
            vals[:,2] = MU.get_function(model,t)(vals[:,0],*popt)  # splat operator.
            # errs['mat_'+t] = np.linalg.norm((vals[:,1]-vals[:,2])/max(matdata[t][:,1]))
            errs['mat_'+t] = 1.0 - CH.rsquared(vals[:,1],vals[:,2])
        CHP.plot_data(ax[1],model,matdata,popt,[0,4],[0,.25])
        ax[1].set_aspect(np.diff(ax[1].get_xlim())/np.diff(ax[1].get_ylim())) # Square axis.


    # Plot settings.
    if cmd=='mat':
        ax[0].set_xlabel('Engineering Strain')
        ax[0].set_ylabel(r'Nominal Stress $\left({}^N\!/{}_{mm^2}\right)$')
    elif cmd=='act' or cmd=='vis':
        ax[0].set_xlabel('Internal Pressure (kPa)')
        if len(simdata)>1: ax[0].set_ylabel('Displacement (mm) or Force (N)')
        else:
            if 'linU' in simdata or 'bndU' in simdata:   ax[0].set_ylabel('Displacement (mm)')
            elif 'linF' in simdata or 'bndF' in simdata: ax[0].set_ylabel('Force (N)')
    ax[0].grid()
    # Plot with the same axis every time.
    if not hasattr(calc_fit, "xlim"):
        calc_fit.xlim = ax[0].get_xlim()
        calc_fit.ylim = ax[0].get_ylim()
    ax[0].set_xlim(calc_fit.xlim)
    ax[0].set_ylim(calc_fit.ylim)
    ax[0].set_aspect(np.diff(calc_fit.xlim)/np.diff(calc_fit.ylim)) # Square axis.
    # ax[0].set_aspect(abs(xlim[1]-xlim[0])/abs(ylim[1]-ylim[0])) # Square axis.
    pyplot.suptitle('\n'.join(textwrap.wrap(str(popt),100))+'\nitr='+str(calc_fit.iter)+'\nerrs='+str(errs)+'\nerr_sum='+str(sum(errs.values())))
    L = ax[0].legend(loc='best',frameon=False,framealpha=0)
    for legobj in L.legendHandles: legobj.set_linewidth(2.0)
    pyplot.tight_layout()
    pyplot.savefig('results--'+str(calc_fit.iter)+'.png')
    pyplot.savefig('results--latest.png')
    pyplot.close()
    print '\n********************************************************************'
    print ' Calculated sum-of-squares error:',errs,'=',sum(errs.values())
    print '********************************************************************'
    calc_fit.iter = calc_fit.iter + 1
    return sum(errs.values())