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,
            ),
        )
示例#2
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))
示例#3
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