示例#1
0
def optcon_nse(problemname='drivencavity',
               N=10,
               Nts=10,
               nu=1e-2,
               clearprvveldata=False,
               ini_vel_stokes=False,
               stst_control=False,
               closed_loop=True,
               outernwtnstps=1,
               t0=None,
               tE=None,
               use_ric_ini_nu=None,
               alphau=1e-9,
               gamma=1e-3,
               spec_tip_dict=None,
               nwtn_adi_dict=None,
               linearized_nse=False,
               stokes_flow=False,
               ystar=None):

    tip = time_int_params(Nts, t0=t0, tE=tE)
    if spec_tip_dict is not None:
        tip.update(spec_tip_dict)
    if nwtn_adi_dict is not None:
        tip['nwtn_adi_dict'] = nwtn_adi_dict

    problemdict = dict(drivencavity=dnsps.drivcav_fems,
                       cylinderwake=dnsps.cyl_fems)

    problemfem = problemdict[problemname]
    femp = problemfem(N)

    # output
    ddir = 'data/'
    try:
        os.chdir(ddir)
    except OSError:
        raise Warning('need "' + ddir + '" subdir for storing the data')
    os.chdir('..')

    if linearized_nse and not outernwtnstps == 1:
        raise Warning('Linearized problem can have only one Newton step')

    if closed_loop:
        if stst_control:
            data_prfx = ddir + 'stst_' + problemname + '__'
        else:
            data_prfx = ddir + 'tdst_' + problemname + '__'

    else:
        data_prfx = ddir + problemname + '__'

    if stokes_flow:
        data_prfx = data_prfx + 'stokes__'

    # specify in what spatial direction Bu changes. The remaining is constant
    if problemname == 'drivencavity':
        uspacedep = 0
    elif problemname == 'cylinderwake':
        uspacedep = 1

    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'])

    print 'Dimension of the div matrix: ', stokesmatsc['J'].shape
    # 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)

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

    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,
                   trange=tip['tmesh'],
                   get_datastring=get_datastr,
                   data_prfx=data_prfx,
                   clearprvdata=clearprvveldata,
                   paraviewoutput=tip['ParaviewOutput'],
                   vfileprfx=tip['proutdir'] + 'vel_',
                   pfileprfx=tip['proutdir'] + 'p_')

    #
    # Prepare for control
    #

    contp = ContParams(femp['odcoo'], ystar=ystar, alphau=alphau, gamma=gamma)
    # casting some parameters
    NY, NU = contp.NY, contp.NU

    contsetupstr = problemname + '__NV{0}NU{1}NY{2}'.format(NV, NU, NY)

    # get the control and observation operators
    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')
    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')

    # restrict the operators to the inner nodes
    mc_mat = mc_mat[:, invinds][:, :]
    b_mat = b_mat[invinds, :][:, :]

    # for further use:
    c_mat = lau.apply_massinv(y_masmat, mc_mat, output='sparse')

    if contp.ystarx is None:
        c_mat = c_mat[NY:, :][:, :]  # TODO: Do this right
        mc_mat = mc_mat[NY:, :][:, :]  # TODO: Do this right
        y_masmat = y_masmat[:NY, :][:, :NY]  # TODO: Do this right

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

    # set the weighing matrices
    contp.R = contp.alphau * u_masmat

    #
    # solve the differential-alg. Riccati eqn for the feedback gain X
    # via computing factors Z, such that X = -Z*Z.T
    #
    # at the same time we solve for the affine-linear correction w
    #

    # tilde B = BR^{-1/2}
    tb_mat = lau.apply_invsqrt_fromright(contp.R, b_mat, output='sparse')
    # tb_dense = np.array(tb_mat.todense())

    trct_mat = lau.apply_invsqrt_fromright(y_masmat,
                                           mct_mat_reg,
                                           output='dense')

    if closed_loop:
        cntpstr = 'NV{3}NY{0}NU{1}alphau{2}gamma{4}'.\
            format(contp.NU, contp.NY, contp.alphau, NV, contp.gamma)
    else:
        cntpstr = ''

    # we gonna use this quite often
    M, A = stokesmatsc['M'], stokesmatsc['A']
    datastrdict = dict(time=None, meshp=N, nu=nu, Nts=Nts, data_prfx=data_prfx)

    # compute the uncontrolled steady state (Navier-)Stokes solution
    # as initial value
    if ini_vel_stokes:
        # compute the uncontrolled steady state Stokes solution
        ini_vel, newtonnorms = snu.solve_steadystate_nse(vel_nwtn_stps=0,
                                                         vel_pcrd_stps=0,
                                                         **soldict)
        soldict.update(dict(iniv=ini_vel))
    else:
        ini_vel, newtonnorms = snu.solve_steadystate_nse(**soldict)
        soldict.update(dict(iniv=ini_vel))

    if closed_loop:
        if stst_control:
            if stokes_flow:
                convc_mat = sps.csr_matrix((NV, NV))
                rhs_con, rhsv_conbc = np.zeros((NV, 1)), np.zeros((NV, 1))
                lin_point = None
            else:
                lin_point, newtonnorms = snu.solve_steadystate_nse(**soldict)
                (convc_mat, rhs_con,
                 rhsv_conbc) = snu.get_v_conv_conts(prev_v=lin_point,
                                                    invinds=invinds,
                                                    V=femp['V'],
                                                    diribcs=femp['diribcs'])
            # infinite control horizon, steady target state
            cdatstr = get_datastr(time=None,
                                  meshp=N,
                                  nu=nu,
                                  Nts=None,
                                  data_prfx=data_prfx)

            try:
                Z = dou.load_npa(cdatstr + cntpstr + '__Z')
                print 'loaded ' + cdatstr + cntpstr + '__Z'
            except IOError:
                if use_ric_ini_nu is not None:
                    cdatstr = get_datastr(nwtn=None,
                                          time=None,
                                          meshp=N,
                                          nu=use_ric_ini_nu,
                                          Nts=None,
                                          data_prfx=data_prfx)
                    try:
                        zini = dou.load_npa(ddir + cdatstr + cntpstr + '__Z')
                        print 'Initialize Newton ADI by Z from ' + cdatstr
                    except IOError:
                        raise Warning('No data for initialization of '
                                      ' Newton ADI -- need ' + cdatstr + '__Z')
                    cdatstr = get_datastr(meshp=N, nu=nu, data_prfx=data_prfx)
                else:
                    zini = None

                parnadi = pru.proj_alg_ric_newtonadi
                Z = parnadi(mmat=M,
                            amat=-A - convc_mat,
                            jmat=stokesmatsc['J'],
                            bmat=tb_mat,
                            wmat=trct_mat,
                            z0=zini,
                            nwtn_adi_dict=tip['nwtn_adi_dict'])['zfac']

                dou.save_npa(Z, fstring=cdatstr + cntpstr + '__Z')
                print 'saved ' + cdatstr + cntpstr + '__Z'

                if tip['compress_z']:
                    Zc = pru.compress_Zsvd(Z,
                                           thresh=tip['comprz_thresh'],
                                           k=tip['comprz_maxc'])
                    Z = Zc

            fvnstst = rhs_con + rhsv_conbc + rhsd_stbc['fv'] + rhsd_vfrc['fvc']

            # X = -ZZ.T
            mtxtb_stst = -pru.get_mTzzTtb(M.T, Z, tb_mat)
            mtxfv_stst = -pru.get_mTzzTtb(M.T, Z, fvnstst)

            fl = mc_mat.T * contp.ystarvec(0)

            wft = lau.solve_sadpnt_smw(amat=A.T + convc_mat.T,
                                       jmat=stokesmatsc['J'],
                                       rhsv=fl + mtxfv_stst,
                                       umat=mtxtb_stst,
                                       vmat=tb_mat.T)[:NV]

            auxstrg = cdatstr + cntpstr
            dou.save_npa(wft, fstring=cdatstr + cntpstr + '__w')
            dou.save_npa(mtxtb_stst, fstring=cdatstr + cntpstr + '__mtxtb')
            feedbackthroughdict = {
                None: dict(w=auxstrg + '__w', mtxtb=auxstrg + '__mtxtb')
            }

            cns = 0
            soldict.update(data_prfx=data_prfx + '_cns{0}'.format(cns))
            if linearized_nse:
                soldict.update(vel_pcrd_stps=0,
                               vel_nwtn_stps=1,
                               lin_vel_point={None: lin_point})
            dictofvels = snu.\
                solve_nse(return_dictofvelstrs=True,
                          closed_loop=True,
                          static_feedback=True,
                          tb_mat=tb_mat,
                          stokes_flow=stokes_flow,
                          clearprvveldata=True,
                          feedbackthroughdict=feedbackthroughdict, **soldict)

        else:  # time dep closed loop

            cns_data_prfx = 'data/cnsvars'
            invd = init_nwtnstps_value_dict
            curnwtnsdict = invd(tmesh=tip['tmesh'], data_prfx=cns_data_prfx)
            # initialization: compute the forward solution
            if stokes_flow:
                dictofvels = None
            else:
                dictofvels = snu.solve_nse(return_dictofvelstrs=True,
                                           stokes_flow=stokes_flow,
                                           **soldict)

            # dbs.plot_vel_norms(tip['tmesh'], dictofvels)

            # function for the time depending parts
            # -- to be passed to the solver
            def get_tdpart(time=None,
                           dictofvalues=None,
                           feedback=False,
                           V=None,
                           invinds=None,
                           diribcs=None,
                           **kw):

                if stokes_flow:
                    convc_mat = sps.csr_matrix((NV, NV))
                    rhs_con, rhsv_conbc = np.zeros((NV, 1)), np.zeros((NV, 1))
                else:
                    curvel = dou.load_npa(dictofvalues[time])
                    convc_mat, rhs_con, rhsv_conbc = \
                        snu.get_v_conv_conts(prev_v=curvel, invinds=invinds,
                                             V=V, diribcs=diribcs)

                return convc_mat, rhsv_conbc + rhs_con

            gttdprtargs = dict(dictofvalues=dictofvels,
                               V=femp['V'],
                               diribcs=femp['diribcs'],
                               invinds=invinds)

            # old version rhs
            # ftilde = rhs_con + rhsv_conbc + rhsd_stbc['fv']
            for cns in range(outernwtnstps):

                datastrdict.update(data_prfx=data_prfx + cntpstr +
                                   '_cns{0}'.format(cns))
                soldict.update(data_prfx=data_prfx + cntpstr +
                               '_cns{0}'.format(cns))

                sfd = sdr.solve_flow_daeric
                feedbackthroughdict = \
                    sfd(mmat=M, amat=A, jmat=stokesmatsc['J'],
                        bmat=b_mat,
                        # cmat=ct_mat_reg.T,
                        mcmat=mct_mat_reg.T,
                        v_is_my=True, rmat=contp.alphau*u_masmat,
                        vmat=y_masmat, rhsv=rhsd_stbc['fv'],
                        gamma=contp.gamma,
                        rhsp=None,
                        tmesh=tip['tmesh'], ystarvec=contp.ystarvec,
                        nwtn_adi_dict=tip['nwtn_adi_dict'],
                        comprz_thresh=tip['comprz_thresh'],
                        comprz_maxc=tip['comprz_maxc'], save_full_z=False,
                        get_tdpart=get_tdpart, gttdprtargs=gttdprtargs,
                        curnwtnsdict=curnwtnsdict,
                        get_datastr=get_datastr, gtdtstrargs=datastrdict)

                # for t in tip['tmesh']:  # feedbackthroughdict.keys():
                #     curw = dou.load_npa(feedbackthroughdict[t]['mtxtb'])
                #     print cns, t, np.linalg.norm(curw)

                cdatstr = get_datastr(time='all',
                                      meshp=N,
                                      nu=nu,
                                      Nts=None,
                                      data_prfx=data_prfx)

                if linearized_nse:
                    dictofvels = snu.\
                        solve_nse(return_dictofvelstrs=True,
                                  closed_loop=True, tb_mat=tb_mat,
                                  lin_vel_point=dictofvels,
                                  feedbackthroughdict=feedbackthroughdict,
                                  vel_nwtn_stps=1,
                                  vel_pcrd_stps=0,
                                  **soldict)
                else:
                    dictofvels = snu.\
                        solve_nse(return_dictofvelstrs=True,
                                  closed_loop=True, tb_mat=tb_mat,
                                  stokes_flow=stokes_flow,
                                  feedbackthroughdict=feedbackthroughdict,
                                  vel_pcrd_stps=1,
                                  vel_nwtn_stps=2,
                                  **soldict)

                # for t in dictofvels.keys():
                #     curw = dou.load_npa(dictofvels[t])
                #     print cns, t, np.linalg.norm(curw)

                gttdprtargs.update(dictofvalues=dictofvels)
    else:
        # no control
        feedbackthroughdict = None
        tb_mat = None
        cdatstr = get_datastr(meshp=N,
                              nu=nu,
                              time='all',
                              Nts=Nts,
                              data_prfx=data_prfx)

        soldict.update(clearprvdata=True)
        dictofvels = snu.solve_nse(feedbackthroughdict=feedbackthroughdict,
                                   tb_mat=tb_mat,
                                   closed_loop=closed_loop,
                                   stokes_flow=stokes_flow,
                                   return_dictofvelstrs=True,
                                   static_feedback=stst_control,
                                   **soldict)

    (yscomplist, ystarlist) = dou.extract_output(dictofpaths=dictofvels,
                                                 tmesh=tip['tmesh'],
                                                 c_mat=c_mat,
                                                 ystarvec=contp.ystarvec)

    save_output_json(yscomplist,
                     tip['tmesh'].tolist(),
                     ystar=ystarlist,
                     fstring=cdatstr + cntpstr + '__sigout')

    costfunval = eval_costfunc(W=y_masmat,
                               V=contp.gamma * y_masmat,
                               R=None,
                               tbmat=tb_mat,
                               cmat=c_mat,
                               ystar=contp.ystarvec,
                               tmesh=tip['tmesh'],
                               veldict=dictofvels,
                               fbftdict=feedbackthroughdict)

    print 'Value of cost functional: ', costfunval

    costfunval = eval_costfunc(W=y_masmat,
                               V=contp.gamma * y_masmat,
                               R=None,
                               tbmat=tb_mat,
                               cmat=c_mat,
                               ystar=contp.ystarvec,
                               penau=False,
                               tmesh=tip['tmesh'],
                               veldict=dictofvels,
                               fbftdict=feedbackthroughdict)

    print 'Value of cost functional not considering `u`: ', costfunval

    print 'dim of v :', femp['V'].dim()
    charlene = .15 if problemname == 'cylinderwake' else 1.0
    print 'Re = charL / nu = {0}'.format(charlene / nu)
示例#2
0
def get_sysmats(problem='drivencavity', N=10, scheme=None, ppin=None,
                Re=None, nu=None, bccontrol=False, mergerhs=False,
                onlymesh=False):
    """ retrieve the system matrices for stokes flow

    Parameters
    ----------
    problem : {'drivencavity', 'cylinderwake'}
        problem class
    N : int
        mesh parameter
    nu : real, optional
        kinematic viscosity, is set to `L/Re` if `Re` is provided
    Re : real, optional
        Reynoldsnumber, is set to `L/nu` if `nu` is provided
    bccontrol : boolean, optional
        whether to consider boundary control via penalized Robin \
        defaults to `False`
    mergerhs : boolean, optional
        whether to merge the actual rhs and the contribution from the \
        boundary conditions into one rhs, defaults to `False`
    onlymesh : boolean, optional
        whether to only return `femp`, containing the mesh and FEM spaces, \
        defaults to `False`

    Returns
    -------
    femp : dict
        with the keys:
         * `V`: FEM space of the velocity
         * `Q`: FEM space of the pressure
         * `diribcs`: list of the (Dirichlet) boundary conditions
         * `bcinds`: indices of the boundary nodes
         * `bcvals`: values of the boundary nodes
         * `invinds`: indices of the inner nodes
         * `fv`: right hand side of the momentum equation
         * `fp`: right hand side of the continuity equation
         * `charlen`: characteristic length of the setup
         * `nu`: the kinematic viscosity
         * `Re`: the Reynolds number
         * `odcoo`: dictionary with the coordinates of the domain of \
                 observation
         * `cdcoo`: dictionary with the coordinates of the domain of \
         * `ppin` : {int, None}
                which dof of `p` is used to pin the pressure, typically \
                `-1` for internal flows, and `None` for flows with outflow
                         control
    stokesmatsc : dict
        a dictionary of the condensed matrices:
         * `M`: the mass matrix of the velocity space,
         * `MP`: the mass matrix of the pressure space,
         * `A`: the stiffness matrix,
         * `JT`: the gradient matrix, and
         * `J`: the divergence matrix
         * `Jfull`: the uncondensed divergence matrix
        and, if `bccontrol=True`, the boundary control matrices that weakly \
        impose `Arob*v = Brob*u`, where
         * `Arob`: contribution to `A`
         * `Brob`: input operator
    `if mergerhs`
    rhsd : dict
        `rhsd_vfrc` and `rhsd_stbc` merged
    `else`
    rhsd_vfrc : dict
        of the dirichlet and pressure fix reduced right hand sides
    rhsd_stbc : dict
        of the contributions of the boundary data to the rhs:
         * `fv`: contribution to momentum equation,
         * `fp`: contribution to continuity equation


    Examples
    --------
    femp, stokesmatsc, rhsd_vfrc, rhsd_stbc \
        = get_sysmats(problem='drivencavity', N=10, nu=1e-2)

    """

    problemdict = dict(drivencavity=drivcav_fems,
                       cylinderwake=cyl_fems)
    problemfem = problemdict[problem]
    femp = problemfem(N, scheme=scheme, bccontrol=bccontrol)
    if onlymesh:
        return femp

    # setting some parameters
    if Re is not None:
        nu = femp['charlen']/Re
    else:
        Re = femp['charlen']/nu

    if bccontrol:
        cbclist = femp['contrbcssubdomains']
        cbshapefuns = femp['contrbcsshapefuns']
    else:
        cbclist, cbshapefuns = None, None

    stokesmats = dts.get_stokessysmats(femp['V'], femp['Q'], nu,
                                       cbclist=cbclist,
                                       cbshapefuns=cbshapefuns,
                                       bccontrol=bccontrol)

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

    # remove the freedom in the pressure if required
    if problem == 'cylinderwake':
        print('cylinderwake: pressure need not be pinned')
        if ppin is not None:
            raise UserWarning('pinning the p will give wrong results')
    elif ppin is None:
        print('pressure is not pinned - `J` may be singular for internal flow')
    elif ppin == -1:
        stokesmats['J'] = stokesmats['J'][:-1, :][:, :]
        stokesmats['JT'] = stokesmats['JT'][:, :-1][:, :]
        rhsd_vf['fp'] = rhsd_vf['fp'][:-1, :]
        print('pressure pinned at last dof `-1`')
    else:
        raise NotImplementedError('Cannot pin `p` other than at `-1`')

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

    # pressure freedom and dirichlet reduced rhs
    rhsd_vfrc = dict(fpr=rhsd_vf['fp'], fvc=rhsd_vf['fv'][invinds, ])
    if bccontrol:
        Arob, fvrob = dts.condense_velmatsbybcs(stokesmats['amatrob'],
                                                femp['diribcs'])
        if np.linalg.norm(fvrob) > 1e-15:
            raise UserWarning('diri and control bc must not intersect')

        Brob = stokesmats['bmatrob'][invinds, :]
        stokesmatsc.update({'Brob': Brob, 'Arob': Arob})

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

    if mergerhs:
        rhsd = dict(fv=rhsd_vfrc['fvc']+rhsd_stbc['fv'],
                    fp=rhsd_vfrc['fpr']+rhsd_stbc['fp'])
        return femp, stokesmatsc, rhsd
    else:
        return femp, stokesmatsc, rhsd_vfrc, rhsd_stbc
示例#3
0
def get_sysmats(problem='drivencavity', N=10, scheme=None, ppin=None,
                Re=None, nu=None, bccontrol=False, mergerhs=False,
                onlymesh=False):
    """ retrieve the system matrices for stokes flow

    Parameters
    ----------
    problem : {'drivencavity', 'cylinderwake'}
        problem class
    N : int
        mesh parameter
    nu : real, optional
        kinematic viscosity, is set to `L/Re` if `Re` is provided
    Re : real, optional
        Reynoldsnumber, is set to `L/nu` if `nu` is provided
    bccontrol : boolean, optional
        whether to consider boundary control via penalized Robin \
        defaults to `False`
    mergerhs : boolean, optional
        whether to merge the actual rhs and the contribution from the \
        boundary conditions into one rhs
    onlymesh : boolean, optional
        whether to only return `femp`, containing the mesh and FEM spaces, \
        defaults to `False`

    Returns
    -------
    femp : dict
        with the keys:
         * `V`: FEM space of the velocity
         * `Q`: FEM space of the pressure
         * `diribcs`: list of the (Dirichlet) boundary conditions
         * `bcinds`: indices of the boundary nodes
         * `bcvals`: values of the boundary nodes
         * `invinds`: indices of the inner nodes
         * `fv`: right hand side of the momentum equation
         * `fp`: right hand side of the continuity equation
         * `charlen`: characteristic length of the setup
         * `nu`: the kinematic viscosity
         * `Re`: the Reynolds number
         * `odcoo`: dictionary with the coordinates of the domain of \
                 observation
         * `cdcoo`: dictionary with the coordinates of the domain of \
         * `ppin` : {int, None}
                which dof of `p` is used to pin the pressure, typically \
                `-1` for internal flows, and `None` for flows with outflow
                         control
    stokesmatsc : dict
        a dictionary of the condensed matrices:
         * `M`: the mass matrix of the velocity space,
         * `A`: the stiffness matrix,
         * `JT`: the gradient matrix, and
         * `J`: the divergence matrix
         * `Jfull`: the uncondensed divergence matrix
        and, if `bccontrol=True`, the boundary control matrices that weakly \
        impose `Arob*v = Brob*u`, where
         * `Arob`: contribution to `A`
         * `Brob`: input operator
    `if mergerhs`
    rhsd : dict
        `rhsd_vfrc` and `rhsd_stbc` merged
    `else`
    rhsd_vfrc : dict
        of the dirichlet and pressure fix reduced right hand sides
    rhsd_stbc : dict
        of the contributions of the boundary data to the rhs:
         * `fv`: contribution to momentum equation,
         * `fp`: contribution to continuity equation


    Examples
    --------
    femp, stokesmatsc, rhsd_vfrc, rhsd_stbc \
        = get_sysmats(problem='drivencavity', N=10, nu=1e-2)

    """

    problemdict = dict(drivencavity=drivcav_fems,
                       cylinderwake=cyl_fems)
    problemfem = problemdict[problem]
    femp = problemfem(N, scheme=scheme, bccontrol=bccontrol)
    if onlymesh:
        return femp

    # setting some parameters
    if Re is not None:
        nu = femp['charlen']/Re
    else:
        Re = femp['charlen']/nu

    if bccontrol:
        cbclist = femp['contrbcssubdomains']
        cbshapefuns = femp['contrbcsshapefuns']
    else:
        cbclist, cbshapefuns = None, None

    stokesmats = dts.get_stokessysmats(femp['V'], femp['Q'], nu,
                                       cbclist=cbclist,
                                       cbshapefuns=cbshapefuns,
                                       bccontrol=bccontrol)

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

    # remove the freedom in the pressure if required
    if problem == 'cylinderwake':
        print 'cylinderwake: pressure need not be pinned'
        if ppin is not None:
            raise UserWarning('pinning the p will give wrong results')
    elif ppin is None:
        print 'pressure is not pinned - `J` may be singular for internal flow'
    elif ppin == -1:
        stokesmats['J'] = stokesmats['J'][:-1, :][:, :]
        stokesmats['JT'] = stokesmats['JT'][:, :-1][:, :]
        rhsd_vf['fp'] = rhsd_vf['fp'][:-1, :]
        print 'pressure pinned at last dof `-1`'
    else:
        raise NotImplementedError('Cannot pin `p` other than at `-1`')

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

    # pressure freedom and dirichlet reduced rhs
    rhsd_vfrc = dict(fpr=rhsd_vf['fp'], fvc=rhsd_vf['fv'][invinds, ])
    if bccontrol:
        Arob, fvrob = dts.condense_velmatsbybcs(stokesmats['amatrob'],
                                                femp['diribcs'])
        if np.linalg.norm(fvrob) > 1e-15:
            raise UserWarning('diri and control bc must not intersect')

        Brob = stokesmats['bmatrob'][invinds, :]
        stokesmatsc.update({'Brob': Brob, 'Arob': Arob})

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

    if mergerhs:
        rhsd = dict(fv=rhsd_vfrc['fvc']+rhsd_stbc['fv'],
                    fp=rhsd_vfrc['fpr']+rhsd_stbc['fp'])
        return femp, stokesmatsc, rhsd
    else:
        return femp, stokesmatsc, rhsd_vfrc, rhsd_stbc
示例#4
0
def lqgbt(problemname='drivencavity',
          N=10, Nts=10, nu=1e-2, plain_bt=True,
          savetomatfiles=False):

    tip = time_int_params(Nts, nu)

    problemdict = dict(drivencavity=dnsps.drivcav_fems,
                       cylinderwake=dnsps.cyl_fems)

    problemfem = problemdict[problemname]
    femp = problemfem(N)

    data_prfx = problemname + '__'
    NU, NY = 3, 4

    # specify in what spatial direction Bu changes. The remaining is constant
    if problemname == 'drivencavity':
        uspacedep = 0
    elif problemname == 'cylinderwake':
        uspacedep = 1

    # 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'],
                                       tip['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)

    # casting some parameters
    NV, DT, INVINDS = len(femp['invinds']), tip['dt'], femp['invinds']

    soldict = stokesmatsc  # containing A, J, JT
    soldict.update(femp)  # adding V, Q, invinds, diribcs
    soldict.update(rhsd_vfrc)  # adding fvc, fpr
    soldict.update(fv_stbc=rhsd_stbc['fv'], fp_stbc=rhsd_stbc['fp'],
                   N=N, nu=tip['nu'],
                   nnewtsteps=tip['nnewtsteps'],
                   vel_nwtn_tol=tip['vel_nwtn_tol'],
                   ddir=ddir, get_datastring=None,
                   data_prfx=data_prfx,
                   paraviewoutput=tip['ParaviewOutput'],
                   vfileprfx=tip['proutdir']+'vel_',
                   pfileprfx=tip['proutdir']+'p_')

#
# compute the uncontrolled steady state Stokes solution
#
    v_ss_nse, list_norm_nwtnupd = snu.solve_steadystate_nse(**soldict)

#
# Prepare for control
#

    contsetupstr = problemname + '__NV{0}NU{1}NY{2}'.format(NV, NU, NY)

    # get the control and observation operators
    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')
    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')

    # restrict the operators to the inner nodes
    mc_mat = mc_mat[:, invinds][:, :]
    b_mat = b_mat[invinds, :][:, :]

    c_mat = lau.apply_massinv(y_masmat, mc_mat, output='sparse')

    # 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
#
    (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

    cdatstr = snu.get_datastr_snu(time=None, meshp=N, nu=tip['nu'],
                                  Nts=None, dt=None)

    if savetomatfiles:
        import datetime
        import scipy.io

        (coors, xinds, 
         yinds, corfunvec) = dts.get_dof_coors(femp['V'], invinds=invinds)

        infostr = 'These are the coefficient matrices of the linearized ' +\
            'Navier-Stokes Equations \n for the ' +\
            problemname + ' to be used as \n\n' +\
            ' $M \\dot v = Av + J^Tp + Bu$   and  $Jv = 0$ \n\n' +\
            ' the Reynoldsnumber is computed as L/nu \n' +\
            ' Note that this is the reduced system for the velocity update\n' +\
            ' caused by the control, i.e., no boundary conditions\n' +\
            ' or inhomogeneities here. To get the actual flow, superpose \n' +\
            ' the steadystate velocity solution `v_ss_nse` \n\n' +\
            ' the control setup is as follows \n' +\
            ' B maps into the domain of control - the first half of the colums' +\
            'actuate in x-direction, the second in y direction \n' +\
            ' C measures averaged velocities in the domain of observation' +\
            ' the first components are in x, the last in y-direction \n\n' +\
            ' Visualization: \n\n' +\
            ' `coors`   -- array of (x,y) coordinates in ' +\
            ' the same order as v[xinds] or v[yinds] \n' +\
            ' `xinds`, `yinds` -- indices of x and y components' +\
            ' of v = [vx, vy] -- note that indexing starts with 0\n' +\
            ' for testing use corfunvec wich is the interpolant of\n' +\
            ' f(x,y) = [x, y] on the grid \n\n' +\
            'Created in `exp_cylinder_mats.py` ' +\
            '(see https://github.com/highlando/lqgbt-oseen) at\n' +\
            datetime.datetime.now().strftime("%I:%M%p on %B %d, %Y")

        mddir = '/afs/mpi-magdeburg.mpg.de/data/csc/projects/qbdae-nse/data/'
        if problemname == 'cylinderwake':
            charlen = 0.15  # diameter of the cylinder
            Re = charlen/nu
        elif problemname == 'drivencavity':
            Re = nu
        else:
            Re = nu
        
        scipy.io.savemat(mddir + problemname +
                         '__mats_N{0}_Re{1}'.format(NV, Re),
                         dict(A=f_mat, M=stokesmatsc['M'], nu=nu, Re=Re,
                              J=stokesmatsc['J'], B=b_mat, C=c_mat,
                              v_ss_nse=v_ss_nse, info=infostr,
                              contsetupstr=contsetupstr, datastr=cdatstr,
                              coors=coors, xinds=xinds, yinds=yinds,
                              corfunvec=corfunvec))

        return
示例#5
0
def optcon_nse(problemname='drivencavity',
               N=10, Nts=10, nu=1e-2, clearprvveldata=False,
               ini_vel_stokes=False, stst_control=False,
               closed_loop=True,
               outernwtnstps=1,
               t0=None, tE=None,
               use_ric_ini_nu=None,
               alphau=1e-9, gamma=1e-3,
               spec_tip_dict=None,
               nwtn_adi_dict=None,
               linearized_nse=False,
               stokes_flow=False,
               ystar=None):

    tip = time_int_params(Nts, t0=t0, tE=tE)
    if spec_tip_dict is not None:
        tip.update(spec_tip_dict)
    if nwtn_adi_dict is not None:
        tip['nwtn_adi_dict'] = nwtn_adi_dict

    problemdict = dict(drivencavity=dnsps.drivcav_fems,
                       cylinderwake=dnsps.cyl_fems)

    problemfem = problemdict[problemname]
    femp = problemfem(N)

    # output
    ddir = 'data/'
    try:
        os.chdir(ddir)
    except OSError:
        raise Warning('need "' + ddir + '" subdir for storing the data')
    os.chdir('..')

    if linearized_nse and not outernwtnstps == 1:
        raise Warning('Linearized problem can have only one Newton step')

    if closed_loop:
        if stst_control:
            data_prfx = ddir + 'stst_' + problemname + '__'
        else:
            data_prfx = ddir + 'tdst_' + problemname + '__'

    else:
        data_prfx = ddir + problemname + '__'

    if stokes_flow:
        data_prfx = data_prfx + 'stokes__'

    # specify in what spatial direction Bu changes. The remaining is constant
    if problemname == 'drivencavity':
        uspacedep = 0
    elif problemname == 'cylinderwake':
        uspacedep = 1

    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'])

    print 'Dimension of the div matrix: ', stokesmatsc['J'].shape
    # 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)

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

    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,
                   trange=tip['tmesh'],
                   get_datastring=get_datastr,
                   data_prfx=data_prfx,
                   clearprvdata=clearprvveldata,
                   paraviewoutput=tip['ParaviewOutput'],
                   vfileprfx=tip['proutdir']+'vel_',
                   pfileprfx=tip['proutdir']+'p_')

#
# Prepare for control
#

    contp = ContParams(femp['odcoo'], ystar=ystar, alphau=alphau, gamma=gamma)
    # casting some parameters
    NY, NU = contp.NY, contp.NU

    contsetupstr = problemname + '__NV{0}NU{1}NY{2}'.format(NV, NU, NY)

    # get the control and observation operators
    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')
    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')

    # restrict the operators to the inner nodes
    mc_mat = mc_mat[:, invinds][:, :]
    b_mat = b_mat[invinds, :][:, :]

    # for further use:
    c_mat = lau.apply_massinv(y_masmat, mc_mat, output='sparse')

    if contp.ystarx is None:
        c_mat = c_mat[NY:, :][:, :]  # TODO: Do this right
        mc_mat = mc_mat[NY:, :][:, :]  # TODO: Do this right
        y_masmat = y_masmat[:NY, :][:, :NY]  # TODO: Do this right

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

    # set the weighing matrices
    contp.R = contp.alphau * u_masmat

#
# solve the differential-alg. Riccati eqn for the feedback gain X
# via computing factors Z, such that X = -Z*Z.T
#
# at the same time we solve for the affine-linear correction w
#

    # tilde B = BR^{-1/2}
    tb_mat = lau.apply_invsqrt_fromright(contp.R, b_mat, output='sparse')
    # tb_dense = np.array(tb_mat.todense())

    trct_mat = lau.apply_invsqrt_fromright(y_masmat,
                                           mct_mat_reg, output='dense')

    if closed_loop:
        cntpstr = 'NV{3}NY{0}NU{1}alphau{2}gamma{4}'.\
            format(contp.NU, contp.NY, contp.alphau, NV, contp.gamma)
    else:
        cntpstr = ''

    # we gonna use this quite often
    M, A = stokesmatsc['M'], stokesmatsc['A']
    datastrdict = dict(time=None, meshp=N, nu=nu, Nts=Nts,
                       data_prfx=data_prfx)

    # compute the uncontrolled steady state (Navier-)Stokes solution
    # as initial value
    if ini_vel_stokes:
        # compute the uncontrolled steady state Stokes solution
        ini_vel, newtonnorms = snu.solve_steadystate_nse(vel_nwtn_stps=0,
                                                         vel_pcrd_stps=0,
                                                         **soldict)
        soldict.update(dict(iniv=ini_vel))
    else:
        ini_vel, newtonnorms = snu.solve_steadystate_nse(**soldict)
        soldict.update(dict(iniv=ini_vel))

    if closed_loop:
        if stst_control:
            if stokes_flow:
                convc_mat = sps.csr_matrix((NV, NV))
                rhs_con, rhsv_conbc = np.zeros((NV, 1)), np.zeros((NV, 1))
                lin_point = None
            else:
                lin_point, newtonnorms = snu.solve_steadystate_nse(**soldict)
                (convc_mat, rhs_con,
                 rhsv_conbc) = snu.get_v_conv_conts(prev_v=lin_point,
                                                    invinds=invinds,
                                                    V=femp['V'],
                                                    diribcs=femp['diribcs'])
            # infinite control horizon, steady target state
            cdatstr = get_datastr(time=None, meshp=N, nu=nu,
                                  Nts=None, data_prfx=data_prfx)

            try:
                Z = dou.load_npa(cdatstr + cntpstr + '__Z')
                print 'loaded ' + cdatstr + cntpstr + '__Z'
            except IOError:
                if use_ric_ini_nu is not None:
                    cdatstr = get_datastr(nwtn=None, time=None, meshp=N,
                                          nu=use_ric_ini_nu, Nts=None,
                                          data_prfx=data_prfx)
                    try:
                        zini = dou.load_npa(ddir + cdatstr
                                            + cntpstr + '__Z')
                        print 'Initialize Newton ADI by Z from ' + cdatstr
                    except IOError:
                        raise Warning('No data for initialization of '
                                      ' Newton ADI -- need ' + cdatstr
                                      + '__Z')
                    cdatstr = get_datastr(meshp=N, nu=nu,
                                          data_prfx=data_prfx)
                else:
                    zini = None

                parnadi = pru.proj_alg_ric_newtonadi
                Z = parnadi(mmat=M, amat=-A-convc_mat,
                            jmat=stokesmatsc['J'],
                            bmat=tb_mat, wmat=trct_mat, z0=zini,
                            nwtn_adi_dict=tip['nwtn_adi_dict'])['zfac']

                dou.save_npa(Z, fstring=cdatstr + cntpstr + '__Z')
                print 'saved ' + cdatstr + cntpstr + '__Z'

                if tip['compress_z']:
                    Zc = pru.compress_Zsvd(Z, thresh=tip['comprz_thresh'],
                                           k=tip['comprz_maxc'])
                    Z = Zc

            fvnstst = rhs_con + rhsv_conbc + rhsd_stbc['fv'] + rhsd_vfrc['fvc']

            # X = -ZZ.T
            mtxtb_stst = -pru.get_mTzzTtb(M.T, Z, tb_mat)
            mtxfv_stst = -pru.get_mTzzTtb(M.T, Z, fvnstst)

            fl = mc_mat.T * contp.ystarvec(0)

            wft = lau.solve_sadpnt_smw(amat=A.T+convc_mat.T,
                                       jmat=stokesmatsc['J'],
                                       rhsv=fl+mtxfv_stst,
                                       umat=mtxtb_stst,
                                       vmat=tb_mat.T)[:NV]

            auxstrg = cdatstr + cntpstr
            dou.save_npa(wft, fstring=cdatstr + cntpstr + '__w')
            dou.save_npa(mtxtb_stst, fstring=cdatstr + cntpstr + '__mtxtb')
            feedbackthroughdict = {None:
                                   dict(w=auxstrg + '__w',
                                        mtxtb=auxstrg + '__mtxtb')}

            cns = 0
            soldict.update(data_prfx=data_prfx+'_cns{0}'.format(cns))
            if linearized_nse:
                soldict.update(vel_pcrd_stps=0,
                               vel_nwtn_stps=1,
                               lin_vel_point={None: lin_point})
            dictofvels = snu.\
                solve_nse(return_dictofvelstrs=True,
                          closed_loop=True,
                          static_feedback=True,
                          tb_mat=tb_mat,
                          stokes_flow=stokes_flow,
                          clearprvveldata=True,
                          feedbackthroughdict=feedbackthroughdict, **soldict)

        else:  # time dep closed loop

            cns_data_prfx = 'data/cnsvars'
            invd = init_nwtnstps_value_dict
            curnwtnsdict = invd(tmesh=tip['tmesh'],
                                data_prfx=cns_data_prfx)
            # initialization: compute the forward solution
            if stokes_flow:
                dictofvels = None
            else:
                dictofvels = snu.solve_nse(return_dictofvelstrs=True,
                                           stokes_flow=stokes_flow,
                                           **soldict)

            # dbs.plot_vel_norms(tip['tmesh'], dictofvels)

            # function for the time depending parts
            # -- to be passed to the solver
            def get_tdpart(time=None, dictofvalues=None, feedback=False,
                           V=None, invinds=None, diribcs=None, **kw):

                if stokes_flow:
                    convc_mat = sps.csr_matrix((NV, NV))
                    rhs_con, rhsv_conbc = np.zeros((NV, 1)), np.zeros((NV, 1))
                else:
                    curvel = dou.load_npa(dictofvalues[time])
                    convc_mat, rhs_con, rhsv_conbc = \
                        snu.get_v_conv_conts(prev_v=curvel, invinds=invinds,
                                             V=V, diribcs=diribcs)

                return convc_mat, rhsv_conbc+rhs_con

            gttdprtargs = dict(dictofvalues=dictofvels,
                               V=femp['V'],
                               diribcs=femp['diribcs'],
                               invinds=invinds)

            # old version rhs
            # ftilde = rhs_con + rhsv_conbc + rhsd_stbc['fv']
            for cns in range(outernwtnstps):

                datastrdict.update(data_prfx=data_prfx+cntpstr+'_cns{0}'.
                                   format(cns))
                soldict.update(data_prfx=data_prfx+cntpstr+'_cns{0}'.
                               format(cns))

                sfd = sdr.solve_flow_daeric
                feedbackthroughdict = \
                    sfd(mmat=M, amat=A, jmat=stokesmatsc['J'],
                        bmat=b_mat,
                        # cmat=ct_mat_reg.T,
                        mcmat=mct_mat_reg.T,
                        v_is_my=True, rmat=contp.alphau*u_masmat,
                        vmat=y_masmat, rhsv=rhsd_stbc['fv'],
                        gamma=contp.gamma,
                        rhsp=None,
                        tmesh=tip['tmesh'], ystarvec=contp.ystarvec,
                        nwtn_adi_dict=tip['nwtn_adi_dict'],
                        comprz_thresh=tip['comprz_thresh'],
                        comprz_maxc=tip['comprz_maxc'], save_full_z=False,
                        get_tdpart=get_tdpart, gttdprtargs=gttdprtargs,
                        curnwtnsdict=curnwtnsdict,
                        get_datastr=get_datastr, gtdtstrargs=datastrdict)

                # for t in tip['tmesh']:  # feedbackthroughdict.keys():
                #     curw = dou.load_npa(feedbackthroughdict[t]['mtxtb'])
                #     print cns, t, np.linalg.norm(curw)

                cdatstr = get_datastr(time='all', meshp=N, nu=nu,
                                      Nts=None, data_prfx=data_prfx)

                if linearized_nse:
                    dictofvels = snu.\
                        solve_nse(return_dictofvelstrs=True,
                                  closed_loop=True, tb_mat=tb_mat,
                                  lin_vel_point=dictofvels,
                                  feedbackthroughdict=feedbackthroughdict,
                                  vel_nwtn_stps=1,
                                  vel_pcrd_stps=0,
                                  **soldict)
                else:
                    dictofvels = snu.\
                        solve_nse(return_dictofvelstrs=True,
                                  closed_loop=True, tb_mat=tb_mat,
                                  stokes_flow=stokes_flow,
                                  feedbackthroughdict=feedbackthroughdict,
                                  vel_pcrd_stps=1,
                                  vel_nwtn_stps=2,
                                  **soldict)

                # for t in dictofvels.keys():
                #     curw = dou.load_npa(dictofvels[t])
                #     print cns, t, np.linalg.norm(curw)

                gttdprtargs.update(dictofvalues=dictofvels)
    else:
        # no control
        feedbackthroughdict = None
        tb_mat = None
        cdatstr = get_datastr(meshp=N, nu=nu, time='all',
                              Nts=Nts, data_prfx=data_prfx)

        soldict.update(clearprvdata=True)
        dictofvels = snu.solve_nse(feedbackthroughdict=feedbackthroughdict,
                                   tb_mat=tb_mat, closed_loop=closed_loop,
                                   stokes_flow=stokes_flow,
                                   return_dictofvelstrs=True,
                                   static_feedback=stst_control,
                                   **soldict)

    (yscomplist,
     ystarlist) = dou.extract_output(dictofpaths=dictofvels,
                                     tmesh=tip['tmesh'],
                                     c_mat=c_mat, ystarvec=contp.ystarvec)

    save_output_json(yscomplist, tip['tmesh'].tolist(), ystar=ystarlist,
                     fstring=cdatstr + cntpstr + '__sigout')

    costfunval = eval_costfunc(W=y_masmat, V=contp.gamma*y_masmat,
                               R=None, tbmat=tb_mat, cmat=c_mat,
                               ystar=contp.ystarvec,
                               tmesh=tip['tmesh'], veldict=dictofvels,
                               fbftdict=feedbackthroughdict)

    print 'Value of cost functional: ', costfunval

    costfunval = eval_costfunc(W=y_masmat, V=contp.gamma*y_masmat,
                               R=None, tbmat=tb_mat, cmat=c_mat,
                               ystar=contp.ystarvec, penau=False,
                               tmesh=tip['tmesh'], veldict=dictofvels,
                               fbftdict=feedbackthroughdict)

    print 'Value of cost functional not considering `u`: ', costfunval

    print 'dim of v :', femp['V'].dim()
    charlene = .15 if problemname == 'cylinderwake' else 1.0
    print 'Re = charL / nu = {0}'.format(charlene/nu)
def solve_euler_timedep(method=1, Omega=8, tE=None, Prec=None,
                        N=40, NtsList=None, LinaTol=None, MaxIter=None,
                        UsePreTStps=None, SaveTStps=None, SaveIniVal=None,
                        scheme='TH', nu=0, Re=None, inikryupd=None,
                        tolcor=False, prob=None):
    """system to solve

             du\dt + (u*D)u + grad p = fv
                      div u          = fp

    """

    methdict = {
        1: 'HalfExpEulSmaMin',
        2: 'HalfExpEulInd2'}

    # instantiate object containing mesh, V, Q, rhs, velbcs, invinds
    # set nu=0 for Euler flow
    if prob == 'cyl':
        femp, stokesmatsc, rhsd_vfrc, rhsd_stbc \
            = dnsps.get_sysmats(problem='cylinderwake', N=N, Re=Re,
                                scheme=scheme)

        Mc, Ac = stokesmatsc['M'], stokesmatsc['A']
        MPa = stokesmatsc['MP']
        BTc, Bc = stokesmatsc['JT'], stokesmatsc['J']
        Ba = stokesmatsc['Jfull']

        # bcinds, bcvals = femp['bcinds'], femp['bcvals']

        fvbc, fpbc = rhsd_stbc['fv'], rhsd_stbc['fp']
        inivdict = dict(A=Ac, J=Bc, JT=BTc, M=Mc,
                        ppin=None, V=femp['V'], Q=femp['Q'],
                        fv=fvbc, fp=fpbc, vel_pcrd_stps=0, vel_nwtn_stps=0,
                        return_vp=True, diribcs=femp['diribcs'],
                        invinds=femp['invinds'])
        dimredsys = Bc.shape[1] + Bc.shape[0]
        vp_init = snu.solve_steadystate_nse(**inivdict)[0]

        PrP = FempToProbParams(N, omega=Omega, femp=femp, pdof=None)
        PrP.Pdof = None  # No p pinning for outflow flow

        print 'Nv, Np -- w/o boundary nodes', BTc.shape
    else:
        if Re is not None:
            nu = 1./Re
        PrP = ProbParams(N, omega=Omega, nu=nu, scheme=scheme)
        # get system matrices as np.arrays

        smts = dts.get_stokessysmats(PrP.V, PrP.Q, nu=nu)
        rhsvecs = dts.setget_rhs(PrP.V, PrP.Q, PrP.fv, PrP.fp)
        # Ma, Aa, BTa, Ba = smts['A'], smts['JT'], smts['J']
        # MPa = smts['MP']

        # Ma, Aa, BTa, Ba, MPa = dtn.get_sysNSmats(PrP.V, PrP.Q, nu=nu)
        # fv, fp = rhsvecs['fv'], rhsvecs['fp']
        # fv, fp = dtn.setget_rhs(PrP.V, PrP.Q, PrP.fv, PrP.fp)
        print 'Nv, Np -- w/ boundary nodes', smts['BTa'].shape

        # condense the system by resolving the boundary values
        # (Mc, Ac, BTc, Bc, fvbc, fpbc, bcinds, bcvals,
        #  invinds) = dtn.condense_sysmatsbybcs(Ma, Aa, BTa, Ba,

        smts.update(rhsvecs)
        smtsc = dts.condense_sysmatsbybcs(smts, PrP.velbcs)
        Mc, Ac, BTc, Bc = smtsc['Mc'], smtsc['Ac'], smtsc['BTc'], smtsc['Bc']
        fvbc, fpbc = smtsc['fvbc'], smtsc['fpbc']
        #  invinds
        print 'Nv, Np -- w/o boundary nodes', BTc.shape
        PrP.Pdof = 0  # Thats how the smamin is constructed

        dimredsys = Bc.shape[0] + Bc.shape[1]
        # TODO: this should sol(0)
        vp_init = np.zeros((dimredsys, 1))

    # instantiate the Time Int Parameters
    TsP = TimestepParams(methdict[method], N, scheme=scheme)

    if NtsList is not None:
        TsP.Ntslist = NtsList
    if LinaTol is not None:
        TsP.linatol = LinaTol
    if MaxIter is not None:
        TsP.MaxIter = MaxIter
    if tE is not None:
        TsP.tE = tE
    if Omega is not None:
        TsP.Omega = Omega
    if SaveTStps is not None:
        TsP.SaveTStps = SaveTStps
    if UsePreTStps is not None:
        TsP.UsePreTStps = UsePreTStps
    if SaveIniVal is not None:
        TsP.SaveIniVal = SaveIniVal
    if inikryupd is not None:
        TsP.inikryupd = inikryupd
    TsP.TolCorB = tolcor

    print 'Mesh parameter N = %d' % N
    print 'Time interval [%d,%1.2f]' % (TsP.t0, TsP.tE)
    print 'Omega = %d' % TsP.Omega
    print 'You have chosen %s for time integration' % methdict[method]
    print 'The tolerance for the linear solver is %e' % TsP.linatol
    print 'tolcor -- controlling the abs residuals -- is ', tolcor

    if method == 1:
        # Rearrange the matrices and rhs
        # from smamin_utils import col_columns_atend
        from scipy.io import loadmat

        if prob == 'cyl' and scheme == 'CR':
            if N == 0:
                cricell = 758
            elif N == 1:
                cricell = 1498
            elif N == 2:
                cricell = 2386
            elif N == 3:
                cricell = 4843
            else:
                raise NotImplementedError()
            # TODO: this is hard coded...
            # dptatnb = dolfin.Point(2.2, 0.2)
            # cricell = smt.get_cellid_nexttopoint(PrP.mesh, dptatnb)

        elif prob == 'cyl':
            raise NotImplementedError()
        else:
            cricell = None

        MSmeCL, ASmeCL, BSme, B2Inds, B2BoolInv, B2BI = smt.\
            get_smamin_rearrangement(N, PrP, M=Mc, A=Ac, B=Bc,
                                     crinicell=cricell, addnedgeat=cricell,
                                     scheme=scheme, fullB=Ba)
        FvbcSme = np.vstack([fvbc[~B2BoolInv, ], fvbc[B2BoolInv, ]])
        FpbcSme = fpbc

        # inivalue
        dname = 'IniValSmaMinN%s' % N
        try:
            IniV = loadmat(dname)
            qqpq_init = IniV['qqpq_old']
            vp_init = None
        except IOError:
            qqpq_init = None

    # Output
    try:
        os.chdir('json')
    except OSError:
        raise Warning('need "json" subdirectory for storing the data')
    os.chdir('..')

    if TsP.ParaviewOutput:
        os.chdir('results/')
        for fname in glob.glob(TsP.method + scheme + '*'):
            os.remove(fname)
        os.chdir('..')

    # ## Time stepping ## #
    for i, CurNTs in enumerate(TsP.Ntslist):
        TsP.Nts = CurNTs

        if method == 2:
            tis.halfexp_euler_nseind2(Mc, MPa, Ac, BTc, Bc, fvbc, fpbc,
                                      PrP, TsP, vp_init=vp_init)
        elif method == 1:
            tis.halfexp_euler_smarminex(MSmeCL, ASmeCL, BSme,
                                        MPa, FvbcSme, FpbcSme,
                                        B2BoolInv, PrP, TsP,
                                        qqpq_init=qqpq_init, vp_init=vp_init)

        # Output only in first iteration!
        TsP.ParaviewOutput = False

    save_simu(TsP, PrP)

    return