Exemple #1
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))
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,
            ),
        )
def test_qbdae_ass(problemname='cylinderwake', N=1, Re=4e2, nu=3e-2,
                   t0=0.0, tE=1.0, Nts=100, use_saved_mats=None):

    trange = np.linspace(t0, tE, Nts+1)
    DT = (tE-t0)/Nts
    rdir = 'results/'
    femp, stokesmatsc, rhsd_vfrc, rhsd_stbc, \
        data_prfx, ddir, proutdir = \
        dns.problem_setups.get_sysmats(problem=problemname, N=N, Re=Re)
    invinds = femp['invinds']

    if use_saved_mats is None:

        A, J, M = stokesmatsc['A'], stokesmatsc['J'], stokesmatsc['M']
        fvc, fpc = rhsd_vfrc['fvc'], rhsd_vfrc['fpr']
        fv_stbc, fp_stbc = rhsd_stbc['fv'], rhsd_stbc['fp']

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

        invinds = femp['invinds']
        NV, NP = invinds.shape[0], J.shape[0]
        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)
        fp = fp_stbc + fpc
        fv = fv_stbc + fvc - bc_rhs_conv

        # Stokes solution as initial value
        vp_stokes = lau.solve_sadpnt_smw(amat=A, jmat=J,
                                         rhsv=fv_stbc + fvc,
                                         rhsp=fp_stbc + fpc)
        old_v = vp_stokes[:NV]

        sysmat = sps.vstack([sps.hstack([M+DT*(A+bc_conv), J.T]),
                             sps.hstack([J, sps.csc_matrix((NP, NP))])])
        # the observation
        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']

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

    if use_saved_mats is not None:
        # if saved as in ../get_exp_mats
        import scipy.io
        mats = scipy.io.loadmat(use_saved_mats)
        A = - mats['A']
        M = mats['M']
        J = mats['J']
        hmat = -mats['H']
        fv = mats['fv']
        fp = mats['fp']
        NV, NP = fv.shape[0], fp.shape[0]
        old_v = mats['ss_stokes']
        sysmat = sps.vstack([sps.hstack([M+DT*A, J.T]),
                             sps.hstack([J, sps.csc_matrix((NP, NP))])])
        pcmat = mats['Cp']

    print 'computing LU once...'
    sysmati = spsla.factorized(sysmat)

    vfile = dolfin.File(rdir + problemname + 'qdae__vel.pvd')
    pfile = dolfin.File(rdir + problemname + 'qdae__p.pvd')

    prvoutdict = dict(V=femp['V'], Q=femp['Q'], vfile=vfile, pfile=pfile,
                      invinds=invinds, diribcs=femp['diribcs'],
                      vp=None, t=None, writeoutput=True)

    print 'doing the time loop...'
    poutlist = []
    for t in trange:
        # conv_mat, rhs_conv, rhsbc_conv = \
        #     snu.get_v_conv_conts(prev_v=old_v, V=femp['V'], invinds=invinds,
        #                          diribcs=femp['diribcs'], Picard=False)
        # crhsv = M*old_v + DT*(fv_stbc + fvc + rhs_conv + rhsbc_conv
        #                       - conv_mat*old_v)
        # raise Warning('TODO: debug')
        crhsv = M*old_v + DT*(fv - hmat*np.kron(old_v, old_v))
        crhs = np.vstack([crhsv, fp])
        vp_new = np.atleast_2d(sysmati(crhs.flatten())).T
        # vp_new = lau.solve_sadpnt_smw(amat=M+DT*(A+0*conv_mat), jmat=J,
        #                               rhsv=crhsv,
        #                               rhsp=fp_stbc + fpc)

        vp_new[NV:] = pcmat.T  # *vp_new[NV:]
        prvoutdict.update(dict(vp=vp_new, t=t))
        dou.output_paraview(**prvoutdict)

        old_v = vp_new[:NV]
        p = vp_new[NV:]
        poutlist.append(np.dot(pcmat, p)[0][0])

        print t, np.linalg.norm(old_v)

    dou.plot_prs_outp(outsig=poutlist, tmesh=trange)
def test_qbdae_ass(problemname='cylinderwake', N=1, Re=None, nu=3e-2,
                   t0=0.0, tE=1.0, Nts=100, use_saved_mats=None):

    trange = np.linspace(t0, tE, Nts+1)
    DT = (tE-t0)/Nts
    rdir = 'results/'
    ddir = 'data/'

    if use_saved_mats is None:
        femp, stokesmatsc, rhsd_vfrc, rhsd_stbc = \
            dns.problem_setups.get_sysmats(problem=problemname, N=N, Re=Re)
        invinds = femp['invinds']

        A, J, M = stokesmatsc['A'], stokesmatsc['J'], stokesmatsc['M']
        L = 0*A
        fvc, fpc = rhsd_vfrc['fvc'], rhsd_vfrc['fpr']
        fv_stbc, fp_stbc = rhsd_stbc['fv'], rhsd_stbc['fp']

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

        invinds = femp['invinds']
        NV, NP = invinds.shape[0], J.shape[0]
        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)
        fp = fp_stbc + fpc
        fv = fv_stbc + fvc - bc_rhs_conv

        if linnsesol:
            vp_nse, _ = snu.\
                solve_steadystate_nse(A=A, J=J, JT=None, M=M,
                                      fv=fv_stbc + fvc,
                                      fp=fp_stbc + fpc,
                                      V=femp['V'], Q=femp['Q'],
                                      invinds=invinds,
                                      diribcs=femp['diribcs'],
                                      return_vp=False, ppin=-1,
                                      N=N, nu=nu,
                                      clearprvdata=False)
            old_v = vp_nse[:NV]
        else:
            import sadptprj_riclyap_adi.lin_alg_utils as lau
            # Stokes solution as initial value
            vp_stokes = lau.solve_sadpnt_smw(amat=A, jmat=J,
                                             rhsv=fv_stbc + fvc,
                                             rhsp=fp_stbc + fpc)

            old_v = vp_stokes[:NV]

        sysmat = sps.vstack([sps.hstack([M+DT*(A+bc_conv), J.T]),
                             sps.hstack([J, sps.csc_matrix((NP, NP))])])

    if use_saved_mats is not None:
        # if saved as in ../get_exp_mats
        import scipy.io
        mats = scipy.io.loadmat(use_saved_mats)
        A = - mats['A']
        L = - mats['L']
        Re = mats['Re']
        N = A.shape[0]
        M = mats['M']
        J = mats['J']
        hmat = -mats['H']
        fv = mats['fv']
        fp = mats['fp']
        NV, NP = fv.shape[0], fp.shape[0]
        old_v = mats['ss_stokes']
        sysmat = sps.vstack([sps.hstack([M+DT*A, J.T]),
                             sps.hstack([J, sps.csc_matrix((NP, NP))])])

    if compevs:
        import matplotlib.pyplot as plt
        import scipy.linalg as spla

        hlstr = ddir + problemname + '_N{0}_Re{1}Nse{2}_hlmat'.\
            format(N, Re, linnsesol)
        HL = linearzd_quadterm(hmat, old_v, hlstr=hlstr)
        print(HL.shape)
        asysmat = sps.vstack([sps.hstack([-(A-L+HL), J.T]),
                              sps.hstack([J, sps.csc_matrix((NP, NP))])])
        msysmat = sps.vstack([sps.hstack([M, sps.csc_matrix((NV, NP))]),
                              sps.hstack([sps.csc_matrix((NP, NV)),
                                          sps.csc_matrix((NP, NP))])])
        levstr = ddir + problemname + '_N{0}Re{1}Nse{2}_levs'.\
            format(N, Re, linnsesol)
        try:
            levs = dou.load_npa(levstr)
            if debug:
                raise IOError()
            print('loaded the eigenvalues of the linearized system')
        except IOError:
            print('computing the eigenvalues of the linearized system')
            A = asysmat.todense()
            M = msysmat.todense()
            levs = spla.eigvals(A, M, overwrite_a=True, check_finite=False)
            dou.save_npa(levs, levstr)

        plt.figure(1)
        # plt.xlim((-25, 15))
        # plt.ylim((-50, 50))
        plt.plot(np.real(levs), np.imag(levs), '+')
        plt.show(block=False)

    if timeint:
        print('computing LU once...')
        sysmati = spsla.factorized(sysmat)

        vfile = dolfin.File(rdir + problemname + 'qdae__vel.pvd')
        pfile = dolfin.File(rdir + problemname + 'qdae__p.pvd')

        prvoutdict = dict(V=femp['V'], Q=femp['Q'], vfile=vfile, pfile=pfile,
                          invinds=invinds, diribcs=femp['diribcs'],
                          vp=None, t=None, writeoutput=True)

        print('doing the time loop...')
        for t in trange:
            crhsv = M*old_v + DT*(fv - hmat*np.kron(old_v, old_v))
            crhs = np.vstack([crhsv, fp])
            vp_new = np.atleast_2d(sysmati(crhs.flatten())).T

            prvoutdict.update(dict(vp=vp_new, t=t))
            dou.output_paraview(**prvoutdict)

            old_v = vp_new[:NV]
            print(t, np.linalg.norm(old_v))
Exemple #5
0
def test_qbdae_ass(problemname='cylinderwake',
                   N=1,
                   Re=None,
                   nu=3e-2,
                   t0=0.0,
                   tE=1.0,
                   Nts=100,
                   use_saved_mats=None):

    trange = np.linspace(t0, tE, Nts + 1)
    DT = (tE - t0) / Nts
    rdir = 'results/'
    ddir = 'data/'

    if use_saved_mats is None:
        femp, stokesmatsc, rhsd_vfrc, rhsd_stbc = \
            dns.problem_setups.get_sysmats(problem=problemname, N=N, Re=Re)
        invinds = femp['invinds']

        A, J, M = stokesmatsc['A'], stokesmatsc['J'], stokesmatsc['M']
        L = 0 * A
        fvc, fpc = rhsd_vfrc['fvc'], rhsd_vfrc['fpr']
        fv_stbc, fp_stbc = rhsd_stbc['fv'], rhsd_stbc['fp']

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

        invinds = femp['invinds']
        NV, NP = invinds.shape[0], J.shape[0]
        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)
        fp = fp_stbc + fpc
        fv = fv_stbc + fvc - bc_rhs_conv

        if linnsesol:
            vp_nse, _ = snu.\
                solve_steadystate_nse(A=A, J=J, JT=None, M=M,
                                      fv=fv_stbc + fvc,
                                      fp=fp_stbc + fpc,
                                      V=femp['V'], Q=femp['Q'],
                                      invinds=invinds,
                                      diribcs=femp['diribcs'],
                                      return_vp=False, ppin=-1,
                                      N=N, nu=nu,
                                      clearprvdata=False)
            old_v = vp_nse[:NV]
        else:
            import sadptprj_riclyap_adi.lin_alg_utils as lau
            # Stokes solution as initial value
            vp_stokes = lau.solve_sadpnt_smw(amat=A,
                                             jmat=J,
                                             rhsv=fv_stbc + fvc,
                                             rhsp=fp_stbc + fpc)

            old_v = vp_stokes[:NV]

        sysmat = sps.vstack([
            sps.hstack([M + DT * (A + bc_conv), J.T]),
            sps.hstack([J, sps.csc_matrix((NP, NP))])
        ])

    if use_saved_mats is not None:
        # if saved as in ../get_exp_mats
        import scipy.io
        mats = scipy.io.loadmat(use_saved_mats)
        A = -mats['A']
        L = -mats['L']
        Re = mats['Re']
        N = A.shape[0]
        M = mats['M']
        J = mats['J']
        hmat = -mats['H']
        fv = mats['fv']
        fp = mats['fp']
        NV, NP = fv.shape[0], fp.shape[0]
        old_v = mats['ss_stokes']
        sysmat = sps.vstack([
            sps.hstack([M + DT * A, J.T]),
            sps.hstack([J, sps.csc_matrix((NP, NP))])
        ])

    if compevs:
        import matplotlib.pyplot as plt
        import scipy.linalg as spla

        hlstr = ddir + problemname + '_N{0}_Re{1}Nse{2}_hlmat'.\
            format(N, Re, linnsesol)
        HL = linearzd_quadterm(hmat, old_v, hlstr=hlstr)
        print(HL.shape)
        asysmat = sps.vstack([
            sps.hstack([-(A - L + HL), J.T]),
            sps.hstack([J, sps.csc_matrix((NP, NP))])
        ])
        msysmat = sps.vstack([
            sps.hstack([M, sps.csc_matrix((NV, NP))]),
            sps.hstack([sps.csc_matrix((NP, NV)),
                        sps.csc_matrix((NP, NP))])
        ])
        levstr = ddir + problemname + '_N{0}Re{1}Nse{2}_levs'.\
            format(N, Re, linnsesol)
        try:
            levs = dou.load_npa(levstr)
            if debug:
                raise IOError()
            print('loaded the eigenvalues of the linearized system')
        except IOError:
            print('computing the eigenvalues of the linearized system')
            A = asysmat.todense()
            M = msysmat.todense()
            levs = spla.eigvals(A, M, overwrite_a=True, check_finite=False)
            dou.save_npa(levs, levstr)

        plt.figure(1)
        # plt.xlim((-25, 15))
        # plt.ylim((-50, 50))
        plt.plot(np.real(levs), np.imag(levs), '+')
        plt.show(block=False)

    if timeint:
        print('computing LU once...')
        sysmati = spsla.factorized(sysmat)

        vfile = dolfin.File(rdir + problemname + 'qdae__vel.pvd')
        pfile = dolfin.File(rdir + problemname + 'qdae__p.pvd')

        prvoutdict = dict(V=femp['V'],
                          Q=femp['Q'],
                          vfile=vfile,
                          pfile=pfile,
                          invinds=invinds,
                          diribcs=femp['diribcs'],
                          vp=None,
                          t=None,
                          writeoutput=True)

        print('doing the time loop...')
        for t in trange:
            crhsv = M * old_v + DT * (fv - hmat * np.kron(old_v, old_v))
            crhs = np.vstack([crhsv, fp])
            vp_new = np.atleast_2d(sysmati(crhs.flatten())).T

            prvoutdict.update(dict(vp=vp_new, t=t))
            dou.output_paraview(**prvoutdict)

            old_v = vp_new[:NV]
            print(t, np.linalg.norm(old_v))