示例#1
0
    def __init__(self, cfg, **kwargs):
        super().__init__(cfg, **kwargs)

        # number of quadrature points inside each element
        self._Nq = self._K

        # the Gauss-Lobatto quadrature on standard interval
        self._z, self._w = zwglj(self._Nq, 0., 0.)

        # define the lagrange nodal basis
        self._B = nodal_basis_at(self._K, self._z, self._z).T

        # define the mass matrix
        # since the basis is identity, this just have weights on diagonal
        self._M = np.einsum("mq,q,lq->ml", self._B, self._w, self._B)
        self._invM = np.linalg.inv(self._M)

        # Forward transform operator
        self._fwdTransMat = self._B  # identity

        # interpolation operator
        Nqr = self.cfg.lookupint(basissect, 'Nqr')
        #zr = np.linspace(-1., 1., Nqr) # the reconstruction points
        zr, _ = zwglj(Nqr, 0., 0.)  # the reconstruction points
        Br = nodal_basis_at(self._K, self._z, zr).T  # at "recons" points
        #self._interpMat = np.einsum('kr,kq->rq', Br, self._fwdTransMat)
        self._interpMat = Br

        # the H tensor (see J. Comput. Phys. 378, 178-208, 2019)
        H = np.einsum("mq,aq,bq,q->mab", self._B, self._B, self._B, self._w)
        invM_H = np.einsum("ml,mab->lab", self._invM, H)
        invM_H = H

        # svd decomposition
        # defines the U, V matrices, and identifies the significant modes
        U, V, sigModes = [0] * self._K, [0] * self._K, [0] * self._K
        for m in range(self._K):
            u, s, v = np.linalg.svd(invM_H[m, :, :])
            U[m], V[m] = u, np.dot(np.diag(s), v)
            U[m], V[m] = map(filter_tol, (U[m], V[m]))
            nnzUm = np.where(np.sum(U[m], axis=0) != 0)[0]
            nnzVm = np.where(np.sum(V[m], axis=1) != 0)[0]
            sigModes[m] = np.intersect1d(nnzUm, nnzVm)

        self._U, self._V, self._sigModes = U, V, sigModes

        # define the {K-1} order derivative matrix
        D = jac_nodal_basis_at(self._K, self._z, self._z)[0]
        self._Sx = np.matmul(self._M, D.T).T
        self._derivMat = self._Sx.T

        # define the operator for reconstructing solution at faces
        self._Nqf = 2  # number of points used in reconstruction at faces
        zqf, _ = zwglj(self._Nqf, 0., 0.)
        self._Bqf = nodal_basis_at(self._K, self._z, zqf).T

        # define the correction functions at the left and right boundaries
        self._gLD = self._Bqf[:, 0]  #/self._w[0]
        self._gRD = self._Bqf[:, -1]  #/self._w[-1]
        #gLD, gRD = invM[0,:], invM[-1,:]

        # prepare kernels
        # since B is identity, (fwdTrans, bwdTrans) just copy data
        self._fwdTransKern = get_mm_kernel(self._fwdTransMat)
        self._bwdTransKern = get_mm_kernel(self._B.T)
        self._bwdTransFaceKern = get_mm_kernel(self._Bqf.T)
        self._derivKern = get_mm_kernel(self._Sx.T)
        self._invMKern = get_mm_kernel(self._invM.T)

        # U, V operator kernels
        for m in range(self._K):
            self._uTransKerns[m] = get_mm_kernel(self._U[m].T)
            self._vTransKerns[m] = get_mm_kernel(self._V[m])

        # operators for limiting
        V = ortho_basis_at(self._K, self._z).T
        invV = np.linalg.inv(V)

        computeCellAvgOp = V.copy()
        computeCellAvgOp[:, 1:] = 0
        computeCellAvgOp = np.matmul(computeCellAvgOp, invV)

        extractLinOp = V.copy()
        extractLinOp[:, 2:] = 0
        extractLinOp = np.matmul(extractLinOp, invV)
        extractDrLinOp = np.matmul(D.T, extractLinOp)

        self.computeCellAvgKern, self.extractDrLinKern = map(
            get_mm_kernel, (computeCellAvgOp, extractDrLinOp))
示例#2
0
    def __init__(self, cfg, **kwargs):
        super().__init__(cfg, **kwargs)

        # number of quadrature points inside each element
        self._Nq = self.cfg.lookupordefault(basissect, 'Nq',
                                            np.int(np.ceil(1.5 * self._K)))

        # define the orthonormal basis
        # the Gauss quadrature on standard interval
        self._z, self._w = zwgrjm(self._Nq, 0., 0.)

        # define the modified basis (see Karniadakis, page 64)
        self._B = self.modified_basis_at(self._K, self._z)

        # define the mass matrix
        self._M = np.einsum("mq,q,lq->ml", self._B, self._w, self._B)
        self._invM = np.linalg.inv(self._M)

        # Forward transform operator
        self._fwdTransMat = np.einsum("ml,lq,q->mq", self._invM, self._B,
                                      self._w)

        # interpolation operator
        Nqr = self.cfg.lookupint(basissect, 'Nqr')
        zr = np.linspace(-1, 1, Nqr)  # the reconstruction points
        Br = self.modified_basis_at(self._K, zr)  # basis at reconst points
        self._interpMat = Br

        # the H tensor (see J. Comput. Phys. 378, 178-208, 2019)
        H = np.einsum("mq,aq,bq,q->mab", self._B, self._B, self._B, self._w)
        invM_H = np.einsum("ml,mab->lab", self._invM, H)

        # svd decomposition
        # defines the U, V matrices, and identifies the significant modes
        U, V, sigModes = [0] * self._K, [0] * self._K, [0] * self._K
        for m in range(self._K):
            u, s, v = np.linalg.svd(H[m, :, :])
            U[m], V[m] = u, np.dot(np.diag(s), v)
            U[m], V[m] = map(filter_tol, (U[m], V[m]))
            nnzUm = np.where(np.sum(U[m], axis=0) != 0)[0]
            nnzVm = np.where(np.sum(V[m], axis=1) != 0)[0]
            sigModes[m] = np.intersect1d(nnzUm, nnzVm)

        self._U, self._V, self._sigModes = U, V, sigModes

        # define the {K-1} order derivative matrix
        D = self.jac_modified_basis_at(self._K, self._z)
        self._Sx = np.einsum("lq,q,mq->ml", self._B, self._w, D)
        #self._Sx = np.einsum("ml,mn->ln", self._invM, self._Sx)
        #self._Sx = np.einsum("lm,mn->ln", self._invM, self._Sx)

        # define the operator for reconstructing solution at faces
        self._Nqf = 2  # number of points used in reconstruction at faces
        zqf, _ = zwglj(self._Nqf, 0., 0.)
        self._Bqf = self.modified_basis_at(self._K, zqf)
        #self._gBqf = np.einsum("ml,mn->ln", self._invM, self._Bqf)

        # define the correction functions at the left and right boundaries
        #self._gLD, self._gRD = self._gBqf[:,0], self._gBqf[:,-1]
        self._gLD, self._gRD = self._Bqf[:, 0], self._Bqf[:, -1]

        # prepare kernels
        self._fwdTransKern = get_mm_kernel(self._fwdTransMat)
        self._bwdTransKern = get_mm_kernel(self._B.T)
        self._bwdTransFaceKern = get_mm_kernel(self._Bqf.T)
        self._derivKern = get_mm_kernel(self._Sx.T)
        self._invMKern = get_mm_kernel(self._invM.T)

        # U, V operator kernels
        for m in range(self._K):
            self._uTransKerns[m] = get_mm_kernel(self._U[m].T)
            self._vTransKerns[m] = get_mm_kernel(self._V[m])