def outputplease(whatson=None, dictofvelstrs=None):
    yscomplist = cou.extract_output(strdict=dictofvelstrs, tmesh=trange,
                                    c_mat=c_mat, load_data=dou.load_npa)
    dou.save_output_json(dict(tmesh=trange.tolist(), outsig=yscomplist),
                         fstring=fdstr + '_{0}'.format(whatson) +
                         't0{0:.4f}tE{1:.4f}Nts{2}'.format(t0, tE,
                                                           np.int(Nts)))
    if plotit:
        dou.plot_outp_sig(tmesh=trange, outsig=yscomplist)
def compare_freqresp(mmat=None, amat=None, jmat=None, bmat=None,
                     cmat=None, tr=None, tl=None,
                     ahat=None, bhat=None, chat=None,
                     plot=False, datastr=None):
    """
    compare the frequency response of the original and the reduced model

    cf. [HeiSS08, p. 1059] but with B_2 = 0

    Returns
    -------
    freqrel : list of floats
        the frob norm of the transferfunction at a frequency range
    red_freqrel : list of floats
        from of the tf of the reduced model at the same frequencies
    absci : list of floats
        frequencies where the tfs are evaluated at
    """

    if ahat is None:
        ahat = np.dot(tl.T, amat*tr)
    if bhat is None:
        bhat = tl.T*bmat
    if chat is None:
        chat = cmat*tr

    NV, red_nv = amat.shape[0], ahat.shape[0]

    imunit = 1j

    absci = np.logspace(-4, 8, base=10)

    freqrel, red_freqrel, diff_freqrel = [], [], []

    for omega in absci:
        sadib = lau.solve_sadpnt_smw(amat=omega*imunit*mmat-amat,
                                     jmat=jmat, rhsv=bmat)
        freqrel.append(np.linalg.norm(cmat*sadib[:NV, :]))
        # print freqrel[-1]

        aib = np.linalg.solve(omega*imunit*np.eye(red_nv) - ahat, bhat)
        red_freqrel.append(np.linalg.norm(np.dot(chat, aib)))
        diff_freqrel.append(np.linalg.norm(np.dot(chat, aib)
                                           - cmat*sadib[:NV, :]))
        # print red_freqrel[-1]

    if datastr is not None:
        dou.save_output_json(dict(tmesh=absci.tolist(),
                                  fullsysfr=freqrel,
                                  redsysfr=red_freqrel,
                                  diffsysfr=diff_freqrel),
                             fstring=datastr + 'forfreqrespplot')

    if plot:
        legstr = ['NV was {0}'.format(mmat.shape[0]),
                  'nv is {0}'.format(tr.shape[1]),
                  'difference']
        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.plot(absci, freqrel, color='b', linewidth=2.0)
        ax.plot(absci, red_freqrel, color='r', linewidth=2.0)
        ax.plot(absci, diff_freqrel, color='b', linewidth=1.0)
        plt.legend(legstr, loc=3)
        plt.semilogx()
        plt.semilogy()
        plt.show(block=False)

        from matplotlib2tikz import save as tikz_save
        tikz_save(datastr + 'freqresp.tikz',
                  figureheight='\\figureheight',
                  figurewidth='\\figurewidth'
                  )

    return freqrel, red_freqrel, absci
def compare_stepresp(tmesh=None, a_mat=None, c_mat=None, b_mat=None,
                     m_mat=None, tl=None, tr=None,
                     iniv=None,
                     fullresp=None, fsr_soldict=None,
                     plot=False, jsonstr=None):
    """ compare the system's step response to unit inputs in time domain

    with reduced system's response.

    We consider the system

    .. math::

        M\\dot v = Av + Bu, \\quad y = Cv

    on the discretized time interval :math:`(t_0, t_E)`

    and the reduced system with :math:`\\hat A = t_l^TAt_r`.

    Parameters
    ----------
    tmesh : iterable list or ndarray
        vector of the time instances
    a_mat : (N,N) sparse matrix
        system matrix
    c_mat : (ny,N) sparse matrix or ndarray
        output matrix
    b_mat : (N,nu) sparse matrix or ndarray
        input operator
    m_mat : (N,N) sparse matrix
        mass matrix
    tl, tr : (N,K) ndarrays
        left, right transformation for the reduced system
    iniv : (N,1) ndarray
        initial value and linearization point of the full system
    fullresp : callable f(v, **dict)
        returns the response of the full system
    fsr_soldict : dictionary
        parameters to be passed to `fullresp`
    plot : boolean, optional
        whether to plot, defaults to `False`
    jsonstr: string, optional
        if defined, the output is stored in this json file, defaults to `None`
    """

    from scipy.integrate import odeint

    ahat = np.dot(tl.T, a_mat*tr)
    chat = lau.mm_dnssps(c_mat, tr)

    inivhat = np.dot(tl.T, m_mat*iniv)

    inivout = lau.mm_dnssps(c_mat, iniv).tolist()

    red_stp_rsp, ful_stp_rsp = [], []
    for ccol in [0]:  # , b_mat.shape[1]-1]:  # range(2):  # b_mat.shape[1]):
        bmc = b_mat[:, ccol][:, :]
        red_bmc = tl.T * bmc

        def dtfunc(v, t):
            return (np.dot(ahat, v).flatten() + red_bmc.flatten())  # +\

        red_state = odeint(dtfunc, 0*inivhat.flatten(), tmesh)
        red_stp_rsp.append(np.dot(chat, red_state.T).T.tolist())
        ful_stp_rsp.append(fullresp(bcol=bmc, trange=tmesh, ini_vel=iniv,
                           cmat=c_mat, soldict=fsr_soldict))

    if jsonstr:
        try:
            tmesh = tmesh.tolist()
        except AttributeError:
            pass  # is a list already
        dou.save_output_json(datadict={"tmesh": tmesh,
                                       "ful_stp_rsp": ful_stp_rsp,
                                       "red_stp_rsp": red_stp_rsp,
                                       "inivout": inivout},
                             fstring=jsonstr,
                             module='sadptprj_riclyap_adi.bal_trunc_utils',
                             plotroutine='plot_step_resp')

    if plot:
        plot_step_resp(tmesh=tmesh, red_stp_rsp=red_stp_rsp,
                       ful_stp_rsp=ful_stp_rsp, inivout=inivout)
Example #4
0
def lqgbt(problemname='drivencavity',
          N=10, Re=1e2, plain_bt=False,
          use_ric_ini=None, t0=0.0, tE=1.0, Nts=11,
          NU=3, NY=3,
          bccontrol=True, palpha=1e-5,
          paraoutput=True,
          trunc_lqgbtcv=1e-6,
          nwtn_adi_dict=None,
          comp_freqresp=False, comp_stepresp='nonlinear',
          closed_loop=False, multiproc=False,
          perturbpara=1e-3):
    """Main routine for LQGBT

    Parameters
    ----------
    problemname : string, optional
        what problem to be solved, 'cylinderwake' or 'drivencavity'
    N : int, optional
        parameter for the dimension of the space discretization
    Re : real, optional
        Reynolds number, defaults to `1e2`
    plain_bt : boolean, optional
        whether to try simple *balanced truncation*, defaults to False
    use_ric_ini : real, optional
        use the solution with this Re number as stabilizing initial guess,
        defaults to `None`
    t0, tE, Nts : real, real, int, optional
        starting and endpoint of the considered time interval, number of
        time instancses, default to `0.0, 1.0, 11`
    bccontrol : boolean, optional
        whether to apply boundary control via penalized robin conditions,
        defaults to `False`
    NU, NY : int, optional
        dimensions of components of in and output space (will double because
        there are two components), default to `3, 3`
    comp_freqresp : boolean, optional
        whether to compute and compare the frequency responses,
        defaults to `False`
    comp_stepresp : {'nonlinear', False, None}
        whether to compute and compare the step responses

        | if False -> no step response
        | if == 'nonlinear' -> compare linear reduced to nonlinear full model
        | else -> linear reduced versus linear full model

        defaults to `False`

    trunc_lqgbtcv : real, optional
        threshold at what the lqgbt characteristiv values are truncated,
        defaults to `1e-6`
    closed_loop : {'full_state_fb', 'red_output_fb', False, None}
        how to do the closed loop simulation:

        | if False -> no simulation
        | if == 'full_state_fb' -> full state feedback
        | if == 'red_output_fb' -> reduced output feedback
        | else -> no control is applied

        defaults to `False`

    """

    typprb = 'BT' if plain_bt else 'LQG-BT'

    print '\n ### We solve the {0} problem for the {1} at Re={2} ###\n'.\
        format(typprb, problemname, Re)

    if nwtn_adi_dict is not None:
        nap = nwtn_adi_dict
    else:
        nap = nwtn_adi_params()['nwtn_adi_dict']
    # output
    ddir = 'data/'
    try:
        os.chdir(ddir)
    except OSError:
        raise Warning('need "' + ddir + '" subdir for storing the data')
    os.chdir('..')

    # stokesmats = dts.get_stokessysmats(femp['V'], femp['Q'], nu)

    # rhsd_vf = dts.setget_rhs(femp['V'], femp['Q'],
    #                          femp['fv'], femp['fp'], t=0)

    # # remove the freedom in the pressure
    # stokesmats['J'] = stokesmats['J'][:-1, :][:, :]
    # stokesmats['JT'] = stokesmats['JT'][:, :-1][:, :]
    # rhsd_vf['fp'] = rhsd_vf['fp'][:-1, :]

    # # reduce the matrices by resolving the BCs
    # (stokesmatsc,
    #  rhsd_stbc,
    #  invinds,
    #  bcinds,
    #  bcvals) = dts.condense_sysmatsbybcs(stokesmats,
    #                                      femp['diribcs'])

    # # pressure freedom and dirichlet reduced rhs
    # rhsd_vfrc = dict(fpr=rhsd_vf['fp'], fvc=rhsd_vf['fv'][invinds, ])

    # # add the info on boundary and inner nodes
    # bcdata = {'bcinds': bcinds,
    #           'bcvals': bcvals,
    #           'invinds': invinds}
    # femp.update(bcdata)

    femp, stokesmatsc, rhsd_vfrc, rhsd_stbc \
        = dnsps.get_sysmats(problem=problemname, N=N, Re=Re,
                            bccontrol=bccontrol, scheme='TH')

    nu = femp['charlen']/Re
    # specify in what spatial direction Bu changes. The remaining is constant
    uspacedep = femp['uspacedep']

    # casting some parameters
    invinds, NV = femp['invinds'], len(femp['invinds'])

    prbstr = '_bt' if plain_bt else '_lqgbt'
    # contsetupstr = 'NV{0}NU{1}NY{2}alphau{3}'.format(NV, NU, NY, alphau)
    if bccontrol:
        import scipy.sparse as sps
        contsetupstr = 'NV{0}_bcc_NY{1}'.format(NV, NY)
        stokesmatsc['A'] = stokesmatsc['A'] + 1./palpha*stokesmatsc['Arob']
        b_mat = 1./palpha*stokesmatsc['Brob']
        u_masmat = sps.eye(b_mat.shape[1], format='csr')
    else:
        contsetupstr = 'NV{0}NU{1}NY{2}'.format(NV, NU, NY)

    def get_fdstr(Re):
        return ddir + problemname + '_Re{0}_'.format(Re) + \
            contsetupstr + prbstr

    fdstr = get_fdstr(Re)

    soldict = stokesmatsc  # containing A, J, JT
    soldict.update(femp)  # adding V, Q, invinds, diribcs
    # soldict.update(rhsd_vfrc)  # adding fvc, fpr
    soldict.update(fv=rhsd_stbc['fv']+rhsd_vfrc['fvc'],
                   fp=rhsd_stbc['fp']+rhsd_vfrc['fpr'],
                   N=N, nu=nu, data_prfx=fdstr)

#
# Prepare for control
#

    # get the control and observation operators
    if not bccontrol:
        try:
            b_mat = dou.load_spa(ddir + contsetupstr + '__b_mat')
            u_masmat = dou.load_spa(ddir + contsetupstr + '__u_masmat')
            print 'loaded `b_mat`'
        except IOError:
            print 'computing `b_mat`...'
            b_mat, u_masmat = cou.get_inp_opa(cdcoo=femp['cdcoo'], V=femp['V'],
                                              NU=NU, xcomp=uspacedep)
            dou.save_spa(b_mat, ddir + contsetupstr + '__b_mat')
            dou.save_spa(u_masmat, ddir + contsetupstr + '__u_masmat')

        b_mat = b_mat[invinds, :][:, :]
        # tb_mat = 1./np.sqrt(alphau)

    try:
        mc_mat = dou.load_spa(ddir + contsetupstr + '__mc_mat')
        y_masmat = dou.load_spa(ddir + contsetupstr + '__y_masmat')
        print 'loaded `c_mat`'
    except IOError:
        print 'computing `c_mat`...'
        mc_mat, y_masmat = cou.get_mout_opa(odcoo=femp['odcoo'],
                                            V=femp['V'], NY=NY)
        dou.save_spa(mc_mat, ddir + contsetupstr + '__mc_mat')
        dou.save_spa(y_masmat, ddir + contsetupstr + '__y_masmat')

    c_mat = lau.apply_massinv(y_masmat, mc_mat, output='sparse')
    # restrict the operators to the inner nodes

    mc_mat = mc_mat[:, invinds][:, :]
    c_mat = c_mat[:, invinds][:, :]
    c_mat_reg = lau.app_prj_via_sadpnt(amat=stokesmatsc['M'],
                                       jmat=stokesmatsc['J'],
                                       rhsv=c_mat.T,
                                       transposedprj=True).T

    # c_mat_reg = np.array(c_mat.todense())

    # TODO: right choice of norms for y
    #       and necessity of regularization here
    #       by now, we go on number save
#
# setup the system for the correction
#
#
# compute the uncontrolled steady state Stokes solution
#
    v_ss_nse, list_norm_nwtnupd = snu.solve_steadystate_nse(**soldict)
    (convc_mat, rhs_con,
     rhsv_conbc) = snu.get_v_conv_conts(prev_v=v_ss_nse, invinds=invinds,
                                        V=femp['V'], diribcs=femp['diribcs'])

    f_mat = - stokesmatsc['A'] - convc_mat
    mmat = stokesmatsc['M']

    # ssv_rhs = rhsv_conbc + rhsv_conbc + rhsd_vfrc['fvc'] + rhsd_stbc['fv']

    if plain_bt:
        get_gramians = pru.solve_proj_lyap_stein
    else:
        get_gramians = pru.proj_alg_ric_newtonadi

    truncstr = '__lqgbtcv{0}'.format(trunc_lqgbtcv)
    try:
        tl = dou.load_npa(fdstr + '__tl' + truncstr)
        tr = dou.load_npa(fdstr + '__tr' + truncstr)
        print 'loaded the left and right transformations: \n' + \
            fdstr + '__tl/__tr' + truncstr
    except IOError:
        print 'computing the left and right transformations' + \
            ' and saving to: \n' + fdstr + '__tl/__tr' + truncstr

        try:
            zwc = dou.load_npa(fdstr + '__zwc')
            zwo = dou.load_npa(fdstr + '__zwo')
            print 'loaded factor of the Gramians: \n\t' + \
                fdstr + '__zwc/__zwo'
        except IOError:
            zinic, zinio = None, None
            if use_ric_ini is not None:
                fdstr = get_fdstr(use_ric_ini)
                try:
                    zinic = dou.load_npa(fdstr + '__zwc')
                    zinio = dou.load_npa(fdstr + '__zwo')
                    print 'Initialize Newton ADI by zwc/zwo from ' + fdstr
                except IOError:
                    raise UserWarning('No initial guess with Re={0}'.
                                      format(use_ric_ini))

            fdstr = get_fdstr(Re)
            print 'computing factors of Gramians: \n\t' + \
                fdstr + '__zwc/__zwo'

            def compobsg():
                try:
                    zwo = dou.load_npa(fdstr + '__zwo')
                    print 'at least __zwo is there'
                except IOError:
                    zwo = get_gramians(mmat=mmat.T, amat=f_mat.T,
                                       jmat=stokesmatsc['J'],
                                       bmat=c_mat_reg.T, wmat=b_mat,
                                       nwtn_adi_dict=nap,
                                       z0=zinio)['zfac']
                    dou.save_npa(zwo, fdstr + '__zwo')

            def compcong():
                try:
                    zwc = dou.load_npa(fdstr + '__zwc')
                    print 'at least __zwc is there'
                except IOError:
                    zwc = get_gramians(mmat=mmat, amat=f_mat,
                                       jmat=stokesmatsc['J'],
                                       bmat=b_mat, wmat=c_mat_reg.T,
                                       nwtn_adi_dict=nap,
                                       z0=zinic)['zfac']
                    dou.save_npa(zwc, fdstr + '__zwc')

            if multiproc:
                print '\n ### multithread start - ' +\
                    'output might be intermangled'
                p1 = multiprocessing.Process(target=compobsg)
                p2 = multiprocessing.Process(target=compcong)
                p1.start()
                p2.start()
                p1.join()
                p2.join()
                print '### multithread end'

            else:
                compobsg()
                compcong()

            zwc = dou.load_npa(fdstr + '__zwc')
            zwo = dou.load_npa(fdstr + '__zwo')

        print 'computing the left and right transformations' + \
            ' and saving to:\n' + fdstr + '__tr/__tl' + truncstr

        tl, tr = btu.\
            compute_lrbt_transfos(zfc=zwc, zfo=zwo,
                                  mmat=stokesmatsc['M'],
                                  trunck={'threshh': trunc_lqgbtcv})
        dou.save_npa(tl, fdstr + '__tl' + truncstr)
        dou.save_npa(tr, fdstr + '__tr' + truncstr)

    print 'NV = {0}, NP = {2}, k = {1}'.\
        format(tl.shape[0], tl.shape[1], stokesmatsc['J'].shape[0])

    if comp_freqresp:
        btu.compare_freqresp(mmat=stokesmatsc['M'], amat=f_mat,
                             jmat=stokesmatsc['J'], bmat=b_mat,
                             cmat=c_mat, tr=tr, tl=tl,
                             plot=True, datastr=fdstr + '__tl' + truncstr)

    if comp_stepresp is not False:
        if comp_stepresp == 'nonlinear':
            stp_rsp_nwtn = 3
            stp_rsp_dtpr = 'nonl_stepresp_'
        else:
            stp_rsp_nwtn = 1
            stp_rsp_dtpr = 'stepresp_'

        def fullstepresp_lnse(bcol=None, trange=None, ini_vel=None,
                              cmat=None, soldict=None):
            soldict.update(fv_stbc=rhsd_stbc['fv']+bcol,
                           vel_nwtn_stps=stp_rsp_nwtn, trange=trange,
                           iniv=ini_vel, lin_vel_point=ini_vel,
                           clearprvdata=True, data_prfx=stp_rsp_dtpr,
                           return_dictofvelstrs=True)

            dictofvelstrs = snu.solve_nse(**soldict)

            return cou.extract_output(strdict=dictofvelstrs, tmesh=trange,
                                      c_mat=cmat, load_data=dou.load_npa)

    # differences in the initial vector
    # print np.dot(c_mat_reg, v_ss_nse)
    # print np.dot(np.dot(c_mat_reg, tr),
    #              np.dot(tl.T, stokesmatsc['M']*v_ss_nse))

        jsonstr = fdstr + stp_rsp_dtpr + '_Nred{0}_t0tENts{1}{2}{3}.json'.\
            format(tl.shape[1], t0, tE, Nts)
        btu.compare_stepresp(tmesh=np.linspace(t0, tE, Nts),
                             a_mat=f_mat, c_mat=c_mat_reg, b_mat=b_mat,
                             m_mat=stokesmatsc['M'],
                             tr=tr, tl=tl, iniv=v_ss_nse,
                             # ss_rhs=ssv_rhs,
                             fullresp=fullstepresp_lnse, fsr_soldict=soldict,
                             plot=True, jsonstr=jsonstr)

# compute the regulated system
    trange = np.linspace(t0, tE, Nts)

    if closed_loop is False:
        return

    elif closed_loop == 'full_state_fb':
        zwc = dou.load_npa(fdstr + '__zwc')
        zwo = dou.load_npa(fdstr + '__zwo')

        mtxtb = pru.get_mTzzTtb(stokesmatsc['M'].T, zwc, b_mat)

        def fv_tmdp_fullstatefb(time=None, curvel=None,
                                linv=None, tb_mat=None, tbxm_mat=None, **kw):
            """realizes a full state static feedback as a function

            that can be passed to a solution routine for the
            unsteady Navier-Stokes equations

            Parameters
            ----------
            time : real
                current time
            curvel : (N,1) nparray
                current velocity
            linv : (N,1) nparray
                linearization point for the linear model
            tb_mat : (N,K) nparray
                input matrix containing the input weighting
            tbxm_mat : (N,K) nparray
                `tb_mat * gain * mass`

            Returns
            -------
            actua : (N,1) nparray
                current contribution to the right-hand side
            , : dictionary
                dummy `{}` for consistency
            """

            actua = -lau.comp_uvz_spdns(tb_mat, tbxm_mat, curvel-linv)
            # actua = 0*curvel
            print '\nnorm of deviation', np.linalg.norm(curvel-linv)
            # print 'norm of actuation {0}'.format(np.linalg.norm(actua))
            return actua, {}

        tmdp_fsfb_dict = dict(linv=v_ss_nse, tb_mat=b_mat, tbxm_mat=mtxtb.T)

        fv_tmdp = fv_tmdp_fullstatefb
        fv_tmdp_params = tmdp_fsfb_dict
        fv_tmdp_memory = None

    elif closed_loop == 'red_output_fb':
        try:
            xok = dou.load_npa(fdstr+truncstr+'__xok')
            xck = dou.load_npa(fdstr+truncstr+'__xck')
            ak_mat = dou.load_npa(fdstr+truncstr+'__ak_mat')
            ck_mat = dou.load_npa(fdstr+truncstr+'__ck_mat')
            bk_mat = dou.load_npa(fdstr+truncstr+'__bk_mat')
        except IOError:
            print 'couldn"t load the red system - compute it'
            zwc = dou.load_npa(fdstr + '__zwc')
            zwo = dou.load_npa(fdstr + '__zwo')

            ak_mat = np.dot(tl.T, f_mat*tr)
            ck_mat = lau.mm_dnssps(c_mat_reg, tr)
            bk_mat = lau.mm_dnssps(tl.T, b_mat)

            tltm, trtm = tl.T*stokesmatsc['M'], tr.T*stokesmatsc['M']
            xok = np.dot(np.dot(tltm, zwo), np.dot(zwo.T, tltm.T))
            xck = np.dot(np.dot(trtm, zwc), np.dot(zwc.T, trtm.T))

            dou.save_npa(xok, fdstr+truncstr+'__xok')
            dou.save_npa(xck, fdstr+truncstr+'__xck')
            dou.save_npa(ak_mat, fdstr+truncstr+'__ak_mat')
            dou.save_npa(ck_mat, fdstr+truncstr+'__ck_mat')
            dou.save_npa(bk_mat, fdstr+truncstr+'__bk_mat')

        obs_bk = np.dot(xok, ck_mat.T)
        DT = (tE - t0)/(Nts-1)

        sysmatk_inv = np.linalg.inv(np.eye(ak_mat.shape[1]) - DT*(ak_mat -
                                    np.dot(np.dot(xok, ck_mat.T), ck_mat) -
                                    np.dot(bk_mat, np.dot(bk_mat.T, xck))))

        def fv_tmdp_redoutpfb(time=None, curvel=None, memory=None,
                              linvel=None,
                              ipsysk_mat_inv=None,
                              obs_bk=None, cts=None,
                              b_mat=None, c_mat=None,
                              xck=None, bk_mat=None,
                              **kw):
            """realizes a reduced static output feedback as a function

            that can be passed to a solution routine for the
            unsteady Navier-Stokes equations

            For convinience the
            Parameters
            ----------
            time : real
                current time
            curvel : (N,1) nparray
                current velocity. For consistency, the full state is taken
                as input. However, internally, we only use the observation
                `y = c_mat*curvel`
            memory : dictionary
                contains values from previous call, in particular the
                previous state estimate
            linvel : (N,1) nparray
                linearization point for the linear model
            ipsysk_mat_inv : (K,K) nparray
                inverse of the system matrix that defines the update
                of the state estimate
            obs_bk : (K,NU) nparray
                input matrix in the observer
            cts : real
                time step length
            b_mat : (N,NU) sparse matrix
                input matrix of the full system
                c_mat=None,
            c_mat : (NY,N) sparse matrix
                output matrix of the full system
            xck : (K,K) nparray
                reduced solution of the CARE
            bk_mat : (K,NU) nparray
                reduced input matrix

            Returns
            -------
            actua : (N,1) nparray
                the current actuation
            memory : dictionary
                to be passed back in the next timestep

            """
            xk_old = memory['xk_old']
            buk = cts*np.dot(obs_bk,
                             lau.mm_dnssps(c_mat, (curvel-linvel)))
            xk_old = np.dot(ipsysk_mat_inv, xk_old + buk)
            #         cts*np.dot(obs_bk,
            #                 lau.mm_dnssps(c_mat, (curvel-linvel))))
            memory['xk_old'] = xk_old
            actua = -lau.mm_dnssps(b_mat,
                                   np.dot(bk_mat.T, np.dot(xck, xk_old)))
            print '\nnorm of deviation', np.linalg.norm(curvel-linvel)
            print 'norm of actuation {0}'.format(np.linalg.norm(actua))
            return actua, memory

        fv_rofb_dict = dict(cts=DT, linvel=v_ss_nse, b_mat=b_mat,
                            c_mat=c_mat_reg, obs_bk=obs_bk, bk_mat=bk_mat,
                            ipsysk_mat_inv=sysmatk_inv, xck=xck)

        fv_tmdp = fv_tmdp_redoutpfb
        fv_tmdp_params = fv_rofb_dict
        fv_tmdp_memory = dict(xk_old=np.zeros((tl.shape[1], 1)))

    else:
        fv_tmdp = None
        fv_tmdp_params = {}
        fv_tmdp_memory = {}

    perturbini = perturbpara*np.ones((NV, 1))
    reg_pertubini = lau.app_prj_via_sadpnt(amat=stokesmatsc['M'],
                                           jmat=stokesmatsc['J'],
                                           rhsv=perturbini)

    soldict.update(fv_stbc=rhsd_stbc['fv'],
                   trange=trange,
                   iniv=v_ss_nse + reg_pertubini,
                   lin_vel_point=None,
                   clearprvdata=True, data_prfx=fdstr + truncstr,
                   fv_tmdp=fv_tmdp,
                   comp_nonl_semexp=True,
                   fv_tmdp_params=fv_tmdp_params,
                   fv_tmdp_memory=fv_tmdp_memory,
                   return_dictofvelstrs=True)

    outstr = truncstr + '{0}'.format(closed_loop) \
        + 't0{0}tE{1}Nts{2}N{3}Re{4}'.format(t0, tE, Nts, N, Re)
    if paraoutput:
        soldict.update(paraviewoutput=True,
                       vfileprfx='results/vel_'+outstr,
                       pfileprfx='results/p_'+outstr)

    dictofvelstrs = snu.solve_nse(**soldict)

    yscomplist = cou.extract_output(strdict=dictofvelstrs, tmesh=trange,
                                    c_mat=c_mat, load_data=dou.load_npa)

    dou.save_output_json(dict(tmesh=trange.tolist(), outsig=yscomplist),
                         fstring=fdstr + truncstr + '{0}'.format(closed_loop) +
                         't0{0}tE{1}Nts{2}'.format(t0, tE, Nts) +
                         'inipert{0}'.format(perturbpara))

    dou.plot_outp_sig(tmesh=trange, outsig=yscomplist)
Example #5
0
def compare_freqresp(mmat=None,
                     amat=None,
                     jmat=None,
                     bmat=None,
                     cmat=None,
                     tr=None,
                     tl=None,
                     ahat=None,
                     bhat=None,
                     chat=None,
                     plot=False,
                     datastr=None):
    """
    compare the frequency response of the original and the reduced model

    cf. [HeiSS08, p. 1059] but with B_2 = 0

    Returns
    -------
    freqrel : list of floats
        the frob norm of the transferfunction at a frequency range
    red_freqrel : list of floats
        from of the tf of the reduced model at the same frequencies
    absci : list of floats
        frequencies where the tfs are evaluated at
    """

    if ahat is None:
        ahat = np.dot(tl.T, amat * tr)
    if bhat is None:
        bhat = tl.T * bmat
    if chat is None:
        chat = cmat * tr

    NV, red_nv = amat.shape[0], ahat.shape[0]

    imunit = 1j

    absci = np.logspace(-4, 8, base=10)

    freqrel, red_freqrel, diff_freqrel = [], [], []

    for omega in absci:
        sadib = lau.solve_sadpnt_smw(amat=omega * imunit * mmat - amat,
                                     jmat=jmat,
                                     rhsv=bmat)
        freqrel.append(np.linalg.norm(cmat * sadib[:NV, :]))
        # print freqrel[-1]

        aib = np.linalg.solve(omega * imunit * np.eye(red_nv) - ahat, bhat)
        red_freqrel.append(np.linalg.norm(np.dot(chat, aib)))
        diff_freqrel.append(
            np.linalg.norm(np.dot(chat, aib) - cmat * sadib[:NV, :]))
        # print red_freqrel[-1]

    if datastr is not None:
        dou.save_output_json(dict(tmesh=absci.tolist(),
                                  fullsysfr=freqrel,
                                  redsysfr=red_freqrel,
                                  diffsysfr=diff_freqrel),
                             fstring=datastr + 'forfreqrespplot')

    if plot:
        legstr = [
            'NV was {0}'.format(mmat.shape[0]),
            'nv is {0}'.format(tr.shape[1]), 'difference'
        ]
        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.plot(absci, freqrel, color='b', linewidth=2.0)
        ax.plot(absci, red_freqrel, color='r', linewidth=2.0)
        ax.plot(absci, diff_freqrel, color='b', linewidth=1.0)
        plt.legend(legstr, loc=3)
        plt.semilogx()
        plt.semilogy()
        plt.show(block=False)

        from matplotlib2tikz import save as tikz_save
        tikz_save(datastr + 'freqresp.tikz',
                  figureheight='\\figureheight',
                  figurewidth='\\figurewidth')

    return freqrel, red_freqrel, absci
Example #6
0
def compare_stepresp(tmesh=None,
                     a_mat=None,
                     c_mat=None,
                     b_mat=None,
                     m_mat=None,
                     tl=None,
                     tr=None,
                     iniv=None,
                     fullresp=None,
                     fsr_soldict=None,
                     plot=False,
                     jsonstr=None):
    """ compare the system's step response to unit inputs in time domain

    with reduced system's response.

    We consider the system

    .. math::

        M\\dot v = Av + Bu, \\quad y = Cv

    on the discretized time interval :math:`(t_0, t_E)`

    and the reduced system with :math:`\\hat A = t_l^TAt_r`.

    Parameters
    ----------
    tmesh : iterable list or ndarray
        vector of the time instances
    a_mat : (N,N) sparse matrix
        system matrix
    c_mat : (ny,N) sparse matrix or ndarray
        output matrix
    b_mat : (N,nu) sparse matrix or ndarray
        input operator
    m_mat : (N,N) sparse matrix
        mass matrix
    tl, tr : (N,K) ndarrays
        left, right transformation for the reduced system
    iniv : (N,1) ndarray
        initial value and linearization point of the full system
    fullresp : callable f(v, **dict)
        returns the response of the full system
    fsr_soldict : dictionary
        parameters to be passed to `fullresp`
    plot : boolean, optional
        whether to plot, defaults to `False`
    jsonstr: string, optional
        if defined, the output is stored in this json file, defaults to `None`
    """

    from scipy.integrate import odeint

    ahat = np.dot(tl.T, a_mat * tr)
    chat = lau.mm_dnssps(c_mat, tr)

    inivhat = np.dot(tl.T, m_mat * iniv)

    inivout = lau.mm_dnssps(c_mat, iniv).tolist()

    red_stp_rsp, ful_stp_rsp = [], []
    for ccol in [0]:  # , b_mat.shape[1]-1]:  # range(2):  # b_mat.shape[1]):
        bmc = b_mat[:, ccol][:, :]
        red_bmc = tl.T * bmc

        def dtfunc(v, t):
            return (np.dot(ahat, v).flatten() + red_bmc.flatten())  # +\

        red_state = odeint(dtfunc, 0 * inivhat.flatten(), tmesh)
        red_stp_rsp.append(np.dot(chat, red_state.T).T.tolist())
        ful_stp_rsp.append(
            fullresp(bcol=bmc,
                     trange=tmesh,
                     ini_vel=iniv,
                     cmat=c_mat,
                     soldict=fsr_soldict))

    if jsonstr:
        try:
            tmesh = tmesh.tolist()
        except AttributeError:
            pass  # is a list already
        dou.save_output_json(datadict={
            "tmesh": tmesh,
            "ful_stp_rsp": ful_stp_rsp,
            "red_stp_rsp": red_stp_rsp,
            "inivout": inivout
        },
                             fstring=jsonstr,
                             module='sadptprj_riclyap_adi.bal_trunc_utils',
                             plotroutine='plot_step_resp')

    if plot:
        plot_step_resp(tmesh=tmesh,
                       red_stp_rsp=red_stp_rsp,
                       ful_stp_rsp=ful_stp_rsp,
                       inivout=inivout)