def comptorque(rotval, thingdict=None, returnitall=False):
        def rotcont(t, vel=None, p=None, memory={}):
            return rotval, memory

        rotcondict = {}
        dircntdict = dict(diricontbcinds=[femp['mvwbcinds']],
                          diricontbcvals=[femp['mvwbcvals']],
                          diricontfuncs=[rotcont],
                          diricontfuncmems=[rotcondict])
        soldict.update(dircntdict)
        soldict.update(dict(vel_start_nwtn=thingdict['vel_start_nwtn']))
        if ininu is not None and thingdict['vel_start_nwtn'] is None:
            inifemp, inistokesmatsc, inirhsd = \
                dnsps.get_sysmats(problem=problem, nu=ininu, bccontrol=False,
                                  charvel=charvel, scheme=scheme,
                                  mergerhs=True, meshparams=meshparams)
            soldict.update(inistokesmatsc)
            soldict.update(inifemp)
            soldict.update(fv=inirhsd['fv'], fp=inirhsd['fp'])
            vp_ss_nse = snu.solve_steadystate_nse(**soldict)
            soldict.update(dict(vel_start_nwtn=vp_ss_nse[0]))
            soldict.update(stokesmatsc)
            soldict.update(femp)
            soldict.update(fv=rhsd['fv'], fp=rhsd['fp'])

        vp_ss_nse = snu.solve_steadystate_nse(**soldict)
        thingdict.update(dict(vel_start_nwtn=vp_ss_nse[0]))

        if returnitall:
            vfun, pfun = dts.\
                expand_vp_dolfunc(vc=vp_ss_nse[0], pc=vp_ss_nse[1],
                                  V=femp['V'], Q=femp['Q'])
            # lift, drag = getld.evaliftdragforce(u=vfun, p=pfun)

            drag = steady_state_res(vfun, pfun, phi=pox)
            lift = steady_state_res(vfun, pfun, phi=poy)
            # phionex = phione.sub(0)

            trqe = steady_state_res(vfun, pfun, phi=phitwo)
            # trqe = getld.evatorqueSphere2D(u=vfun, p=pfun)
            a_1 = dolfin.Point(0.15, 0.2)
            a_2 = dolfin.Point(0.25, 0.2)
            pdiff = rho * pfun(a_2) - rho * pfun(a_1)
            return trqe, lift, drag, pdiff
        else:
            vfun, pfun = dts.\
                expand_vp_dolfunc(vc=vp_ss_nse[0], pc=vp_ss_nse[1],
                                  V=femp['V'], Q=femp['Q'])
            # trqe = getld.evatorqueSphere2D(u=vfun, p=pfun)
            trqe = steady_state_res(vfun, pfun, phi=phitwo)

            print('omeg: {0:.3e} -- trqe: {1:.3e}'.format(rotval, trqe))
            return np.abs(trqe)
    def test_pfv(self):
        """check the computation of p from a given v

        """

        femp, stokesmatsc, rhsd = \
            dnsps.get_sysmats(problem='cylinderwake', N=self.N,
                              Re=self.Re, scheme=self.scheme, mergerhs=True)

        Mc, Ac = stokesmatsc['M'], stokesmatsc['A']
        BTc, Bc = stokesmatsc['JT'], stokesmatsc['J']
        print(Bc.shape)

        invinds = femp['invinds']

        fv, fp = rhsd['fv'], rhsd['fp']
        print(np.linalg.norm(fv), np.linalg.norm(fp))
        inivdict = dict(A=Ac, J=Bc, JT=BTc, M=Mc, ppin=self.ppin, fv=fv, fp=fp,
                        return_vp=True, V=femp['V'], clearprvdata=True,
                        invinds=invinds, diribcs=femp['diribcs'])
        vp_init = snu.solve_steadystate_nse(**inivdict)

        NV = Bc.shape[1]

        pfv = snu.get_pfromv(v=vp_init[0], V=femp['V'],
                             M=Mc, A=Ac, J=Bc, fv=fv,
                             invinds=femp['invinds'], diribcs=femp['diribcs'])
        self.assertTrue(np.allclose(pfv, vp_init[1]))
def testit(problem='cylinderwake', N=None, nu=None, Re=None,
           nnwtnstps=9, npcrdstps=5, palpha=1e-5):

    vel_nwtn_tol = 1e-14
    # prefix for data files
    data_prfx = problem
    # dir to store data
    ddir = 'data/'
    # paraview output
    ParaviewOutput = True
    proutdir = 'results/'

    femp, stokesmatsc, rhsd = dnsps.get_sysmats(problem=problem, N=N, Re=Re,
                                                nu=nu, scheme='TH',
                                                mergerhs=True, bccontrol=True)
    import scipy.sparse.linalg as spsla
    print('get expmats: |A| = {0}'.format(spsla.norm(stokesmatsc['A'])))
    print('get expmats: |Arob| = {0}'.format(spsla.norm(stokesmatsc['Arob'])))

    stokesmatsc['A'] = stokesmatsc['A'] + 1./palpha*stokesmatsc['Arob']
    b_mat = 1./palpha*stokesmatsc['Brob']
    brhs = 1*(1.5*b_mat[:, :1] - 1.5*b_mat[:, 1:])

    soldict = stokesmatsc  # containing A, J, JT
    soldict.update(femp)  # adding V, Q, invinds, diribcs

    soldict.update(fv=rhsd['fv']+brhs, fp=rhsd['fp'],
                   N=N, nu=nu,
                   vel_nwtn_stps=nnwtnstps,
                   vel_pcrd_stps=npcrdstps,
                   vel_nwtn_tol=vel_nwtn_tol,
                   ddir=ddir, get_datastring=None,
                   clearprvdata=True,
                   data_prfx=ddir+data_prfx,
                   paraviewoutput=ParaviewOutput,
                   vfileprfx=proutdir+'vel_',
                   pfileprfx=proutdir+'p_')

#
# compute the uncontrolled steady state Navier-Stokes solution
#
    snu.solve_steadystate_nse(**soldict)
    print('plots go to : ' + proutdir + 'vel___steadystates.pvd')
Exemple #4
0
    def test_pfv(self):
        """check the computation of p from a given v

        """

        femp, stokesmatsc, rhsd = \
            dnsps.get_sysmats(problem='cylinderwake',
                              meshparams=dict(refinement_level=self.N),
                              Re=self.Re, scheme=self.scheme, mergerhs=True)

        Mc, Ac = stokesmatsc['M'], stokesmatsc['A']
        BTc, Bc = stokesmatsc['JT'], stokesmatsc['J']
        print(Bc.shape)

        invinds = femp['invinds']

        fv, fp = rhsd['fv'], rhsd['fp']
        print(np.linalg.norm(fv), np.linalg.norm(fp))
        inivdict = dict(A=Ac,
                        J=Bc,
                        JT=BTc,
                        M=Mc,
                        ppin=self.ppin,
                        fv=fv,
                        fp=fp,
                        return_vp=True,
                        V=femp['V'],
                        clearprvdata=True,
                        invinds=invinds,
                        diribcs=femp['diribcs'])
        vp_init = snu.solve_steadystate_nse(**inivdict)

        dbcinds, dbcvals = dts.unroll_dlfn_dbcs(femp['diribcs'])
        pfv = snu.get_pfromv(v=vp_init[0][invinds],
                             V=femp['V'],
                             M=Mc,
                             A=Ac,
                             J=Bc,
                             fv=fv,
                             invinds=femp['invinds'],
                             dbcinds=dbcinds,
                             dbcvals=dbcvals)
        self.assertTrue(np.allclose(pfv, vp_init[1]))
Exemple #5
0
def twod_simu(nu=None, charvel=None, rho=1., rhosolid=10., meshparams=None,
              inirot=None, inivfun=None,
              t0=0.0, tE=.1, Nts=1e2+1,
              start_steadystate=False, ininu=None,
              plotplease=False, proutdir='paraviewplots/',
              return_final_vp=False, ParaviewOutput=False, scheme='TH'):

    femp, stokesmatsc, rhsd = \
        dnsps.get_sysmats(problem='gen_bccont', nu=nu, bccontrol=False,
                          charvel=charvel, scheme=scheme, mergerhs=True,
                          meshparams=meshparams)
    # dnsps.get_sysmats(problem='cylinder_rot', nu=nu, bccontrol=False,
    #                   charvel=charvel, scheme=scheme, mergerhs=True,
    #                   meshparams=meshparams)

    tips = dict(t0=t0, tE=tE, Nts=Nts)

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

    # function of ones at the lift/drag boundary
    phionevec = np.zeros((femp['V'].dim(), 1))
    phionevec[femp['mvwbcinds'], :] = 1.
    phione = dolfin.Function(femp['V'])
    phione.vector().set_local(phionevec)
    pickx = dolfin.as_matrix([[1., 0.], [0., 0.]])
    picky = dolfin.as_matrix([[0., 0.], [0., 1.]])
    pox = pickx*phione
    poy = picky*phione

    # function of the tangential vector at the lift/drag boundary
    phitwovec = np.zeros((femp['V'].dim(), 1))
    phitwovec[femp['mvwbcinds'], 0] = femp['mvwbcvals']
    phitwo = dolfin.Function(femp['V'])
    phitwo.vector().set_local(phitwovec)

    # getld = dnsps.LiftDragSurfForce(V=femp['V'], nu=nu,
    #                                 phione=phione, phitwo=phitwo,
    #                                 outflowds=femp['outflowds'],
    #                                 ldds=femp['liftdragds'])

    # L = femp['charlen']  # characteristic length = 2*Radius

    a_1 = dolfin.Point(0.15, 0.2)
    a_2 = dolfin.Point(0.25, 0.2)

    reschkdict = dict(V=femp['V'], gradvsymmtrc=True,
                      outflowds=femp['outflowds'], nu=nu)
    euleres = get_imex_res(explscheme='eule', **reschkdict)
    heunres = get_imex_res(explscheme='heun', **reschkdict)
    abtwres = get_imex_res(explscheme='abtw', **reschkdict)
    # ststres = get_steady_state_res(**reschkdict)

    def record_ldt(t, vel=None, p=None, memory={}, mode='abtwo'):

        rotval = 0.
        if mode == 'stokes':
            memory.update(dict(lastt=t))
            return rotval, memory

        if mode == 'init':
            memory.update(dict(lastt=t))
            return rotval, memory

        vfun, pfun = dts.expand_vp_dolfunc(vc=vel, pc=p, **femp)

        if mode == 'heunpred' or mode == 'heuncorr':
            curdt = t - memory['lastt']
            if mode == 'heunpred':
                memory.update(dict(lastv=vel))
                pass

            elif mode == 'heuncorr':
                lvfun = dts.expand_vp_dolfunc(vc=memory['lastv'],
                                              **femp)[0]
                trqe = euleres(vfun, pfun, curdt, lastvel=lvfun, phi=phitwo)
                lift = euleres(vfun, pfun, curdt, lastvel=lvfun, phi=poy)
                drag = euleres(vfun, pfun, curdt, lastvel=lvfun, phi=pox)
                memory.update(dict(lastt=t, lastdt=curdt, heunpred=vel))

                memory['trqs'].append(trqe)
                memory['lfts'].append(lift)
                memory['drgs'].append(drag)
                memory['tims'].append(t)

        elif mode == 'abtwo':

            lvfun = dts.expand_vp_dolfunc(vc=memory['lastv'], **femp)[0]
            curdt = t - memory['lastt']

            try:
                ovfn = dts.expand_vp_dolfunc(vc=memory['lastlastv'], **femp)[0]
                modres = abtwres
            except KeyError:  # no lastlastv yet -- we can check the Heun res
                ovfn = dts.expand_vp_dolfunc(vc=memory['heunpred'], **femp)[0]
                modres = heunres

            trqe = modres(vfun, pfun, curdt, lastvel=lvfun, othervel=ovfn,
                          phi=phitwo)
            lift = modres(vfun, pfun, curdt, lastvel=lvfun, othervel=ovfn,
                          phi=poy)
            drag = modres(vfun, pfun, curdt, lastvel=lvfun, othervel=ovfn,
                          phi=pox)

            memory.update(dict(lastlastv=np.copy(memory['lastv'])))
            memory.update(dict(lastv=vel))

            memory['trqs'].append(trqe)
            memory['lfts'].append(lift)
            memory['drgs'].append(drag)
            memory['tims'].append(t)
            memory.update(dict(lastt=t, lastdt=curdt))

        deltap = pfun(a_1) - pfun(a_2)
        memory['dtps'].append(deltap)
        return rotval, memory

    rotcondict = dict(lastt=None,
                      trqs=[], omegs=[], lfts=[], drgs=[], dtps=[], tims=[],
                      lastdt=None)

    dircntdict = dict(diricontbcinds=[femp['mvwbcinds']],
                      diricontbcvals=[femp['mvwbcvals']],
                      diricontfuncs=[record_ldt],
                      diricontfuncmems=[rotcondict])

    soldict = {}
    soldict.update(stokesmatsc)  # containing A, J, JT
    soldict.update(femp)  # adding V, Q, invinds, diribcs
    soldict.update(tips)  # adding time integration params
    soldict.update(dircntdict)
    soldict.update(fv=rhsd['fv'], fp=rhsd['fp'],
                   verbose=True,
                   vel_pcrd_stps=5,
                   return_vp=True,
                   treat_nonl_explct=True,
                   no_data_caching=True,
                   return_final_vp=return_final_vp,
                   dbcinds=femp['dbcinds'], dbcvals=femp['dbcvals'],
                   paraviewoutput=ParaviewOutput,
                   vfileprfx=proutdir+'vel_',
                   pfileprfx=proutdir+'p_')

#
    if inivfun is None:
        if start_steadystate:
            if ininu is not None:
                inifemp, inistokesmatsc, inirhsd = \
                    dnsps.get_sysmats(problem='cylinder_rot', nu=ininu,
                                      bccontrol=False,
                                      charvel=charvel, scheme=scheme,
                                      mergerhs=True, meshparams=meshparams)
                soldict.update(inistokesmatsc)
                soldict.update(inifemp)
                soldict.update(fv=inirhsd['fv'], fp=inirhsd['fp'])
                vp_ss_nse = snu.solve_steadystate_nse(**soldict)
                soldict.update(dict(vel_start_nwtn=vp_ss_nse[0]))
                soldict.update(stokesmatsc)
                soldict.update(femp)
                soldict.update(fv=rhsd['fv'], fp=rhsd['fp'])
            soldict.update(vel_nwtn_tol=1e-3)
            vp_ss_nse = snu.solve_steadystate_nse(**soldict)
            soldict.update(dict(iniv=vp_ss_nse[0]))
        else:
            soldict.update(start_ssstokes=True)
    else:
        inivvec = (inivfun.vector().get_local()).reshape((femp['V'].dim(), 1))
        soldict.update(dict(iniv=inivvec))

    finalvp = snu.solve_nse(**soldict)
    if ParaviewOutput:
        print('for plots check \nparaview ' + proutdir + 'vel___timestep.pvd')
        print('or \nparaview ' + proutdir + 'p___timestep.pvd')

    resdict = rotcondict

    nnz = 2*stokesmatsc['J'].nnz + stokesmatsc['A'].nnz

    resdict.update(dict(nvnp=[NV, NP], nnz=nnz))
    if return_final_vp:
        return rotcondict, finalvp

    return rotcondict
def comp_exp_nsmats(
    problemname="drivencavity",
    N=10,
    Re=1e2,
    nu=None,
    linear_system=False,
    refree=False,
    bccontrol=False,
    palpha=None,
    use_old_data=False,
    mddir="pathtodatastorage",
):
    """compute and export the system matrices for Navier-Stokes equations

    Parameters
    ---
    refree : boolean, optional
        whether to use `Re=1` (so that the `Re` number can be applied later by
        scaling the corresponding matrices, defaults to `False`
    linear_system : boolean, optional
        whether to compute/return the linearized system, defaults to `False`
    bccontrol : boolean, optional
        whether to model boundary control at the cylinder via penalized robin
        boundary conditions, defaults to `False`
    palpha : float, optional
        penalization parameter for the boundary control, defaults to `None`,
        `palpha` is mandatory for `linear_system`

    """

    if refree:
        Re = 1
        print "For the Reynoldsnumber free mats, we set Re=1"

    if problemname == "drivencavity" and bccontrol:
        raise NotImplementedError("boundary control for the driven cavity" + " is not implemented yet")

    if linear_system and bccontrol and palpha is None:
        raise UserWarning("For the linear system a" + " value for `palpha` is needed")
    if not linear_system and bccontrol:
        raise NotImplementedError("Nonlinear system with boundary control" + " is not implemented yet")
    femp, stokesmatsc, rhsd_vfrc, rhsd_stbc = dnsps.get_sysmats(problem=problemname, bccontrol=bccontrol, N=N, Re=Re)
    if linear_system and bccontrol:
        Arob = stokesmatsc["A"] + 1.0 / palpha * stokesmatsc["Arob"]
        Brob = 1.0 / palpha * stokesmatsc["Brob"]
    elif linear_system:
        Brob = 0

    invinds = femp["invinds"]
    A, J = stokesmatsc["A"], stokesmatsc["J"]
    fvc, fpc = rhsd_vfrc["fvc"], rhsd_vfrc["fpr"]
    fv_stbc, fp_stbc = rhsd_stbc["fv"], rhsd_stbc["fp"]
    invinds = femp["invinds"]
    NV = invinds.shape[0]
    data_prfx = problemname + "__N{0}Re{1}".format(N, Re)
    if bccontrol:
        data_prfx = data_prfx + "_penarob"

    soldict = stokesmatsc  # containing A, J, JT
    soldict.update(femp)  # adding V, Q, invinds, diribcs
    soldict.update(rhsd_vfrc)  # adding fvc, fpr
    fv = rhsd_vfrc["fvc"] + rhsd_stbc["fv"]
    fp = rhsd_vfrc["fpr"] + rhsd_stbc["fp"]
    # print 'get expmats: ||fv|| = {0}'.format(np.linalg.norm(fv))
    # print 'get expmats: ||fp|| = {0}'.format(np.linalg.norm(fp))
    # import scipy.sparse.linalg as spsla
    # print 'get expmats: ||A|| = {0}'.format(spsla.norm(A))
    # print 'get expmats: ||Arob|| = {0}'.format(spsla.norm(Arob))
    # print 'get expmats: ||A|| = {0}'.format(spsla.norm(stokesmatsc['A']))
    # raise Warning('TODO: debug')

    soldict.update(
        fv=fv,
        fp=fp,
        N=N,
        nu=nu,
        clearprvdata=~use_old_data,
        get_datastring=None,
        data_prfx=ddir + data_prfx + "_stst",
        paraviewoutput=False,
    )
    if bccontrol and linear_system:
        soldict.update(A=Arob)

    # compute the uncontrolled steady state Navier-Stokes solution
    vp_ss_nse, list_norm_nwtnupd = snu.solve_steadystate_nse(return_vp=True, **soldict)
    v_ss_nse, p_ss_nse = vp_ss_nse[:NV], vp_ss_nse[NV:]

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

    #
    # Control mats
    #
    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

    # the pressure observation mean over a small domain
    if problemname == "cylinderwake":
        podcoo = dict(xmin=0.6, xmax=0.64, ymin=0.18, ymax=0.22)
    elif problemname == "drivencavity":
        podcoo = dict(xmin=0.45, xmax=0.55, ymin=0.7, ymax=0.8)
    else:
        podcoo = femp["odcoo"]

    # description of the control and observation domains
    dmd = femp["cdcoo"]
    xmin, xmax, ymin, ymax = dmd["xmin"], dmd["xmax"], dmd["ymin"], dmd["ymax"]
    velcondomstr = "vel control domain: [{0}, {1}]x[{2}, {3}]\n".format(xmin, xmax, ymin, ymax)
    dmd = femp["odcoo"]
    xmin, xmax, ymin, ymax = dmd["xmin"], dmd["xmax"], dmd["ymin"], dmd["ymax"]
    velobsdomstr = "vel observation domain: [{0}, {1}]x[{2}, {3}]\n".format(xmin, xmax, ymin, ymax)
    dmd = podcoo
    xmin, xmax, ymin, ymax = dmd["xmin"], dmd["xmax"], dmd["ymin"], dmd["ymax"]
    pobsdomstr = "pressure observation domain: [{0}, {1}]x[{2}, {3}]\n".format(xmin, xmax, ymin, ymax)

    pcmat = cou.get_pavrg_onsubd(odcoo=podcoo, Q=femp["Q"], ppin=None)

    cdatstr = snu.get_datastr_snu(time=None, meshp=N, nu=nu, Nts=None)

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

    ctrl_visu_str = (
        " the (distributed) control setup is as follows \n"
        + " B maps into the domain of control -"
        + velcondomstr
        + " the first half of the columns"
        + "actuate in x-direction, the second in y direction \n"
        + " Cv measures averaged velocities in the domain of observation"
        + velobsdomstr
        + " Cp measures the averaged pressure"
        + " in the domain of pressure observation: "
        + pobsdomstr
        + " 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 `get_exp_nsmats.py` "
        + "(see https://github.com/highlando/dolfin_navier_scipy) at\n"
        + datetime.datetime.now().strftime("%I:%M%p on %B %d, %Y")
    )

    if bccontrol and problemname == "cylinderwake" and linear_system:
        ctrl_visu_str = (
            "the boundary control is realized via penalized robin \n"
            + "boundary conditions, cf. e.g. [Hou/Ravindran `98], \n"
            + "with predefined shape functions for the cylinder wake \n"
            + "and the penalization parameter `palpha`={0}."
        ).format(palpha) + ctrl_visu_str

    if linear_system:
        convc_mat, rhs_con, rhsv_conbc = snu.get_v_conv_conts(
            prev_v=v_ss_nse, invinds=invinds, V=femp["V"], diribcs=femp["diribcs"]
        )
        # TODO: omg
        if bccontrol:
            f_mat = -Arob - convc_mat
        else:
            f_mat = -stokesmatsc["A"] - convc_mat

        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 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"
            + ctrl_visu_str
        )

        matstr = (mddir + problemname + "__mats_N{0}_Re{1}").format(NV, Re)
        if bccontrol:
            matstr = matstr + "__penarob_palpha{0}".format(palpha)

        scipy.io.savemat(
            matstr,
            dict(
                A=f_mat,
                M=stokesmatsc["M"],
                nu=femp["nu"],
                Re=femp["Re"],
                J=stokesmatsc["J"],
                B=b_mat,
                C=c_mat,
                Cp=pcmat,
                Brob=Brob,
                v_ss_nse=v_ss_nse,
                info=infostr,
                contsetupstr=contsetupstr,
                datastr=cdatstr,
                coors=coors,
                xinds=xinds,
                yinds=yinds,
                corfunvec=corfunvec,
            ),
        )

        print ("matrices saved to " + matstr)

    elif refree:
        hstr = ddir + problemname + "_N{0}_hmat".format(N)
        try:
            hmat = dou.load_spa(hstr)
            print "loaded `hmat`"
        except IOError:
            print "assembling hmat ..."
            hmat = dts.ass_convmat_asmatquad(W=femp["V"], invindsw=invinds)
            dou.save_spa(hmat, hstr)

        zerv = np.zeros((NV, 1))
        bc_conv, bc_rhs_conv, rhsbc_convbc = snu.get_v_conv_conts(
            prev_v=zerv, V=femp["V"], invinds=invinds, diribcs=femp["diribcs"], Picard=False
        )

        # diff_mat = stokesmatsc['A']
        # bcconv_mat = bc_conv
        # fv_bcdiff = fv_stbc
        # fv_bcconv = - bc_rhs_conv
        fv = fvc
        fp = fpc
        # fp_bc = fp_stbc

        infostr = (
            "These are the coefficient matrices of the quadratic "
            + "formulation of the Navier-Stokes Equations \n for the "
            + problemname
            + " to be used as \n\n"
            + " $M \\dot v + Av + H*kron(v,v) + J^Tp = Bu + fv$ \n"
            + " and  $Jv = fp$ \n\n"
            + " the Reynoldsnumber is computed as L/nu \n"
            + " note that `A` contains the diffusion and the linear term \n"
            + " that comes from the dirichlet boundary values \n"
            + " as initial value one can use the provided steady state \n"
            + " Stokes solution \n"
            + " see https://github.com/highlando/dolfin_navier_scipy/blob/"
            + " master/tests/solve_nse_quadraticterm.py for appl example\n"
            + ctrl_visu_str
        )

        scipy.io.savemat(
            mddir + problemname + "quadform__mats_N{0}_Re{1}".format(NV, Re),
            dict(
                A=f_mat,
                M=stokesmatsc["M"],
                H=-hmat,
                fv=fv,
                fp=fp,
                nu=femp["nu"],
                Re=femp["Re"],
                J=stokesmatsc["J"],
                B=b_mat,
                Cv=c_mat,
                Cp=pcmat,
                info=infostr,
                # ss_stokes=old_v,
                contsetupstr=contsetupstr,
                datastr=cdatstr,
                coors=coors,
                xinds=xinds,
                yinds=yinds,
                corfunvec=corfunvec,
            ),
        )
    else:
        hstr = ddir + problemname + "_N{0}_hmat".format(N)
        try:
            hmat = dou.load_spa(hstr)
            print "loaded `hmat`"
        except IOError:
            print "assembling hmat ..."
            hmat = dts.ass_convmat_asmatquad(W=femp["V"], invindsw=invinds)
            dou.save_spa(hmat, hstr)

        zerv = np.zeros((NV, 1))
        bc_conv, bc_rhs_conv, rhsbc_convbc = snu.get_v_conv_conts(
            prev_v=zerv, V=femp["V"], invinds=invinds, diribcs=femp["diribcs"], Picard=False
        )

        f_mat = -stokesmatsc["A"] - bc_conv
        l_mat = -bc_conv
        fv = fv_stbc + fvc - bc_rhs_conv
        fp = fp_stbc + fpc

        vp_stokes = lau.solve_sadpnt_smw(amat=A, jmat=J, rhsv=fv_stbc + fvc, rhsp=fp_stbc + fpc)
        old_v = vp_stokes[:NV]
        p_stokes = -vp_stokes[NV:]  # the pressure was flipped for symmetry

        infostr = (
            "These are the coefficient matrices of the quadratic "
            + "formulation of the Navier-Stokes Equations \n for the "
            + problemname
            + " to be used as \n\n"
            + " $M \\dot v = Av + H*kron(v,v) + J^Tp + Bu + fv$ \n"
            + " and  $Jv = fp$ \n\n"
            + " the Reynoldsnumber is computed as L/nu \n"
            + " note that `A` contains the diffusion and the linear term `L`\n"
            + " that comes from the dirichlet boundary values \n"
            + " for linearizations it might be necessary to consider `A-L` \n"
            + " as initial value one can use the provided steady state \n"
            + " Stokes solution \n"
            + " see https://github.com/highlando/dolfin_navier_scipy/blob/"
            + " master/tests/solve_nse_quadraticterm.py for appl example\n"
            + ctrl_visu_str
        )

        scipy.io.savemat(
            mddir + problemname + "quadform__mats_N{0}_Re{1}".format(NV, Re),
            dict(
                A=f_mat,
                M=stokesmatsc["M"],
                H=-hmat,
                fv=fv,
                fp=fp,
                L=l_mat,
                nu=femp["nu"],
                Re=femp["Re"],
                J=stokesmatsc["J"],
                B=b_mat,
                Cv=c_mat,
                Cp=pcmat,
                info=infostr,
                p_ss_stokes=p_stokes,
                p_ss_nse=p_ss_nse,
                v_ss_stokes=old_v,
                v_ss_nse=v_ss_nse,
                contsetupstr=contsetupstr,
                datastr=cdatstr,
                coors=coors,
                xinds=xinds,
                yinds=yinds,
                corfunvec=corfunvec,
            ),
        )
Exemple #7
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)
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
def testit(problem=None, nu=None, charvel=None, Re=None,
           meshlvl=1,
           rho=1.,
           t0=0.0, tE=1.0, Nts=1e2+1, ParaviewOutput=False, scheme='TH'):

    meshfile = 'mesh/karman2D-rotcyl_lvl{0}.xml.gz'.format(meshlvl)
    physregs = 'mesh/karman2D-rotcyl_lvl{0}_facet_region.xml.gz'.\
        format(meshlvl)
    femp, stokesmatsc, rhsd = \
        dnsps.get_sysmats(problem='cylinder_rot', nu=nu, bccontrol=False,
                          charvel=charvel,
                          scheme=scheme, mergerhs=True,
                          meshparams=dict(strtomeshfile=meshfile,
                                          strtophysicalregions=physregs,
                                          strtobcsobs=geodata))
    ddir = 'data/'
    data_prfx = problem + '{4}_mesh{0}_Re{1}_Nts{2}_tE{3}'.\
        format(meshlvl, femp['Re'], Nts, tE, scheme)

    tips = dict(t0=t0, tE=tE, Nts=Nts)

    # ## Parameters for the benchmark values
    Um = charvel  # (we alread scale the inflow parabola accordingly)
    L = femp['charlen']  # characteristic length
    NP, NV = stokesmatsc['J'].shape
    print('NV + NP : {0} + {1} = {2}'.format(NV, NP, NV+NP))

    def rotcont(t, vel):
        return 0.

    dircntdict = dict(diricontbcinds=[femp['mvwbcinds']],
                      diricontbcvals=[femp['mvwbcvals']],
                      diricontfuncs=[rotcont])

    soldict = stokesmatsc  # containing A, J, JT
    soldict.update(femp)  # adding V, Q, invinds, diribcs
    soldict.update(tips)  # adding time integration params
    soldict.update(dircntdict)
    soldict.update(fv=rhsd['fv'], fp=rhsd['fp'],
                   N=meshlvl, nu=nu,
                   # start_ssstokes=True,
                   verbose=True,
                   return_vp=True,
                   iniv=0*rhsd['fv'],
                   get_datastring=None,
                   comp_nonl_semexp=True,
                   dbcinds=femp['dbcinds'], dbcvals=femp['dbcvals'],
                   data_prfx=ddir+data_prfx,
                   paraviewoutput=ParaviewOutput,
                   vfileprfx=proutdir+'vel_',
                   pfileprfx=proutdir+'p_')

#
# compute the uncontrolled steady state Navier-Stokes solution
#
    vp_ss_nse = snu.solve_steadystate_nse(**soldict)
    vss, dynpss = dts.expand_vp_dolfunc(vc=vp_ss_nse[0], pc=vp_ss_nse[1],
                                        **femp)
    realpss = rho*dynpss  # Um**2*rho*dynpss
    realvss = vss  # Um*vss
    getld = dnsps.LiftDragSurfForce(V=femp['V'], nu=nu,
                                    ldds=femp['liftdragds'])
    clift, cdrag = getld.evaliftdragforce(u=realvss, p=realpss)
    cdclfac = 2./(rho*L*Um**2)
    print('Cl: {0}'.format(cdclfac*clift))
    print('Cd: {0}'.format(cdclfac*cdrag))
    import dolfin
    a_1 = dolfin.Point(0.15, 0.2)
    a_2 = dolfin.Point(0.25, 0.2)
    pdiff = realpss(a_1) - realpss(a_2)
    print('Delta P: {0}'.format(pdiff))

    print('\n values from Schaefer/Turek as in')
    print('www.featflow.de/en/benchmarks/cfdbenchmarking/flow/' +
          'dfg_benchmark1_re20.html:')
    print('Cl: {0}'.format(0.010618948146))
    print('Cd: {0}'.format(5.57953523384))
    print('Delta P: {0}'.format(0.11752016697))
Exemple #10
0
fv, fp = rhsd['fv'], rhsd['fp']
inivdict = dict(A=Ac,
                J=Bc,
                JT=BTc,
                M=Mc,
                ppin=ppin,
                fv=fv,
                fp=fp,
                return_vp=True,
                V=femp['V'],
                invinds=invinds,
                diribcs=femp['diribcs'])

# ## Solve the steady-state NSE
vp_steadystate = snu.solve_steadystate_nse(**inivdict)

# ## Test: recompute the p from the v
dbcinds, dbcvals = dts.unroll_dlfn_dbcs(femp['diribcs'])
pfv = snu.get_pfromv(v=vp_steadystate[0][femp['invinds'], :],
                     V=femp['V'],
                     M=Mc,
                     A=Ac,
                     J=Bc,
                     fv=fv,
                     invinds=femp['invinds'],
                     dbcinds=dbcinds,
                     dbcvals=dbcvals)

print('Number of inner velocity nodes: {0}'.format(invinds.shape))
print('Shape of the divergence matrix: ', Bc.shape)
Exemple #11
0
N, Re, scheme, ppin = 2, 50, 'TH', None

femp, stokesmatsc, rhsd_vfrc, \
    rhsd_stbc, data_prfx, ddir, proutdir \
    = dnsps.get_sysmats(problem='cylinderwake', N=N, Re=Re,
                        scheme=scheme)

Mc, Ac = stokesmatsc['M'], stokesmatsc['A']
BTc, Bc = stokesmatsc['JT'], stokesmatsc['J']
print Bc.shape

invinds = femp['invinds']

fv, fp = rhsd_stbc['fv'], rhsd_stbc['fp']
inivdict = dict(A=Ac, J=Bc, JT=BTc, M=Mc, ppin=ppin, fv=fv, fp=fp,
                return_vp=True, V=femp['V'],
                invinds=invinds, diribcs=femp['diribcs'])
vp_init = snu.solve_steadystate_nse(**inivdict)[0]

NV = Bc.shape[1]

pfv = snu.get_pfromv(v=vp_init[:NV, :], V=femp['V'], M=Mc, A=Ac, J=Bc, fv=fv,
                     invinds=femp['invinds'], diribcs=femp['diribcs'])
print invinds.shape
print Bc.shape
print pfv.shape
print vp_init.shape

print np.linalg.norm(pfv - vp_init[NV:, :])
def set_inival(whichinival='sstokes', soldict=None, perturbpara=None,
               v_ss_nse=None, trange=None, tpp=None, fdstr=None,
               retvssnse=False):
    ''' compute the wanted initial value and set it in the soldict

    '''

    if (retvssnse or whichinival == 'sstate+d') and v_ss_nse is None:
        ret_v_ss_nse = snu.solve_steadystate_nse(**soldict)
    elif v_ss_nse is not None:
        ret_v_ss_nse = v_ss_nse
    else:
        ret_v_ss_nse is None

    if whichinival == 'sstokes':
        print('we start with Stokes -- `perturbpara` is not considered')
        soldict.update(dict(iniv=None, start_ssstokes=True))
        shortinivstr = 'sks'
        return shortinivstr, ret_v_ss_nse

    if (whichinival == 'sstate+d' or
            whichinival == 'snse+d++' or whichinival == 'sstate+du'):
        perturbini = perturbpara*np.ones((soldict['M'].shape[0], 1))
        reg_pertubini = lau.app_prj_via_sadpnt(amat=soldict['M'],
                                               jmat=soldict['J'],
                                               rhsv=perturbini)
        if whichinival == 'sstate+d':
            soldict.update(dict(iniv=ret_v_ss_nse + reg_pertubini))
            shortinivstr = 'ssd{0}'.format(perturbpara)
            return shortinivstr, ret_v_ss_nse

    if whichinival == 'sstokes++' or whichinival == 'snse+d++':
        lctrng = (trange[trange < tpp]).tolist()
        lctrng.append(tpp)

        stksppdtstr = fdstr + 't0{0:.1f}tE{1:.4f}'.\
            format(trange[0], tpp) + whichinival
        try:
            sstokspp = dou.load_npa(stksppdtstr)
            print('loaded ' + stksppdtstr + ' for inival')
        except IOError:
            inivsoldict = {}
            inivsoldict.update(soldict)  # containing A, J, JT
            inivsoldict['fv_tmdp'] = None  # don't want control here
            # import ipdb; ipdb.set_trace()
            inivsoldict.update(trange=np.array(lctrng),
                               comp_nonl_semexp=True,
                               return_dictofvelstrs=True)
            if whichinival == 'sstokes++':
                print('solving for `stokespp({0})` as inival'.format(tpp))
                inivsoldict.update(iniv=None, start_ssstokes=True)
            else:
                inivsoldict.update(iniv=ret_v_ss_nse+reg_pertubini)
                print('solving for `nse+d+pp({0})` as inival'.format(tpp))
            dcvlstrs = snu.solve_nse(**inivsoldict)
            sstokspp = dou.load_npa(dcvlstrs[tpp])
            dou.save_npa(sstokspp, stksppdtstr)
        soldict.update(dict(iniv=sstokspp))
        shortinivstr = 'sk{0}'.format(tpp) if whichinival == 'sstokes++' \
            else 'nsk{0}'.format(tpp)
        return shortinivstr, ret_v_ss_nse
Exemple #13
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
Exemple #14
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)
femp, stokesmatsc, rhsd = \
    dnsps.get_sysmats(problem='cylinderwake', Re=Re,
                      scheme=scheme, mergerhs=True,
                      meshparams=dict(refinement_level=N))

Mc, Ac = stokesmatsc['M'], stokesmatsc['A']
BTc, Bc = stokesmatsc['JT'], stokesmatsc['J']
invinds = femp['invinds']

fv, fp = rhsd['fv'], rhsd['fp']
inivdict = dict(A=Ac, J=Bc, JT=BTc, M=Mc, ppin=ppin, fv=fv, fp=fp,
                return_vp=True, V=femp['V'],
                invinds=invinds, diribcs=femp['diribcs'])

# ## Solve the steady-state NSE
vp_steadystate = snu.solve_steadystate_nse(**inivdict)

NV = Bc.shape[1]

# ## Test: recompute the p from the v
pfv = snu.get_pfromv(v=vp_steadystate[0],
                     V=femp['V'], M=Mc, A=Ac, J=Bc, fv=fv,
                     invinds=femp['invinds'], diribcs=femp['diribcs'])

print('Number of inner velocity nodes: {0}'.format(invinds.shape))
print('Shape of the divergence matrix: ', Bc.shape)

print('error in recomputed pressure: {0}'.
      format(np.linalg.norm(pfv - vp_steadystate[1])))
def gopod(problemname='drivencavity',
          N=10, Re=1e2, t0=0.0, tE=1.0, Nts=11, NU=3, NY=3,
          paraoutput=True, multiproc=False,
          krylov=None, krpslvprms={}, krplsprms={}):
    """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`
    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`
    NU, NY : int, optional
        dimensions of components of in and output space (will double because
        there are two components), default to `3, 3`
    krylov : {None, 'gmres'}, optional
        whether or not to use an iterative solver, defaults to `None`
    krpslvprms : dictionary, optional
        to specify parameters of the linear solver for use in Krypy, e.g.,

          * initial guess
          * tolerance
          * number of iterations

        defaults to `None`
    krplsprms : dictionary, optional
        parameters to define the linear system like

          *preconditioner

    """
    femp, stokesmatsc, rhsd_vfrc, rhsd_stbc, data_prfx, ddir, proutdir = \
        dnsps.get_sysmats(problem=problemname, N=N, Re=Re)

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

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

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

    # contsetupstr = 'NV{0}NU{1}NY{2}alphau{3}'.format(NV, NU, NY, alphau)
    contsetupstr = 'NV{0}NU{1}NY{2}Re{3}'.format(NV, NU, NY, 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_stbc=rhsd_stbc['fv'], fp_stbc=rhsd_stbc['fp'],
                   N=N, nu=femp['nu'], data_prfx=data_prfx)
    soldict.update(paraviewoutput=paraoutput)
    soldict.update(krylov=krylov, krplsprms=krplsprms, krpslvprms=krpslvprms)

#
# Prepare for control
#

    # 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
    invinds = femp['invinds']
    mc_mat = mc_mat[:, invinds][:, :]
    b_mat = b_mat[invinds, :][:, :]

    # tb_mat = 1./np.sqrt(alphau)

# setup the system for the correction
#
# # compute the uncontrolled steady state Stokes solution
#
    v_ss_stokes, list_norm_nwtnupd = \
        snu.solve_steadystate_nse(vel_pcrd_stps=0, vel_nwtn_stps=0,
                                  clearprvdata=True, **soldict)
    tmesh = np.linspace(t0, tE, Nts)

    soldict.update(trange=tmesh,
                   iniv=v_ss_stokes,
                   lin_vel_point=v_ss_stokes,
                   clearprvdata=True,
                   vel_nwtn_stps=1,
                   return_dictofvelstrs=False,
                   paraviewoutput=True,
                   vfileprfx='results/fullvel',
                   pfileprfx='results/fullp')

    convc_mat_n, rhs_con_n, rhsv_conbc_n = \
        snu.get_v_conv_conts(prev_v=v_ss_stokes, invinds=invinds,
                             V=femp['V'], diribcs=femp['diribcs'],
                             Picard=False)

    convc_mat_z, rhs_con_z, rhsv_conbc_z = \
        snu.get_v_conv_conts(prev_v=0*v_ss_stokes, invinds=invinds,
                             V=femp['V'], diribcs=femp['diribcs'],
                             Picard=False)

    vellist = snu.solve_nse(return_as_list=True, **soldict)
    velar = np.array(vellist)[:, :, 0].T
    rhsv = soldict['fv_stbc'] + soldict['fvc'] + rhsv_conbc_n + rhs_con_n
    rhsp = soldict['fp_stbc'] + soldict['fpr']

    # print 'fvstbc', np.linalg.norm(soldict['fv_stbc'])
    # print 'fvc', np.linalg.norm(soldict['fvc'])
    # print 'rhsvconbc', np.linalg.norm(rhsv_conbc_n)
    # print 'rhscon', np.linalg.norm(rhs_con_n)

    print 'velarshape :', velar.shape

    checkreturns = False
    if checkreturns:
        inivel = velar[:, 0:1]

        ylist = snu.solve_nse(A=soldict['A']+convc_mat_n-convc_mat_z,
                              M=soldict['M'],
                              J=soldict['J'], fvc=rhsv, fpr=rhsp,
                              iniv=inivel,
                              fv_stbc=0*rhsv - rhsv_conbc_z - rhs_con_z,
                              fp_stbc=0*rhsp,
                              lin_vel_point=0*inivel, trange=tmesh,
                              V=femp['V'], Q=femp['Q'],
                              invinds=femp['invinds'],
                              diribcs=femp['diribcs'], N=soldict['N'],
                              nu=soldict['nu'],
                              vel_nwtn_stps=1,
                              return_as_list=True)

        velarcheck = np.array(ylist)[:, :, 0].T

        print np.linalg.norm(velarcheck - velar)
        # print np.linalg.norm(velarcheck[:, 1] - velar[:, 1])

    return (soldict['M'], soldict['A']+convc_mat_n, velar,
            rhsv, b_mat, tmesh, soldict['J'])
Exemple #17
0
def comp_exp_nsmats(problemname='drivencavity',
                    N=10,
                    Re=1e2,
                    nu=None,
                    linear_system=False,
                    refree=False,
                    bccontrol=False,
                    palpha=None,
                    use_old_data=False,
                    mddir='pathtodatastorage'):
    """compute and export the system matrices for Navier-Stokes equations

    Parameters
    ---
    refree : boolean, optional
        whether to use `Re=1` (so that the `Re` number can be applied later by
        scaling the corresponding matrices, defaults to `False`
    linear_system : boolean, optional
        whether to compute/return the linearized system, defaults to `False`
    bccontrol : boolean, optional
        whether to model boundary control at the cylinder via penalized robin
        boundary conditions, defaults to `False`
    palpha : float, optional
        penalization parameter for the boundary control, defaults to `None`,
        `palpha` is mandatory for `linear_system`

    """

    if refree:
        Re = 1
        print 'For the Reynoldsnumber free mats, we set Re=1'

    if problemname == 'drivencavity' and bccontrol:
        raise NotImplementedError('boundary control for the driven cavity' +
                                  ' is not implemented yet')

    if linear_system and bccontrol and palpha is None:
        raise UserWarning('For the linear system a' +
                          ' value for `palpha` is needed')
    if not linear_system and bccontrol:
        raise NotImplementedError('Nonlinear system with boundary control' +
                                  ' is not implemented yet')
    femp, stokesmatsc, rhsd_vfrc, rhsd_stbc = \
        dnsps.get_sysmats(problem=problemname, bccontrol=bccontrol, N=N, Re=Re)
    if linear_system and bccontrol:
        Arob = stokesmatsc['A'] + 1. / palpha * stokesmatsc['Arob']
        Brob = 1. / palpha * stokesmatsc['Brob']
    elif linear_system:
        Brob = 0

    invinds = femp['invinds']
    A, J = stokesmatsc['A'], stokesmatsc['J']
    fvc, fpc = rhsd_vfrc['fvc'], rhsd_vfrc['fpr']
    fv_stbc, fp_stbc = rhsd_stbc['fv'], rhsd_stbc['fp']
    invinds = femp['invinds']
    NV = invinds.shape[0]
    data_prfx = problemname + '__N{0}Re{1}'.format(N, Re)
    if bccontrol:
        data_prfx = data_prfx + '_penarob'

    soldict = stokesmatsc  # containing A, J, JT
    soldict.update(femp)  # adding V, Q, invinds, diribcs
    soldict.update(rhsd_vfrc)  # adding fvc, fpr
    fv = rhsd_vfrc['fvc'] + rhsd_stbc['fv']
    fp = rhsd_vfrc['fpr'] + rhsd_stbc['fp']
    # print 'get expmats: ||fv|| = {0}'.format(np.linalg.norm(fv))
    # print 'get expmats: ||fp|| = {0}'.format(np.linalg.norm(fp))
    # import scipy.sparse.linalg as spsla
    # print 'get expmats: ||A|| = {0}'.format(spsla.norm(A))
    # print 'get expmats: ||Arob|| = {0}'.format(spsla.norm(Arob))
    # print 'get expmats: ||A|| = {0}'.format(spsla.norm(stokesmatsc['A']))
    # raise Warning('TODO: debug')

    soldict.update(fv=fv,
                   fp=fp,
                   N=N,
                   nu=nu,
                   clearprvdata=~use_old_data,
                   get_datastring=None,
                   data_prfx=ddir + data_prfx + '_stst',
                   paraviewoutput=False)
    if bccontrol and linear_system:
        soldict.update(A=Arob)

    # compute the uncontrolled steady state Navier-Stokes solution
    vp_ss_nse, list_norm_nwtnupd = snu.solve_steadystate_nse(return_vp=True,
                                                             **soldict)
    v_ss_nse, p_ss_nse = vp_ss_nse[:NV], vp_ss_nse[NV:]

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

    #
    # Control mats
    #
    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

    # the pressure observation mean over a small domain
    if problemname == 'cylinderwake':
        podcoo = dict(xmin=0.6, xmax=0.64, ymin=0.18, ymax=0.22)
    elif problemname == 'drivencavity':
        podcoo = dict(xmin=0.45, xmax=0.55, ymin=0.7, ymax=0.8)
    else:
        podcoo = femp['odcoo']

    # description of the control and observation domains
    dmd = femp['cdcoo']
    xmin, xmax, ymin, ymax = dmd['xmin'], dmd['xmax'], dmd['ymin'], dmd['ymax']
    velcondomstr = 'vel control domain: [{0}, {1}]x[{2}, {3}]\n'.\
        format(xmin, xmax, ymin, ymax)
    dmd = femp['odcoo']
    xmin, xmax, ymin, ymax = dmd['xmin'], dmd['xmax'], dmd['ymin'], dmd['ymax']
    velobsdomstr = 'vel observation domain: [{0}, {1}]x[{2}, {3}]\n'.\
        format(xmin, xmax, ymin, ymax)
    dmd = podcoo
    xmin, xmax, ymin, ymax = dmd['xmin'], dmd['xmax'], dmd['ymin'], dmd['ymax']
    pobsdomstr = 'pressure observation domain: [{0}, {1}]x[{2}, {3}]\n'.\
        format(xmin, xmax, ymin, ymax)

    pcmat = cou.get_pavrg_onsubd(odcoo=podcoo, Q=femp['Q'], ppin=None)

    cdatstr = snu.get_datastr_snu(time=None, meshp=N, nu=nu, Nts=None)

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

    ctrl_visu_str = \
        ' the (distributed) control setup is as follows \n' +\
        ' B maps into the domain of control -' +\
        velcondomstr +\
        ' the first half of the columns' +\
        'actuate in x-direction, the second in y direction \n' +\
        ' Cv measures averaged velocities in the domain of observation' +\
        velobsdomstr +\
        ' Cp measures the averaged pressure' +\
        ' in the domain of pressure observation: ' +\
        pobsdomstr +\
        ' 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 `get_exp_nsmats.py` ' +\
        '(see https://github.com/highlando/dolfin_navier_scipy) at\n' +\
        datetime.datetime.now().strftime("%I:%M%p on %B %d, %Y")

    if bccontrol and problemname == 'cylinderwake' and linear_system:
        ctrl_visu_str = \
            ('the boundary control is realized via penalized robin \n' +
             'boundary conditions, cf. e.g. [Hou/Ravindran `98], \n' +
             'with predefined shape functions for the cylinder wake \n' +
             'and the penalization parameter `palpha`={0}.').format(palpha) +\
            ctrl_visu_str

    if linear_system:
        convc_mat, rhs_con, rhsv_conbc = \
            snu.get_v_conv_conts(prev_v=v_ss_nse, invinds=invinds,
                                 V=femp['V'], diribcs=femp['diribcs'])
        # TODO: omg
        if bccontrol:
            f_mat = -Arob - convc_mat
        else:
            f_mat = -stokesmatsc['A'] - convc_mat

        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 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' +\
            ctrl_visu_str

        matstr = (mddir + problemname + '__mats_N{0}_Re{1}').format(NV, Re)
        if bccontrol:
            matstr = matstr + '__penarob_palpha{0}'.format(palpha)

        scipy.io.savemat(
            matstr,
            dict(A=f_mat,
                 M=stokesmatsc['M'],
                 nu=femp['nu'],
                 Re=femp['Re'],
                 J=stokesmatsc['J'],
                 B=b_mat,
                 C=c_mat,
                 Cp=pcmat,
                 Brob=Brob,
                 v_ss_nse=v_ss_nse,
                 info=infostr,
                 contsetupstr=contsetupstr,
                 datastr=cdatstr,
                 coors=coors,
                 xinds=xinds,
                 yinds=yinds,
                 corfunvec=corfunvec))

        print('matrices saved to ' + matstr)

    elif refree:
        hstr = ddir + problemname + '_N{0}_hmat'.format(N)
        try:
            hmat = dou.load_spa(hstr)
            print 'loaded `hmat`'
        except IOError:
            print 'assembling hmat ...'
            hmat = dts.ass_convmat_asmatquad(W=femp['V'], invindsw=invinds)
            dou.save_spa(hmat, hstr)

        zerv = np.zeros((NV, 1))
        bc_conv, bc_rhs_conv, rhsbc_convbc = \
            snu.get_v_conv_conts(prev_v=zerv, V=femp['V'], invinds=invinds,
                                 diribcs=femp['diribcs'], Picard=False)

        # diff_mat = stokesmatsc['A']
        # bcconv_mat = bc_conv
        # fv_bcdiff = fv_stbc
        # fv_bcconv = - bc_rhs_conv
        fv = fvc
        fp = fpc
        # fp_bc = fp_stbc

        infostr = 'These are the coefficient matrices of the quadratic ' +\
            'formulation of the Navier-Stokes Equations \n for the ' +\
            problemname + ' to be used as \n\n' +\
            ' $M \\dot v + Av + H*kron(v,v) + J^Tp = Bu + fv$ \n' +\
            ' and  $Jv = fp$ \n\n' +\
            ' the Reynoldsnumber is computed as L/nu \n' +\
            ' note that `A` contains the diffusion and the linear term \n' +\
            ' that comes from the dirichlet boundary values \n' +\
            ' as initial value one can use the provided steady state \n' +\
            ' Stokes solution \n' +\
            ' see https://github.com/highlando/dolfin_navier_scipy/blob/' +\
            ' master/tests/solve_nse_quadraticterm.py for appl example\n' +\
            ctrl_visu_str

        scipy.io.savemat(
            mddir + problemname + 'quadform__mats_N{0}_Re{1}'.format(NV, Re),
            dict(
                A=f_mat,
                M=stokesmatsc['M'],
                H=-hmat,
                fv=fv,
                fp=fp,
                nu=femp['nu'],
                Re=femp['Re'],
                J=stokesmatsc['J'],
                B=b_mat,
                Cv=c_mat,
                Cp=pcmat,
                info=infostr,
                # ss_stokes=old_v,
                contsetupstr=contsetupstr,
                datastr=cdatstr,
                coors=coors,
                xinds=xinds,
                yinds=yinds,
                corfunvec=corfunvec))
    else:
        hstr = ddir + problemname + '_N{0}_hmat'.format(N)
        try:
            hmat = dou.load_spa(hstr)
            print 'loaded `hmat`'
        except IOError:
            print 'assembling hmat ...'
            hmat = dts.ass_convmat_asmatquad(W=femp['V'], invindsw=invinds)
            dou.save_spa(hmat, hstr)

        zerv = np.zeros((NV, 1))
        bc_conv, bc_rhs_conv, rhsbc_convbc = \
            snu.get_v_conv_conts(prev_v=zerv, V=femp['V'], invinds=invinds,
                                 diribcs=femp['diribcs'], Picard=False)

        f_mat = -stokesmatsc['A'] - bc_conv
        l_mat = -bc_conv
        fv = fv_stbc + fvc - bc_rhs_conv
        fp = fp_stbc + fpc

        vp_stokes = lau.solve_sadpnt_smw(amat=A,
                                         jmat=J,
                                         rhsv=fv_stbc + fvc,
                                         rhsp=fp_stbc + fpc)
        old_v = vp_stokes[:NV]
        p_stokes = -vp_stokes[NV:]  # the pressure was flipped for symmetry

        infostr = 'These are the coefficient matrices of the quadratic ' +\
            'formulation of the Navier-Stokes Equations \n for the ' +\
            problemname + ' to be used as \n\n' +\
            ' $M \\dot v = Av + H*kron(v,v) + J^Tp + Bu + fv$ \n' +\
            ' and  $Jv = fp$ \n\n' +\
            ' the Reynoldsnumber is computed as L/nu \n' +\
            ' note that `A` contains the diffusion and the linear term `L`\n' +\
            ' that comes from the dirichlet boundary values \n' +\
            ' for linearizations it might be necessary to consider `A-L` \n' +\
            ' as initial value one can use the provided steady state \n' +\
            ' Stokes solution \n' +\
            ' see https://github.com/highlando/dolfin_navier_scipy/blob/' +\
            ' master/tests/solve_nse_quadraticterm.py for appl example\n' +\
            ctrl_visu_str

        scipy.io.savemat(
            mddir + problemname + 'quadform__mats_N{0}_Re{1}'.format(NV, Re),
            dict(A=f_mat,
                 M=stokesmatsc['M'],
                 H=-hmat,
                 fv=fv,
                 fp=fp,
                 L=l_mat,
                 nu=femp['nu'],
                 Re=femp['Re'],
                 J=stokesmatsc['J'],
                 B=b_mat,
                 Cv=c_mat,
                 Cp=pcmat,
                 info=infostr,
                 p_ss_stokes=p_stokes,
                 p_ss_nse=p_ss_nse,
                 v_ss_stokes=old_v,
                 v_ss_nse=v_ss_nse,
                 contsetupstr=contsetupstr,
                 datastr=cdatstr,
                 coors=coors,
                 xinds=xinds,
                 yinds=yinds,
                 corfunvec=corfunvec))
fh.setFormatter(formatter)
logger.addHandler(fh)

problemname = 'cylinderwake'
N = 2
Nref = 3
Re = 10

femp, stokesmatsc, rhsd = dnsps.get_sysmats(problem=problemname, N=N, Re=Re,
                                            mergerhs=True)
soldict = stokesmatsc  # containing A, J, JT
soldict.update(femp)  # adding V, Q, invinds, diribcs
soldict.update(rhsd)  # adding the discrete rhs

v_ss_nse, list_norm_nwtnupd = snu.solve_steadystate_nse(N=N, **soldict)

vwbc = dts.append_bcs_vec(v_ss_nse, **femp)
vwbcf, _ = dts.expand_vp_dolfunc(vc=vwbc, V=femp['V'])

fempref, stokesmatsc, rhsd = dnsps.get_sysmats(problem=problemname, N=Nref,
                                               Re=Re, mergerhs=True)
Vref = fempref['V']


class ExtFunZero(dolfin.Expression):
    def __init__(self, vfun=None):
        self.vfun = vfun

    def eval(self, value, x):
        try:
Exemple #19
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 testit(problem=None,
           nu=None,
           charvel=None,
           Re=None,
           meshlvl=1,
           gradvsymmtrc=True,
           rho=1.,
           ParaviewOutput=False,
           scheme='TH'):

    meshfile = 'mesh/karman2D-rotcyl_lvl{0}.xml.gz'.format(meshlvl)
    physregs = 'mesh/karman2D-rotcyl_lvl{0}_facet_region.xml.gz'.\
        format(meshlvl)
    femp, stokesmatsc, rhsd = \
        dnsps.get_sysmats(problem=problem, nu=nu,
                          charvel=charvel, gradvsymmtrc=gradvsymmtrc,
                          scheme=scheme, mergerhs=True,
                          meshparams=dict(strtomeshfile=meshfile,
                                          movingwallcntrl=False,
                                          strtophysicalregions=physregs,
                                          strtobcsobs=geodata))

    ddir = 'data/'
    data_prfx = problem + '{2}_mesh{0}_Re{1}'.format(meshlvl, femp['Re'],
                                                     scheme)

    # ## Parameters for the benchmark values
    Um = charvel  # (we alread scale the inflow parabola accordingly)
    L = femp['charlen']  # characteristic length
    NP, NV = stokesmatsc['J'].shape
    print('NV + NP : {0} + {1} = {2}'.format(NV, NP, NV + NP))

    soldict = stokesmatsc  # containing A, J, JT
    # soldict.update(femp)  # adding V, Q, invinds, diribcs
    soldict.update(invinds=femp['invinds'], V=femp['V'], Q=femp['Q'])
    soldict.update(fv=rhsd['fv'],
                   fp=rhsd['fp'],
                   N=meshlvl,
                   nu=nu,
                   verbose=True,
                   return_vp=True,
                   get_datastring=None,
                   dbcinds=femp['dbcinds'],
                   dbcvals=femp['dbcvals'],
                   data_prfx=ddir + data_prfx,
                   paraviewoutput=ParaviewOutput,
                   vfileprfx=proutdir + 'vel_',
                   pfileprfx=proutdir + 'p_')

    #
    # compute the uncontrolled steady state Navier-Stokes solution
    #
    vp_ss_nse = snu.solve_steadystate_nse(**soldict)
    vss, dynpss = dts.expand_vp_dolfunc(vc=vp_ss_nse[0],
                                        pc=vp_ss_nse[1],
                                        **femp)
    steady_state_res = \
        get_steady_state_res(V=femp['V'], gradvsymmtrc=True,
                             outflowds=femp['outflowds'], nu=nu)

    res = steady_state_res(vss, rho * dynpss)
    auxvec = np.zeros((femp['V'].dim(), ))
    invinds = femp['invinds']
    auxvec[invinds] = res.get_local()[invinds]
    print('two norm of the res: {0}'.format(np.linalg.norm(auxvec)))

    phionevec = np.zeros((femp['V'].dim(), 1))
    phionevec[femp['ldsbcinds'], :] = 1.
    phione = dolfin.Function(femp['V'])
    phione.vector().set_local(phionevec)
    pickx = dolfin.as_matrix([[1., 0.], [0., 0.]])
    picky = dolfin.as_matrix([[0., 0.], [0., 1.]])
    pox = pickx * phione
    poy = picky * phione
    drag = steady_state_res(vss, rho * dynpss, phi=pox)
    lift = steady_state_res(vss, rho * dynpss, phi=poy)
    cdclfac = 2. / (rho * L * Um**2)

    print('Computed via testing the residual: ')
    print('Cl: {0}'.format(cdclfac * lift))
    print('Cd: {0}'.format(cdclfac * drag))

    phionevec = np.zeros((femp['V'].dim(), 1))
    phionevec[femp['ldsbcinds'], :] = 1.
    phione = dolfin.Function(femp['V'])
    phione.vector().set_local(phionevec)
    # phionex = phione.sub(0)

    print('Computed via `dnsps.LiftDragSurfForce`:')
    realpss = rho * dynpss  # Um**2*rho*dynpss
    realvss = vss  # Um*vss
    getld = dnsps.LiftDragSurfForce(V=femp['V'],
                                    nu=nu,
                                    ldds=femp['liftdragds'],
                                    outflowds=femp['outflowds'],
                                    phione=phione)
    clift, cdrag = getld.evaliftdragforce(u=realvss, p=realpss)
    print('Cl: {0}'.format(cdclfac * clift))
    print('Cd: {0}'.format(cdclfac * cdrag))

    a_1 = dolfin.Point(0.15, 0.2)
    a_2 = dolfin.Point(0.25, 0.2)
    pdiff = realpss(a_1) - realpss(a_2)
    print('Delta P: {0}'.format(pdiff))

    print('\n values from Schaefer/Turek as in')
    print('www.featflow.de/en/benchmarks/cfdbenchmarking/flow/' +
          'dfg_benchmark1_re20.html:')
    print('Cl: {0}'.format(0.010618948146))
    print('Cd: {0}'.format(5.57953523384))
    print('Delta P: {0}'.format(0.11752016697))