示例#1
0
def assemblePatchInterpolationMatrix(IElement, NPatchFine, NCoarseElement):
    assert np.all(np.mod(NPatchFine, NCoarseElement) == 0)

    d = np.size(NPatchFine)

    NPatchCoarse = NPatchFine / NCoarseElement

    NpFine = np.prod(NPatchFine + 1)
    NpCoarse = np.prod(NPatchCoarse + 1)

    fineToPatchMap = util.lowerLeftpIndexMap(NCoarseElement, NPatchFine)
    coarseToPatchMap = util.lowerLeftpIndexMap(np.ones(d, dtype='int64'),
                                               NPatchCoarse)

    IElementCoo = IElement.tocoo()

    raisedRows = coarseToPatchMap[IElementCoo.row]
    raisedCols = fineToPatchMap[IElementCoo.col]

    pCoarseInd = util.lowerLeftpIndexMap(NPatchCoarse - 1, NPatchCoarse)
    pFineInd = util.pIndexMap(NPatchCoarse - 1, NPatchFine, NCoarseElement)

    fullRows = np.add.outer(pCoarseInd, raisedRows).flatten()
    fullCols = np.add.outer(pFineInd, raisedCols).flatten()
    fullData = np.tile(IElementCoo.data, np.size(pFineInd))

    I = sparse.csr_matrix((fullData, (fullRows, fullCols)),
                          shape=(NpCoarse, NpFine))

    return I
示例#2
0
    def computeFaceFluxTF(self, u, f=None):
        assert (f is None)

        world = self.world
        NWorldCoarse = world.NWorldCoarse
        d = np.size(NWorldCoarse)
        NtCoarse = np.prod(NWorldCoarse)
        NpCoarse = np.prod(NWorldCoarse + 1)

        fluxTF = np.zeros([NtCoarse, 2 * d])

        elementpIndexMap = util.elementpIndexMap(NWorldCoarse)
        elementpStartIndices = util.lowerLeftpIndexMap(NWorldCoarse - 1,
                                                       NWorldCoarse)

        for TInd in np.arange(NtCoarse):
            ecT = self.ecList[TInd]
            assert (hasattr(ecT, 'csi'))

            patchtStartIndex = util.convertpCoordinateToIndex(
                NWorldCoarse - 1, ecT.iPatchWorldCoarse)
            patchtIndexMap = util.lowerLeftpIndexMap(ecT.NPatchCoarse - 1,
                                                     NWorldCoarse - 1)
            elementpIndex = elementpStartIndices[TInd] + elementpIndexMap

            patchtIndices = patchtStartIndex + patchtIndexMap
            fluxTF[TInd, :] += np.einsum('iF, i -> F', ecT.csi.basisFluxTF,
                                         u[elementpIndex])
            fluxTF[patchtIndices, :] -= np.einsum('iTF, i -> TF',
                                                  ecT.csi.correctorFluxTF,
                                                  u[elementpIndex])

        return fluxTF
示例#3
0
def harmonicMeanOverFaces(NPatchCoarse, NCoarseElement, k, boundary, aPatch):
    NPatchFine = NPatchCoarse*NCoarseElement
    
    TPatchBasis = util.linearpIndexBasis(NPatchCoarse-1)

    NPatchBottom = np.array(NPatchCoarse)
    NPatchBottom[k] = 1
    NtBottom = np.prod(NPatchBottom)

    NPatchBase = np.array(NPatchCoarse)
    NPatchBase[k] -= 1
        
    TIndBase = util.lowerLeftpIndexMap(NPatchBase-1, NPatchCoarse-1)
    TIndBottom = util.lowerLeftpIndexMap(NPatchBottom-1, NPatchCoarse-1)

    t0Faces = faceElementIndices(NPatchCoarse, NCoarseElement, k, 0)
    t1Faces = faceElementIndices(NPatchCoarse, NCoarseElement, k, 1)

    aH0Faces = aPatch[t0Faces[TPatchBasis[k] + TIndBase]]
    aH1Faces = aPatch[t1Faces[TIndBase]]

    if boundary==0:
        abFaces = aPatch[t0Faces]
        abFaces[TPatchBasis[k] + TIndBase] = 2*aH0Faces*aH1Faces/(aH0Faces + aH1Faces)
    elif boundary==1:
        abFaces = aPatch[t1Faces]
        abFaces[TIndBase] = 2*aH0Faces*aH1Faces/(aH0Faces + aH1Faces)

    return abFaces
示例#4
0
def assembleProlongationMatrix(NPatchCoarse, NCoarseElement):  #, localBasis):
    d = np.size(NPatchCoarse)
    Phi = localBasis(NCoarseElement)
    assert np.size(Phi, 1) == 2**d

    NPatchFine = NPatchCoarse * NCoarseElement
    NtCoarse = np.prod(NPatchCoarse)
    NpCoarse = np.prod(NPatchCoarse + 1)
    NpFine = np.prod(NPatchFine + 1)

    rowsBasis = util.lowerLeftpIndexMap(NCoarseElement, NPatchFine)
    colsBasis = np.zeros_like(rowsBasis)

    rowsElement = np.tile(rowsBasis, 2**d)
    colsElement = np.add.outer(
        util.lowerLeftpIndexMap(np.ones(d, dtype='int64'), NPatchCoarse),
        colsBasis).flatten()

    rowsOffset = util.pIndexMap(NPatchCoarse - 1, NPatchFine, NCoarseElement)
    colsOffset = util.lowerLeftpIndexMap(NPatchCoarse - 1, NPatchCoarse)

    rows = np.add.outer(rowsOffset, rowsElement).flatten()
    cols = np.add.outer(colsOffset, colsElement).flatten()
    values = np.tile(Phi.flatten('F'), NtCoarse)

    rows, cols, values = util.ignoreDuplicates(rows, cols, values)
    PPatch = sparse.csc_matrix((values, (rows, cols)),
                               shape=(NpFine, NpCoarse))
    PPatch.eliminate_zeros()

    return PPatch
示例#5
0
def computeUpwindSaturation(NWorldCoarse, boundarys, sT, fluxTF):
    d = np.size(NWorldCoarse)
    
    sTF = np.tile(sT[...,None], [1, 2*d])
    basis = util.linearpIndexBasis(NWorldCoarse-1)
    for k in range(d):
        b = basis[k]

        N = np.array(NWorldCoarse-1)
        N[k] -= 1
        TIndBase = util.lowerLeftpIndexMap(N, NWorldCoarse-1)
            
        N[k] = 0
        TIndBottom = util.lowerLeftpIndexMap(N, NWorldCoarse-1)

        for face in [0,1]:
            faceInd = 2*k+face
            stepToFace = b*(face*(NWorldCoarse[k]-1))
            TIndInterior = (1-face)*b + TIndBase
            TIndBoundary = stepToFace + TIndBottom

            # Interior
            TIndDst = TIndInterior[fluxTF[TIndInterior, faceInd] < 0]
            TIndSrc = TIndDst + (2*face - 1)*b
            sTF[TIndDst, faceInd] = sT[TIndSrc]

            # Boundary
            TIndDst = TIndBoundary[fluxTF[TIndBoundary, faceInd] < 0]
            sTF[TIndDst, faceInd] = boundarys[k, face]
            
    return sTF
示例#6
0
    def localize(self, iSubPatchCoarse, NSubPatchCoarse):
        # Either ._aBase or ._aFine exists, not both
        if not hasattr(self, '_aFine'):
            a = self._aBase
        else:
            a = self._aFine

        NPatchCoarse = self.NPatchCoarse
        NCoarseElement = self.NCoarseElement
        NPatchFine = NPatchCoarse*NCoarseElement
        NSubPatchFine = NSubPatchCoarse*NCoarseElement
        iSubPatchFine = iSubPatchCoarse*NCoarseElement

        # rCoarse
        coarseTIndexMap = util.lowerLeftpIndexMap(NSubPatchCoarse-1, NPatchCoarse-1)
        coarseTStartIndex = util.convertpCoordinateToIndex(NPatchCoarse-1, iSubPatchCoarse)
        rCoarseLocalized = self._rCoarse[coarseTStartIndex + coarseTIndexMap]

        # a
        coarsetIndexMap = util.lowerLeftpIndexMap(NSubPatchFine-1, NPatchFine-1)
        coarsetStartIndex = util.convertpCoordinateToIndex(NPatchFine-1, iSubPatchFine)
        aLocalized = a[coarsetStartIndex + coarsetIndexMap]

        localizedCoefficient = coefficientCoarseFactor(NSubPatchCoarse, NCoarseElement, None, rCoarseLocalized)
        if not hasattr(self, '_aFine'):
            localizedCoefficient._aBase = aLocalized
        else:
            localizedCoefficient._aFine = aLocalized
            del localizedCoefficient._aBase

        return localizedCoefficient
示例#7
0
def computeElementFaceFlux(NWorldCoarse, NPatchCoarse, NCoarseElement, aPatch, uPatch):
    '''Per element, compute face normal flux integrals.'''
    NPatchFine = NPatchCoarse*NCoarseElement
    NWorldFine = NWorldCoarse*NCoarseElement
    
    NtCoarse = np.prod(NPatchCoarse)
    d = np.size(NPatchCoarse)

    fluxTF = np.zeros([NtCoarse, 2*d])

    TFinepIndexMap = util.lowerLeftpIndexMap(NCoarseElement, NPatchFine)
    TFinepStartIndices = util.pIndexMap(NPatchCoarse-1, NPatchFine, NCoarseElement)

    TFinetIndexMap = util.lowerLeftpIndexMap(NCoarseElement-1, NPatchFine-1)
    TFinetStartIndices = util.pIndexMap(NPatchCoarse-1, NPatchFine-1, NCoarseElement)

    faces = np.arange(2*d)

    CLocGetter = fem.localBoundaryNormalDerivativeMatrixGetter(NWorldFine)
    boundaryMap = np.zeros([d, 2], dtype='bool')
    for TInd in np.arange(NtCoarse):
        aElement = aPatch[TFinetStartIndices[TInd] + TFinetIndexMap]
        uElement = uPatch[TFinepStartIndices[TInd] + TFinepIndexMap]
        for F in faces:
            boundaryMap[:] = False
            boundaryMap.flat[F] = True
            AFace = fem.assemblePatchBoundaryMatrix(NCoarseElement, CLocGetter, aElement, boundaryMap)
            fluxFace = -np.sum(AFace*uElement)
            fluxTF[TInd,F] = fluxFace

    return fluxTF
示例#8
0
    def computeCorrection(self, ARhsFull=None, MRhsFull=None):
        assert (self.ecList is not None)
        assert (self.coefficient is not None)

        world = self.world
        NCoarseElement = world.NCoarseElement
        NWorldCoarse = world.NWorldCoarse
        NWorldFine = NWorldCoarse * NCoarseElement

        NpFine = np.prod(NWorldFine + 1)

        coefficient = self.coefficient
        IPatchGenerator = self.IPatchGenerator

        localBasis = world.localBasis

        TpIndexMap = util.lowerLeftpIndexMap(NCoarseElement, NWorldFine)
        TpStartIndices = util.pIndexMap(NWorldCoarse - 1, NWorldFine,
                                        NCoarseElement)

        uFine = np.zeros(NpFine)

        NtCoarse = np.prod(world.NWorldCoarse)
        for TInd in range(NtCoarse):
            if self.printLevel > 0:
                print str(TInd) + ' / ' + str(NtCoarse)

            ecT = self.ecList[TInd]

            coefficientPatch = coefficient.localize(ecT.iPatchWorldCoarse,
                                                    ecT.NPatchCoarse)
            IPatch = IPatchGenerator(ecT.iPatchWorldCoarse, ecT.NPatchCoarse)

            if ARhsFull is not None:
                ARhsList = [ARhsFull[TpStartIndices[TInd] + TpIndexMap]]
            else:
                ARhsList = None

            if MRhsFull is not None:
                MRhsList = [MRhsFull[TpStartIndices[TInd] + TpIndexMap]]
            else:
                MRhsList = None

            correctorT = ecT.computeElementCorrector(coefficientPatch, IPatch,
                                                     ARhsList, MRhsList)[0]

            NPatchFine = ecT.NPatchCoarse * NCoarseElement
            iPatchWorldFine = ecT.iPatchWorldCoarse * NCoarseElement
            patchpIndexMap = util.lowerLeftpIndexMap(NPatchFine, NWorldFine)
            patchpStartIndex = util.convertpCoordinateToIndex(
                NWorldFine, iPatchWorldFine)

            uFine[patchpStartIndex + patchpIndexMap] += correctorT

        return uFine
示例#9
0
    def assembleBasisCorrectors(self):
        if self.basisCorrectors is not None:
            return self.basisCorrectors

        assert (self.ecList is not None)

        world = self.world
        NWorldCoarse = world.NWorldCoarse
        NCoarseElement = world.NCoarseElement
        NWorldFine = NWorldCoarse * NCoarseElement

        NtCoarse = np.prod(NWorldCoarse)
        NpCoarse = np.prod(NWorldCoarse + 1)
        NpFine = np.prod(NWorldFine + 1)

        TpIndexMap = util.lowerLeftpIndexMap(np.ones_like(NWorldCoarse),
                                             NWorldCoarse)
        TpStartIndices = util.lowerLeftpIndexMap(NWorldCoarse - 1,
                                                 NWorldCoarse)

        cols = []
        rows = []
        data = []
        ecList = self.ecList
        for TInd in range(NtCoarse):
            ecT = ecList[TInd]
            assert (ecT is not None)
            assert (hasattr(ecT, 'fsi'))

            NPatchFine = ecT.NPatchCoarse * NCoarseElement
            iPatchWorldFine = ecT.iPatchWorldCoarse * NCoarseElement

            patchpIndexMap = util.lowerLeftpIndexMap(NPatchFine, NWorldFine)
            patchpStartIndex = util.convertpCoordinateToIndex(
                NWorldFine, iPatchWorldFine)

            colsT = TpStartIndices[TInd] + TpIndexMap
            rowsT = patchpStartIndex + patchpIndexMap
            dataT = np.hstack(ecT.fsi.correctorsList)

            cols.extend(np.repeat(colsT, np.size(rowsT)))
            rows.extend(np.tile(rowsT, np.size(colsT)))
            data.extend(dataT)

        basisCorrectors = sparse.csc_matrix((data, (rows, cols)),
                                            shape=(NpFine, NpCoarse))

        self.basisCorrectors = basisCorrectors
        return basisCorrectors
示例#10
0
    def assembleMsStiffnessMatrix(self):
        if self.Kms is not None:
            return self.Kms

        assert (self.ecList is not None)

        world = self.world
        NWorldCoarse = world.NWorldCoarse

        NtCoarse = np.prod(world.NWorldCoarse)
        NpCoarse = np.prod(world.NWorldCoarse + 1)

        TpIndexMap = util.lowerLeftpIndexMap(np.ones_like(NWorldCoarse),
                                             NWorldCoarse)
        TpStartIndices = util.lowerLeftpIndexMap(NWorldCoarse - 1,
                                                 NWorldCoarse)

        cols = []
        rows = []
        data = []
        ecList = self.ecList
        for TInd in range(NtCoarse):
            ecT = ecList[TInd]
            assert (ecT is not None)

            NPatchCoarse = ecT.NPatchCoarse

            patchpIndexMap = util.lowerLeftpIndexMap(NPatchCoarse,
                                                     NWorldCoarse)
            patchpStartIndex = util.convertpCoordinateToIndex(
                NWorldCoarse, ecT.iPatchWorldCoarse)

            colsT = TpStartIndices[TInd] + TpIndexMap
            rowsT = patchpStartIndex + patchpIndexMap
            dataT = ecT.csi.Kmsij.flatten()

            cols.extend(np.tile(colsT, np.size(rowsT)))
            rows.extend(np.repeat(rowsT, np.size(colsT)))
            data.extend(dataT)

        Kms = sparse.csc_matrix((data, (rows, cols)),
                                shape=(NpCoarse, NpCoarse))

        self.Kms = Kms
        return Kms
示例#11
0
def localToPatchSparsityPattern(NPatch, NSubPatch=None):
    if NSubPatch is None:
        NSubPatch = NPatch

    d = np.size(NPatch)

    loc2Patch = util.lowerLeftpIndexMap(np.ones(d, 'int64'), NPatch)
    pInd = util.lowerLeftpIndexMap(NSubPatch - 1, NPatch)

    loc2PatchRep = np.repeat(loc2Patch, 2**d)
    loc2PatchTile = np.tile(loc2Patch, 2**d)
    indexMatrixRows = np.add.outer(pInd, loc2PatchRep)
    indexMatrixCols = np.add.outer(pInd, loc2PatchTile)

    rows = indexMatrixRows.flatten()
    cols = indexMatrixCols.flatten()

    return rows, cols
示例#12
0
    def computeErrorIndicatorFine(self, coefficientNew):
        assert (hasattr(self, 'fsi'))

        NPatchCoarse = self.NPatchCoarse
        world = self.world
        NCoarseElement = world.NCoarseElement
        NPatchFine = NPatchCoarse * NCoarseElement

        ALocFine = world.ALocFine
        P = world.localBasis

        a = coefficientNew.aFine
        aTilde = self.fsi.coefficient.aFine

        TFinetIndexMap = util.lowerLeftpIndexMap(NCoarseElement - 1,
                                                 NPatchFine - 1)
        iElementPatchFine = self.iElementPatchCoarse * NCoarseElement
        TFinetStartIndex = util.convertpCoordinateToIndex(
            NPatchFine - 1, iElementPatchFine)

        b = ((aTilde - a)**2) / a
        bT = b[TFinetStartIndex + TFinetIndexMap]
        PatchNorm = fem.assemblePatchMatrix(NPatchFine, ALocFine, b)
        TNorm = fem.assemblePatchMatrix(NCoarseElement, ALocFine, bT)

        BNorm = fem.assemblePatchMatrix(NCoarseElement, ALocFine,
                                        a[TFinetStartIndex + TFinetIndexMap])

        TFinepIndexMap = util.lowerLeftpIndexMap(NCoarseElement, NPatchFine)
        TFinepStartIndex = util.convertpCoordinateToIndex(
            NPatchFine, iElementPatchFine)

        Q = np.column_stack(self.fsi.correctorsList)
        QT = Q[TFinepStartIndex + TFinepIndexMap, :]

        A = np.dot((P - QT).T, TNorm * (P - QT)) + np.dot(Q.T, PatchNorm * Q)
        B = np.dot(P.T, BNorm * P)

        eigenvalues = scipy.linalg.eigvals(A[:-1, :-1], B[:-1, :-1])
        epsilonTSquare = np.max(np.real(eigenvalues))

        return np.sqrt(epsilonTSquare)
示例#13
0
def assemblePatchBoundaryMatrix(NPatch,
                                CLocGetter,
                                aPatch=None,
                                boundaryMap=None):
    # Integral over part of boundary can be implemented by adding an
    # input "chi" as an indicator function to be callable with edge
    # midpoints as inputs.
    d = np.size(NPatch)
    Np = np.prod(NPatch + 1)
    Nt = np.prod(NPatch)

    if aPatch is None:
        aPatch = np.ones(Nt)

    if boundaryMap is None:
        boundaryMap = np.ones([d, 2], dtype='bool')

    rows = []
    cols = []
    values = []
    # Loop through each dimension
    for k in range(d):
        NEdge = NPatch.copy()
        NEdge[k] = 1

        edgeElementInd0 = util.lowerLeftpIndexMap(NEdge - 1, NPatch - 1)
        rows0, cols0 = localToPatchSparsityPattern(NPatch, NSubPatch=NEdge)

        for neg in [False, True]:
            if boundaryMap[k][int(neg)]:
                CLoc = CLocGetter(k, neg)
                if not neg:
                    edgeElementIndneg = edgeElementInd0
                    rowsneg = rows0
                    colsneg = cols0
                else:
                    pointIndexDisplacement = int(
                        np.prod(NPatch[:k] + 1) * (NPatch[k] - 1))
                    elementIndexDisplacement = int(
                        np.prod(NPatch[:k]) * (NPatch[k] - 1))
                    edgeElementIndneg = edgeElementInd0 + elementIndexDisplacement
                    rowsneg = rows0 + pointIndexDisplacement
                    colsneg = cols0 + pointIndexDisplacement

                valuesneg = np.kron(aPatch[edgeElementIndneg], CLoc.flatten())

                rows = np.hstack([rows, rowsneg])
                cols = np.hstack([cols, colsneg])
                values = np.hstack([values, valuesneg])

    APatch = sparse.csc_matrix((values, (rows, cols)), shape=(Np, Np))
    APatch.eliminate_zeros()

    return APatch
示例#14
0
    def localize(self, iSubPatchCoarse, NSubPatchCoarse):
        NPatchCoarse = self.NPatchCoarse
        NCoarseElement = self.NCoarseElement
        NPatchFine = NPatchCoarse*NCoarseElement
        NSubPatchFine = NSubPatchCoarse*NCoarseElement
        iSubPatchFine = iSubPatchCoarse*NCoarseElement

        # a
        coarsetIndexMap = util.lowerLeftpIndexMap(NSubPatchFine-1, NPatchFine-1)
        coarsetStartIndex = util.convertpCoordinateToIndex(NPatchFine-1, iSubPatchFine)
        aFineLocalized = self._aFine[coarsetStartIndex + coarsetIndexMap]

        localizedCoefficient = coefficientFine(NSubPatchCoarse, NCoarseElement, aFineLocalized)
        return localizedCoefficient
示例#15
0
def faceElementPointIndices(NPatchCoarse, NCoarseElement, k, boundary):
    '''Return indices of points in fine elements adjacent to face (k, boundary) for all coarse triangles

    Return type shape: (NtCoarse, Number of elements of face, 2**d)
    '''
    NPatchFine = NPatchCoarse*NCoarseElement
    
    tIndices = faceElementIndices(NPatchCoarse, NCoarseElement, k, boundary)
    tpIndexMap = util.lowerLeftpIndexMap(NPatchFine-1, NPatchFine)
    elementpIndices = util.elementpIndexMap(NPatchFine)

    pIndices = np.add.outer(tpIndexMap[tIndices], elementpIndices)
    
    return pIndices
示例#16
0
def computeJumps(NWorldCoarse, quantityT):
    d = np.size(NWorldCoarse)
    b = util.linearpIndexBasis(NWorldCoarse-1)

    jumpTF = np.tile(quantityT[...,None], [1, 2*d])
    for k in range(d):
        NWorldBase = np.array(NWorldCoarse)
        NWorldBase[k] -= 1
        TIndBase = util.lowerLeftpIndexMap(NWorldBase-1, NWorldCoarse-1)
        jump = quantityT[TIndBase] - quantityT[TIndBase + b[k]]
        jumpTF[TIndBase, 2*k + 1] = jump
        jumpTF[TIndBase + b[k], 2*k] = -jump

    return jumpTF
示例#17
0
    def precompute(self):
        if hasattr(self, '_aFine'):
            return
        
        NPatchCoarse = self.NPatchCoarse
        NCoarseElement = self.NCoarseElement
        NPatchFine = NPatchCoarse*NCoarseElement
        
        coarsetStartIndices = util.pIndexMap(NPatchCoarse-1, NPatchFine-1, NCoarseElement)
        coarsetIndexMap = util.lowerLeftpIndexMap(NCoarseElement-1, NPatchFine-1)

        coarsetIndexTensor = np.add.outer(coarsetIndexMap, coarsetStartIndices)
        self._aFine = np.array(self._aBase)
        self._aFine[coarsetIndexTensor] *= self._rCoarse
        del self._aBase
示例#18
0
def faceElementIndices(NPatchCoarse, NCoarseElement, k, boundary):
    '''Return indices of fine elements adjacent to face (k, boundary) for all coarse triangles

    Return type shape: (NtCoarse, Number of elements of face)
    '''
    NPatchFine = NPatchCoarse*NCoarseElement

    NFace = np.array(NCoarseElement)
    NFace[k] = 1
    
    tPatchBasis = util.linearpIndexBasis(NPatchFine-1)
    tStepToFace = boundary*tPatchBasis[k]*(NCoarseElement[k]-1)

    tIndexMap = tStepToFace + util.lowerLeftpIndexMap(NFace-1, NPatchFine-1)
    tStartIndices = util.pIndexMap(NPatchCoarse-1, NPatchFine-1, NCoarseElement)
    tIndices = np.add.outer(tStartIndices, tIndexMap)
    
    return tIndices
示例#19
0
def computeAverageFaceFlux(NWorldCoarse, fluxTF):
    # Note  I: these velocities are not conservative and do not fulfill
    #          strongly with Neumann boundary conditions
    #
    # Note II: the velocities are integrated and hence already scaled with face
    #          area
    d = np.size(NWorldCoarse)
    b = util.linearpIndexBasis(NWorldCoarse-1)

    avgFluxTF = np.array(fluxTF)
    for k in range(d):
        NWorldBase = np.array(NWorldCoarse-1)
        NWorldBase[k] -= 1
        TIndBase = util.lowerLeftpIndexMap(NWorldBase, NWorldCoarse-1)
        avg = 0.5*(fluxTF[TIndBase, 2*k + 1] - fluxTF[TIndBase + b[k], 2*k])
        avgFluxTF[TIndBase, 2*k + 1] = avg
        avgFluxTF[TIndBase + b[k], 2*k] = -avg

    return avgFluxTF
示例#20
0
def uncoupledL2ProjectionCoarseElementMatrix(NCoarseElement):
    d = np.size(NCoarseElement)

    NpFine = np.prod(NCoarseElement + 1)

    # First compute full element P'*M
    MLoc = fem.localMassMatrix(NCoarseElement)
    MElement = fem.assemblePatchMatrix(NCoarseElement, MLoc)
    Phi = fem.localBasis(NCoarseElement)

    PhiTM = Phi.T * MElement

    # Prepare indices to go from local to element and find all corner
    # element indices
    dOnes = np.ones_like(NCoarseElement, dtype='int64')
    loc2ElementIndexMap = util.lowerLeftpIndexMap(dOnes, NCoarseElement)
    cornerElementIndices = util.pIndexMap(dOnes, NCoarseElement,
                                          NCoarseElement - 1)

    # Compute P'*MCorner for all corners
    PhiTMCornersList = []
    for i in range(2**d):
        cornerInd = cornerElementIndices[i] + loc2ElementIndexMap
        PhiTMCorner = 0 * PhiTM
        PhiTMCorner[:, cornerInd] = np.dot(Phi.T[:, cornerInd], MLoc)
        PhiTMCornersList.append(PhiTMCorner)

    PhiTMAllCorners = reduce(np.add, PhiTMCornersList)

    # For each corner, compute
    #    P'*M - P'*MAllCorners + P'*MCorner
    IDense = np.zeros((2**d, NpFine))
    for i in range(2**d):
        PhiTMCorner = PhiTMCornersList[i]
        PhiTMi = PhiTM - PhiTMAllCorners + PhiTMCorner
        PhiTMiPhi = np.dot(PhiTMi, Phi)

        IiDense = np.dot(np.linalg.inv(PhiTMiPhi), PhiTMi)
        IDense[i, :] = IiDense[i, :]

    I = sparse.coo_matrix(IDense)

    return I
示例#21
0
def computeElementFaceFluxFromSigma(NWorldCoarse, sigmaFluxT):
    d = np.size(NWorldCoarse)

    NtCoarse = np.prod(NWorldCoarse)
    fluxTF = np.zeros([NtCoarse, 2*d])

    pBasis = util.linearpIndexBasis(np.ones_like(NWorldCoarse))
    for k in range(d):
        N = np.ones_like(NWorldCoarse)
        N[k] = 0
        bottomp = util.lowerLeftpIndexMap(N, np.ones_like(N))
        topp = bottomp + pBasis[k]

        NFace = np.array(NWorldCoarse)
        NFace[k] = 1
        faceArea = np.prod(1./NFace)
        
        fluxTF[:,2*k] = faceArea*np.mean(-sigmaFluxT[:,bottomp], axis=1)
        fluxTF[:,2*k + 1] = faceArea*np.mean(-sigmaFluxT[:,topp], axis=1)

    return fluxTF
示例#22
0
    def computeErrorIndicatorFineWithLagging(self, a, aTilde):
        assert (hasattr(self, 'csi'))

        world = self.world
        NPatchCoarse = self.NPatchCoarse
        NCoarseElement = world.NCoarseElement
        NPatchFine = NPatchCoarse * NCoarseElement
        iElementPatchCoarse = self.iElementPatchCoarse

        elementCoarseIndex = util.convertpCoordinateToIndex(
            NPatchCoarse - 1, iElementPatchCoarse)

        TPrimeFinetStartIndices = util.pIndexMap(NPatchCoarse - 1,
                                                 NPatchFine - 1,
                                                 NCoarseElement)
        TPrimeFinetIndexMap = util.lowerLeftpIndexMap(NCoarseElement - 1,
                                                      NPatchFine - 1)

        muTPrime = self.csi.muTPrime

        TPrimeIndices = np.add.outer(TPrimeFinetStartIndices,
                                     TPrimeFinetIndexMap)
        aTPrime = a[TPrimeIndices]
        aTildeTPrime = aTilde[TPrimeIndices]

        deltaMaxNormTPrime = np.max(np.abs(
            (aTPrime - aTildeTPrime) / np.sqrt(aTPrime * aTildeTPrime)),
                                    axis=1)
        theOtherUnnamedFactorTPrime = np.max(
            np.abs(aTPrime[elementCoarseIndex] /
                   aTildeTPrime[elementCoarseIndex]))

        epsilonTSquare = theOtherUnnamedFactorTPrime * \
                         np.sum((deltaMaxNormTPrime**2)*muTPrime)

        return np.sqrt(epsilonTSquare)
示例#23
0
    def computeCoarseQuantities(self):
        '''Compute the coarse quantities K and L for this element corrector

        Compute the tensors (T is given by the class instance):

        KTij   = (A \nabla lambda_j, \nabla lambda_i)_{T}
        KmsTij = (A \nabla (lambda_j - Q_T lambda_j), \nabla lambda_i)_{U_k(T)}
        muTT'  = max_{w_H} || A \nabla (\chi_T - Q_T) w_H ||^2_T' / || A \nabla w_H ||^2_T

        and store them in the self.csi object. See
        notes/coarse_quantities*.pdf for a description.

        Auxiliary quantities are computed, but not saved, e.g.

        LTT'ij = (A \nabla (chi_T - Q_T)lambda_j, \nabla (chi_T - Q_T) lambda_j)_{T'}
        '''
        assert (hasattr(self, 'fsi'))

        world = self.world
        NCoarseElement = world.NCoarseElement
        NPatchCoarse = self.NPatchCoarse
        NPatchFine = NPatchCoarse * NCoarseElement

        NTPrime = np.prod(NPatchCoarse)
        NpPatchCoarse = np.prod(NPatchCoarse + 1)

        d = np.size(NPatchCoarse)

        correctorsList = self.fsi.correctorsList
        aPatch = self.fsi.coefficient.aFine

        ALocFine = world.ALocFine
        localBasis = world.localBasis

        TPrimeCoarsepStartIndices = util.lowerLeftpIndexMap(
            NPatchCoarse - 1, NPatchCoarse)
        TPrimeCoarsepIndexMap = util.lowerLeftpIndexMap(
            np.ones_like(NPatchCoarse), NPatchCoarse)

        TPrimeFinetStartIndices = util.pIndexMap(NPatchCoarse - 1,
                                                 NPatchFine - 1,
                                                 NCoarseElement)
        TPrimeFinetIndexMap = util.lowerLeftpIndexMap(NCoarseElement - 1,
                                                      NPatchFine - 1)

        TPrimeFinepStartIndices = util.pIndexMap(NPatchCoarse - 1, NPatchFine,
                                                 NCoarseElement)
        TPrimeFinepIndexMap = util.lowerLeftpIndexMap(NCoarseElement,
                                                      NPatchFine)

        TInd = util.convertpCoordinateToIndex(NPatchCoarse - 1,
                                              self.iElementPatchCoarse)

        QPatch = np.column_stack(correctorsList)

        # This loop can probably be done faster than this. If a bottle-neck, fix!
        Kmsij = np.zeros((NpPatchCoarse, 2**d))
        LTPrimeij = np.zeros((NTPrime, 2**d, 2**d))
        for (TPrimeInd,
             TPrimeCoarsepStartIndex,
             TPrimeFinetStartIndex,
             TPrimeFinepStartIndex) \
             in zip(np.arange(NTPrime),
                    TPrimeCoarsepStartIndices,
                    TPrimeFinetStartIndices,
                    TPrimeFinepStartIndices):

            aTPrime = aPatch[TPrimeFinetStartIndex + TPrimeFinetIndexMap]
            KTPrime = fem.assemblePatchMatrix(NCoarseElement, ALocFine,
                                              aTPrime)
            P = localBasis
            Q = QPatch[TPrimeFinepStartIndex + TPrimeFinepIndexMap, :]
            BTPrimeij = np.dot(P.T, KTPrime * Q)
            CTPrimeij = np.dot(Q.T, KTPrime * Q)
            sigma = TPrimeCoarsepStartIndex + TPrimeCoarsepIndexMap
            if TPrimeInd == TInd:
                Kij = np.dot(P.T, KTPrime * P)
                LTPrimeij[TPrimeInd] = CTPrimeij \
                                       - BTPrimeij \
                                       - BTPrimeij.T \
                                       + Kij
                Kmsij[sigma, :] += Kij - BTPrimeij

            else:
                LTPrimeij[TPrimeInd] = CTPrimeij
                Kmsij[sigma, :] += -BTPrimeij

        muTPrime = np.zeros(NTPrime)
        for TPrimeInd in np.arange(NTPrime):
            # Solve eigenvalue problem LTPrimeij x = mu_TPrime Mij x
            eigenvalues = scipy.linalg.eigvals(LTPrimeij[TPrimeInd][:-1, :-1],
                                               Kij[:-1, :-1])
            muTPrime[TPrimeInd] = np.max(np.real(eigenvalues))

        # Compute coarse element face flux for basis and Q (not yet implemented for R)
        correctorFluxTF = transport.computeHarmonicMeanFaceFlux(
            world.NWorldCoarse, NPatchCoarse, NCoarseElement, aPatch, QPatch)

        # Need to compute over at least one fine element over the
        # boundary of the main element to make the harmonic average
        # right.  Note: We don't do this for correctorFluxTF, beause
        # we do not have access to a outside the patch...
        localBasisExtended = np.zeros_like(QPatch)
        localBasisExtended[TPrimeFinepStartIndices[TInd] +
                           TPrimeFinepIndexMap, :] = localBasis
        basisFluxTF = transport.computeHarmonicMeanFaceFlux(
            world.NWorldCoarse, NPatchCoarse, NCoarseElement, aPatch,
            localBasisExtended)[:, TInd, :]

        if isinstance(self.fsi.coefficient,
                      coef.coefficientCoarseFactorAbstract):
            rCoarse = self.fsi.coefficient.rCoarse
        else:
            rCoarse = None
        self.csi = CoarseScaleInformation(Kij, Kmsij, muTPrime,
                                          correctorFluxTF, basisFluxTF,
                                          rCoarse)
示例#24
0
def assembleFaceConnectivityMatrix(NPatch, FLoc, boundaryMap=None):
    Nt = np.prod(NPatch)

    d = np.size(NPatch)

    if boundaryMap is None:
        boundaryMap = np.zeros([d, 2], dtype='bool')

    rowsList = []
    colsList = []
    valuesList = []

    tBasis = util.linearpIndexBasis(NPatch - 1)
    for k in range(d):
        for boundary in [0, 1]:
            NPatchBase = np.array(NPatch)
            NPatchBase[k] -= 1

            TIndInterior = (1 -
                            boundary) * tBasis[k] + util.lowerLeftpIndexMap(
                                NPatchBase - 1, NPatch - 1)
            nT = np.size(TIndInterior)

            FLocRepeated = np.repeat(FLoc[2 * k + boundary], nT)

            # Add diagonal elements
            rowsList.append(TIndInterior)
            colsList.append(TIndInterior)
            valuesList.append(FLocRepeated)

            # Add off-diagonal elements
            rowsList.append(TIndInterior + (2 * boundary - 1) * tBasis[k])
            colsList.append(TIndInterior)
            valuesList.append(-FLocRepeated / 2.)

            rowsList.append(TIndInterior)
            colsList.append(TIndInterior + (2 * boundary - 1) * tBasis[k])
            valuesList.append(-FLocRepeated / 2.)

            # Add boundary diagonal elements, if applies
            if boundaryMap[k, boundary]:
                NPatchBottom = np.array(NPatch)
                NPatchBottom[k] = 1

                TIndBoundary = (boundary)*tBasis[k]*(NPatch[k]-1) + \
                               util.lowerLeftpIndexMap(NPatchBottom-1, NPatch-1)
                nT = np.size(TIndBoundary)

                FLocRepeatedBoundary = np.repeat(FLoc[2 * k + boundary], nT)

                rowsList.append(TIndBoundary)
                colsList.append(TIndBoundary)
                valuesList.append(FLocRepeatedBoundary)

    # Concatenate lists
    rows = np.hstack(rowsList)
    cols = np.hstack(colsList)
    values = np.hstack(valuesList)

    # Create sparse matrix
    FC = sparse.csc_matrix((values, (rows, cols)), shape=(Nt, Nt))

    return FC
示例#25
0
 def applyNeumannBoundaryConditionsOneSide(fluxTF, k, boundary):
     stepToFace = (boundary)*tBasis[k]*(NWorldCoarse[k]-1)
     NWorldBottom = np.array(NWorldCoarse)
     NWorldBottom[k] = 1
     TIndBoundary = stepToFace + util.lowerLeftpIndexMap(NWorldBottom-1, NWorldCoarse-1)
     fluxTF[TIndBoundary, 2*k+boundary] = 0