def get_conv_curfv_rearr(v, PrP, tcur, B2BoolInv):

    ConV = dts.get_convvec(u0_dolfun=v, V=PrP.V)
    ConV = ConV[PrP.invinds, ]

    ConV = np.vstack([ConV[~B2BoolInv], ConV[B2BoolInv]])

    CurFv = dts.get_curfv(PrP.V, PrP.fv, PrP.invinds, tcur)
    if len(CurFv) != len(PrP.invinds):
        raise Warning('Need fv at innernodes here')
    CurFv = np.vstack([CurFv[~B2BoolInv], CurFv[B2BoolInv]])

    return ConV, CurFv
def roth_upd_ind2(vvec=None, cts=None, nu=None, Vc=None, diribcsc=None,
                  nmd=dict(V=None, Q=None,
                           M=None, A=None, J=None, fv=None, fp=None,
                           invinds=None, diribcs=None, coefalu=None),
                  returnalu=False, **kwargs):
    """ advancing `v, p` for one time using Rothe's method

    Parameters
    ---
    nmd : dict
        containing the data (mesh, matrices, rhs) from the next time step
    vvec : (n,1)-array
        current solution
    Vc : dolfin.mesh
        current mesh

    Notes
    -----
    Time dependent Dirichlet conditions are not supported by now
    """
    logger.debug("length of vvec={0}".format(vvec.size))
    if not nmd['V'] == Vc:
        vvec = _vctovn(vvec=vvec, Vc=Vc, Vn=nmd['V'])
        logger.debug('len(vvec)={0}, dim(Vn)={1}, dim(Vc)={2}'.
                     format(vvec.size, nmd['V'].dim(), Vc.dim()))
    mvvec = nmd['M']*vvec[nmd['invinds'], :]
    convvec = dts.get_convvec(u0_vec=vvec, V=nmd['V'],
                              diribcs=nmd['diribcs'],
                              invinds=nmd['invinds'])
    if nmd['coefalu'] is None:
        mta = nmd['M'] + cts*nmd['A']
        mtJT = -cts*nmd['J'].T
    else:
        mta = None
        mtJT = None

    rhsv = mvvec + cts*(nmd['fv'] - convvec)

    lsdpdict = dict(amat=mta, jmat=nmd['J'], jmatT=mtJT, rhsv=rhsv,
                    rhsp=nmd['fp'], sadlu=nmd['coefalu'],
                    return_alu=returnalu)
    if returnalu:
        vp_new, coefalu = lau.solve_sadpnt_smw(**lsdpdict)
        return vp_new, coefalu
    else:
        vp_new = lau.solve_sadpnt_smw(**lsdpdict)
        return vp_new
    def test_linearized_mat_NSE_form(self):
        """check the conversion: dolfin form <-> numpy arrays

          and the linearizations"""

        import dolfin_navier_scipy.dolfin_to_sparrays as dts

        u = self.fenics_sol_u
        u.t = 1.0
        ufun = dolfin.project(u, self.V)
        uvec = ufun.vector().get_local().reshape(len(ufun.vector()), 1)

        N1, N2, fv = dts.get_convmats(u0_dolfun=ufun, V=self.V)
        conv = dts.get_convvec(u0_dolfun=ufun, V=self.V)

        self.assertTrue(np.allclose(conv, N1 * uvec))
        self.assertTrue(np.allclose(conv, N2 * uvec))
    def test_linearized_mat_NSE_form(self):
        """check the conversion: dolfin form <-> numpy arrays

          and the linearizations"""

        import dolfin_navier_scipy.dolfin_to_sparrays as dts

        u = self.fenics_sol_u
        u.t = 1.0
        ufun = dolfin.project(u, self.V)
        uvec = ufun.vector().get_local().reshape(len(ufun.vector()), 1)

        N1, N2, fv = dts.get_convmats(u0_dolfun=ufun, V=self.V)
        conv = dts.get_convvec(u0_dolfun=ufun, V=self.V)

        self.assertTrue(np.allclose(conv, N1 * uvec))
        self.assertTrue(np.allclose(conv, N2 * uvec))
예제 #5
0
 def getconvvec(vvec):
     return dts.get_convvec(u0_vec=vvec, V=V,
                            diribcs=diribcs, invinds=invinds)
    def test_residuals(self):
        femp, stokesmatsc, rhsd = \
            dnsps.get_sysmats(problem=self.problem, nu=self.nu,
                              bccontrol=False, charvel=self.charvel,
                              scheme=self.scheme, mergerhs=True,
                              meshparams=self.meshparams)

        # setting some parameters

        t0 = 0.0
        tE = .1
        Nts = 2
        tips = dict(t0=t0, tE=tE, Nts=Nts)

        soldict = stokesmatsc  # containing A, J, JT
        soldict.update(femp)  # adding V, Q, invinds, diribcs
        soldict.update(tips)  # adding time integration params
        soldict.update(fv=rhsd['fv'],
                       fp=rhsd['fp'],
                       treat_nonl_explct=True,
                       return_vp_dict=True,
                       no_data_caching=True,
                       start_ssstokes=True)

        vpdct = snu.solve_nse(**soldict)
        M, A, JT = stokesmatsc['M'], stokesmatsc['A'], stokesmatsc['JT']
        fv = rhsd['fv']
        V, invinds = femp['V'], femp['invinds']
        dt = (tE - t0) / Nts
        tm = (tE - t0) / 2

        reschkdict = dict(V=V,
                          nu=self.nu,
                          gradvsymmtrc=True,
                          outflowds=femp['outflowds'])
        euleres = get_imex_res(explscheme='eule', **reschkdict)
        heunres = get_imex_res(explscheme='heun', **reschkdict)
        crnires = get_imex_res(explscheme='abtw', **reschkdict)

        # the initial value
        inivwbcs = vpdct[t0]['v']
        iniv = inivwbcs[invinds]
        iniconvvec = dts.get_convvec(V=V, u0_vec=inivwbcs, invinds=invinds)
        inivelfun = dts.expand_vp_dolfunc(vc=inivwbcs, **femp)[0]

        # the Heun prediction step
        cneevwbcs = vpdct[(tm, 'heunpred')]['v']
        cneev = cneevwbcs[invinds]
        cneep = vpdct[(tm, 'heunpred')]['p']

        # the Heun step
        cnhevwbcs = vpdct[tm]['v']
        cnhev = cnhevwbcs[invinds]
        cnhep = vpdct[tm]['p']
        hpconvvec = dts.get_convvec(V=V, u0_vec=cneevwbcs, invinds=invinds)
        hpvelfun = dts.expand_vp_dolfunc(vc=cneevwbcs, **femp)[0]

        # the AB2 step
        cnabvwbcs = vpdct[tE]['v']
        cnabv = cnabvwbcs[invinds]
        cnabp = vpdct[tE]['p']
        hcconvvec = dts.get_convvec(V=V, u0_vec=cnhevwbcs, invinds=invinds)
        hcvelfun = dts.expand_vp_dolfunc(vc=cnhevwbcs, **femp)[0]

        print('Heun-Prediction: one step of Euler')
        resvec = (1. / dt * M * (cneev - iniv) + .5 * A * (iniv + cneev) +
                  iniconvvec - JT * cneep - fv)
        hpscres = np.linalg.norm(resvec)
        print('Scipy residual: ', hpscres)
        curv, curp = dts.expand_vp_dolfunc(vc=cneevwbcs, pc=cneep, **femp)
        res = euleres(curv, curp, dt, lastvel=inivelfun)
        hpfnres = np.linalg.norm(res.get_local()[invinds])
        print('dolfin residua: ', hpfnres)

        self.assertTrue(np.allclose(hpfnres, 0.))
        self.assertTrue(np.allclose(hpscres, 0.))

        print('\nHeun-Step:')
        heunrhs = M * iniv - .5 * dt * \
            (A * iniv + iniconvvec + hpconvvec) + dt * fv
        matvp = M * cnhev + .5 * dt * A * cnhev - dt * JT * cnhep
        hcscres = np.linalg.norm(matvp - heunrhs)
        print('Scipy residual: ', hcscres)
        # import ipdb; ipdb.set_trace()
        curv, curp = dts.expand_vp_dolfunc(vc=cnhevwbcs, pc=cnhep, **femp)
        heunres = heunres(curv, curp, dt, lastvel=inivelfun, othervel=hpvelfun)
        hcfnres = np.linalg.norm(heunres.get_local()[invinds])
        print('dolfin residua: ', hcfnres)

        self.assertTrue(np.allclose(hcfnres, 0.))
        self.assertTrue(np.allclose(hcscres, 0.))

        print('\nAB2-Step:')
        abtrhs = M * cnhev - .5 * dt * \
            (A * cnhev + -iniconvvec + 3. * hcconvvec) + dt * fv
        matvp = M * cnabv + .5 * dt * A * cnabv - dt * JT * cnabp
        abscres = np.linalg.norm(matvp - abtrhs)
        print('Scipy residual: ', abscres)

        # import ipdb; ipdb.set_trace()
        curv, curp = dts.expand_vp_dolfunc(vc=cnabvwbcs, pc=cnabp, **femp)
        crnires = crnires(curv, curp, dt, lastvel=hcvelfun, othervel=inivelfun)
        abfnres = np.linalg.norm(crnires.get_local()[invinds])
        print('dolfin residua: ', abfnres)

        self.assertTrue(np.allclose(abfnres, 0.))
        self.assertTrue(np.allclose(abscres, 0.))
def roth_upd_smmx(vvec=None, cts=None, nu=None, Vc=None, diribcsc=None,
                  nmd=dict(V=None, Q=None, M=None, invinds=None, npc=None,
                           MSme=None, ASme=None, JSme=None, fvSme=None,
                           fp=None, diribcs=None, coefalu=None,
                           smmxqq2vel=None, vel2smmxqq=None),
                  returnalu=False, **kwargs):
    """ advancing `v, p` for one time using Rothe's method

    Parameters
    ---
    vvec : (n, 1) array
        the current velocity solution vector incl. bcs in the actual coors
    nmd : dict
        containing the data (mesh, matrices, rhs) from the next time step,
        with the `*Sme` matrices resorted according to the minimal extension
    vvec : (n,1)-array
        current solution
    Vc : dolfin.mesh
        current mesh

    Notes
    -----
    Time dependent Dirichlet conditions are not supported by now
    """

    Npc = nmd['npc']
    # split the coeffs
    J1Sme = nmd['JSme'][:, :-Npc]
    J2Sme = nmd['JSme'][:, -Npc:]

    M1Sme = nmd['MSme'][:, :-Npc]
    M2Sme = nmd['MSme'][:, -Npc:]

    A1Sme = nmd['ASme'][:, :-Npc]
    A2Sme = nmd['ASme'][:, -Npc:]

    if not nmd['V'] == Vc:
        vvec = _vctovn(vvec=vvec, Vc=Vc, Vn=nmd['V'])
        logger.debug('interpolate v: len(vvec)={0}, dim(Vn)={1}, dim(Vc)={2}'.
                     format(vvec.size, nmd['V'].dim(), Vc.dim()))
    q1c, q2c = nmd['vel2smmxqq'](vvec[nmd['invinds']])

    convvec = dts.get_convvec(u0_vec=vvec, V=nmd['V'],
                              diribcs=nmd['diribcs'],
                              invinds=nmd['invinds'])
    logger.debug('in `roth_upd_smmx`: |[q1,q2]|={0}'.
                 format(npla.norm(np.vstack([q1c, q2c]))))
    logger.debug('in `roth_upd_smmx`: cts={0}'.format(cts))
    logger.debug('in `roth_upd_smmx`: |vvec|={0}'.
                 format(npla.norm(vvec[nmd['invinds']])))

    coefmatmom = sps.hstack([1/cts*M1Sme+A1Sme, M2Sme, -nmd['JSme'].T, A2Sme])
    coefmdivdrv = sps.hstack([1/cts*J1Sme, J2Sme,
                              sps.csr_matrix((Npc, 2*Npc))])
    coefmdiv = sps.hstack([J1Sme, sps.csr_matrix((Npc, 2*Npc)), J2Sme])
    coefmat = sps.vstack([coefmatmom, coefmdivdrv, coefmdiv])

    rhsmom = 1/cts*M1Sme*q1c - nmd['vel2smmxqq'](convvec, getitstacked=True) +\
        nmd['fvSme']
    rhsdivdrv = 1/cts*J1Sme*q1c
    rhsdiv = nmd['fp']
    rhs = np.vstack([rhsmom, rhsdivdrv, rhsdiv])
    logger.debug('in `roth_upd_smmx`: |rhs|={0}'.format(npla.norm(rhs)))

    qqpqnext = spsla.spsolve(coefmat, rhs)

    Nvc = A1Sme.shape[0]
    q1, q2 = qqpqnext[:Nvc-Npc], qqpqnext[Nvc+Npc:Nvc+2*Npc]
    p_new = qqpqnext[Nvc:Nvc+Npc]
    v_new = nmd['smmxqq2vel'](q1=q1, q2=q2)
    vp_new = np.vstack([v_new, p_new.reshape((p_new.size, 1))])
    logger.debug('in `roth_upd_smmx`: |vpnew|={0}'.format(npla.norm(vp_new)))

    if returnalu:
        return vp_new, None
    else:
        return vp_new
def get_v_conv_conts(prev_v=None, V=None, invinds=None, diribcs=None,
                     dbcvals=None, dbcinds=None,
                     semi_explicit=False,
                     Picard=False, retparts=False, zerodiribcs=False):
    """ get and condense the linearized convection

    to be used in a Newton scheme

    .. math::

        (u \\cdot \\nabla) u \\to (u_0 \\cdot \\nabla) u + \
            (u \\cdot \\nabla) u_0 - (u_0 \\cdot \\nabla) u_0

    or in a Picard scheme

    .. math::

        (u \\cdot \\nabla) u \\to (u_0 \\cdot \\nabla) u

    Parameters
    ----------
    prev_v : (N,1) ndarray
        convection velocity
    V : dolfin.VectorFunctionSpace
        FEM space of the velocity
    invinds : (N,) ndarray or list
        indices of the inner nodes
    diribcs : list
        of dolfin Dirichlet boundary conditons
    Picard : Boolean
        whether Picard linearization is applied, defaults to `False`
    semi_explicit: Boolean, optional
        whether to return minus the convection vector, and zero convmats
        as needed for semi-explicit integration, defaults to `False`
    retparts : Boolean, optional
        whether to return both components of the matrices
        and contributions to the rhs through the boundary conditions,
        defaults to `False`

    Returns
    -------
    convc_mat : (N,N) sparse matrix
        representing the linearized convection at the inner nodes
    rhs_con : (N,1) array
        representing :math:`(u_0 \\cdot \\nabla )u_0` at the inner nodes
    rhsv_conbc : (N,1) ndarray
        representing the boundary conditions

    """

    if semi_explicit:
        rhs_con = dts.get_convvec(V=V, u0_vec=prev_v, diribcs=diribcs,
                                  dbcinds=dbcinds, dbcvals=dbcvals,
                                  invinds=invinds)

        return 0., -rhs_con, 0.

    N1, N2, rhs_con = dts.get_convmats(u0_vec=prev_v, V=V, invinds=invinds,
                                       dbcinds=dbcinds, dbcvals=dbcvals,
                                       diribcs=diribcs)

    if zerodiribcs:
        def _cndnsmts(mat, diribcs, **kw):
            return mat[invinds, :][:, invinds], np.zeros((invinds.size, 1))
    else:
        _cndnsmts = dts.condense_velmatsbybcs

    if Picard:
        convc_mat, rhsv_conbc = _cndnsmts(N1, velbcs=diribcs,
                                          dbcinds=dbcinds, dbcvals=dbcvals)
        # return convc_mat, rhs_con[invinds, ], rhsv_conbc
        return convc_mat, None, rhsv_conbc

    elif retparts:
        picrd_convc_mat, picrd_rhsv_conbc = _cndnsmts(N1, velbcs=diribcs,
                                                      dbcinds=dbcinds,
                                                      dbcvals=dbcvals)
        anti_picrd_convc_mat, anti_picrd_rhsv_conbc = \
            _cndnsmts(N2, velbcs=diribcs, dbcinds=dbcinds, dbcvals=dbcvals)
        return ((picrd_convc_mat, anti_picrd_convc_mat),
                rhs_con[invinds, ],
                (picrd_rhsv_conbc, anti_picrd_rhsv_conbc))

    else:
        convc_mat, rhsv_conbc = _cndnsmts(N1+N2, velbcs=diribcs,
                                          dbcinds=dbcinds, dbcvals=dbcvals)
        return convc_mat, rhs_con[invinds, ], rhsv_conbc
def halfexp_euler_nseind2(Mc, MP, Ac, BTc, Bc, fvbc, fpbc, PrP, TsP,
                          vp_init=None):
    """halfexplicit euler for the NSE in index 2 formulation
    """
    #
    #
    # Basic Eqn:
    #
    # 1/dt*M  -B.T    q+       1/dt*M*qc - K(qc) + fc
    #    B        * pc   =   g
    #
    #

    Nts, t0, tE, dt, Nv = init_time_stepping(PrP, TsP)

    tcur = t0

    MFac = dt
    CFac = 1  # /dt
    # PFac = -1  # -1 for symmetry (if CFac==1)
    PFacI = -1./dt

    dtstrdct = dict(prefix=TsP.svdatapath, method=2, N=PrP.N,
                    tolcor=TsP.TolCorB,
                    nu=PrP.nu, Nts=TsP.Nts, tol=TsP.linatol, te=TsP.tE)
    cdatstr = get_dtstr(t=t0, **dtstrdct)
    try:
        np.load(cdatstr + '.npy')
        print 'loaded data from ', cdatstr, ' ...'
    except IOError:
        np.save(cdatstr, vp_init)
        print 'saving to ', cdatstr, ' ...'

    v, p = expand_vp_dolfunc(PrP, vp=vp_init, vc=None, pc=None)
    TsP.UpFiles.u_file << v, tcur
    TsP.UpFiles.p_file << p, tcur
    Bcc, BTcc, MPc, fpbcc, vp_init, Npc = pinthep(Bc, BTc, MP, fpbc,
                                                  vp_init, PrP.Pdof)

    IterAv = MFac*sps.hstack([1.0/dt*Mc + Ac, PFacI*(-1)*BTcc])
    IterAp = CFac*sps.hstack([Bcc, sps.csr_matrix((Npc, Npc))])
    IterA = sps.vstack([IterAv, IterAp])
    if TsP.linatol == 0:
        IterAfac = spsla.factorized(IterA)

    vp_old = vp_init
    vp_old = np.vstack([vp_init[:Nv], 1./PFacI*vp_init[Nv:]])
    vp_oldold = vp_old
    ContiRes, VelEr, PEr, TolCorL = [], [], [], []

    # Mvp = sps.csr_matrix(sps.block_diag((Mc, MPc)))
    # Mvp = sps.eye(Mc.shape[0] + MPc.shape[0])
    # Mvp = None

    # M matrix for the minres routine
    # M accounts for the FEM discretization

    Mcfac = spsla.splu(Mc)
    MPcfac = spsla.splu(MPc)

    def _MInv(vp):
        # v, p = vp[:Nv, ], vp[Nv:, ]
        # lsv = krypy.linsys.LinearSystem(Mc, v, self_adjoint=True)
        # lsp = krypy.linsys.LinearSystem(MPc, p, self_adjoint=True)
        # Mv = (krypy.linsys.Cg(lsv, tol=1e-14)).xk
        # Mp = (krypy.linsys.Cg(lsp, tol=1e-14)).xk
        v, p = vp[:Nv, ], vp[Nv:, ]
        Mv = np.atleast_2d(Mcfac.solve(v.flatten())).T
        Mp = np.atleast_2d(MPcfac.solve(p.flatten())).T
        return np.vstack([Mv, Mp])

    MInv = spsla.LinearOperator(
        (Nv + Npc,
         Nv + Npc),
        matvec=_MInv,
        dtype=np.float32)

    def ind2_ip(vp1, vp2):
        """

        for applying the fem inner product
        """
        v1, v2 = vp1[:Nv, ], vp2[:Nv, ]
        p1, p2 = vp1[Nv:, ], vp2[Nv:, ]
        return mass_fem_ip(v1, v2, Mcfac) + mass_fem_ip(p1, p2, MPcfac)

    inikryupd = TsP.inikryupd
    iniiterfac = TsP.iniiterfac  # the first krylov step needs more maxiter

    for etap in range(1, TsP.NOutPutPts + 1):
        for i in range(Nts / TsP.NOutPutPts):
            cdatstr = get_dtstr(t=tcur+dt, **dtstrdct)
            try:
                vp_next = np.load(cdatstr + '.npy')
                print 'loaded data from ', cdatstr, ' ...'
                vp_next = np.vstack([vp_next[:Nv], 1./PFacI*vp_next[Nv:]])
                vp_oldold = vp_old
                vp_old = vp_next
                if tcur == dt+dt:
                    iniiterfac = 1  # fac only in the first Krylov Call
            except IOError:
                print 'computing data for ', cdatstr, ' ...'
                ConV = dts.get_convvec(u0_dolfun=v, V=PrP.V)
                CurFv = dts.get_curfv(PrP.V, PrP.fv, PrP.invinds, tcur)

                Iterrhs = np.vstack([MFac*1.0/dt*Mc*vp_old[:Nv, ],
                                     np.zeros((Npc, 1))]) +\
                    np.vstack([MFac*(fvbc + CurFv - ConV[PrP.invinds, ]),
                               CFac*fpbcc])

                if TsP.linatol == 0:
                    # ,vp_old,tol=TsP.linatol)
                    vp_new = IterAfac(Iterrhs.flatten())
                    # vp_new = spsla.spsolve(IterA, Iterrhs)
                    vp_old = np.atleast_2d(vp_new).T
                    TolCor = 0

                else:
                    if inikryupd and tcur == t0:
                        print '\n1st step direct solve to initialize krylov\n'
                        vp_new = spsla.spsolve(IterA, Iterrhs)
                        vp_old = np.atleast_2d(vp_new).T
                        TolCor = 0
                        inikryupd = False  # only once !!
                    else:
                        if TsP.TolCorB:
                            NormRhsInd2 = \
                                np.sqrt(ind2_ip(Iterrhs, Iterrhs))[0][0]
                            TolCor = 1.0 / np.max([NormRhsInd2, 1])
                        else:
                            TolCor = 1.0

                        curls = krypy.linsys.LinearSystem(IterA, Iterrhs,
                                                          M=MInv)

                        tstart = time.time()

                        # extrapolating the initial value
                        upv = (vp_old - vp_oldold)

                        ret = krypy.linsys.\
                            RestartedGmres(curls, x0=vp_old + upv,
                                           tol=TolCor*TsP.linatol,
                                           maxiter=iniiterfac*TsP.MaxIter,
                                           max_restarts=100)

                        # ret = krypy.linsys.\
                        #     Minres(curls, maxiter=20*TsP.MaxIter,
                        #            x0=vp_old + upv, tol=TolCor*TsP.linatol)
                        tend = time.time()
                        vp_oldold = vp_old
                        vp_old = ret.xk

                        print ('Needed {0} of max {4}*{1} iterations: ' +
                               'final relres = {2}\n TolCor was {3}').\
                            format(len(ret.resnorms), TsP.MaxIter,
                                   ret.resnorms[-1], TolCor, iniiterfac)
                        print 'Elapsed time {0}'.format(tend - tstart)
                        iniiterfac = 1  # fac only in the first Krylov Call

                np.save(cdatstr, np.vstack([vp_old[:Nv],
                                            PFacI*vp_old[Nv:]]))

            vc = vp_old[:Nv, ]
            print 'Norm of current v: ', np.linalg.norm(vc)
            pc = PFacI*vp_old[Nv:, ]

            v, p = expand_vp_dolfunc(PrP, vp=None, vc=vc, pc=pc)

            tcur += dt

            # the errors
            vCur, pCur = PrP.v, PrP.p
            try:
                vCur.t = tcur
                pCur.t = tcur - dt

                ContiRes.append(comp_cont_error(v, fpbc, PrP.Q))
                VelEr.append(errornorm(vCur, v))
                PEr.append(errornorm(pCur, p))
                TolCorL.append(TolCor)
            except AttributeError:
                ContiRes.append(0)
                VelEr.append(0)
                PEr.append(0)
                TolCorL.append(0)

        print '%d of %d time steps completed ' % (etap*Nts/TsP.NOutPutPts, Nts)

        if TsP.ParaviewOutput:
            TsP.UpFiles.u_file << v, tcur
            TsP.UpFiles.p_file << p, tcur

    TsP.Residuals.ContiRes.append(ContiRes)
    TsP.Residuals.VelEr.append(VelEr)
    TsP.Residuals.PEr.append(PEr)
    TsP.TolCor.append(TolCorL)

    return