Example #1
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
Example #2
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
Example #3
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
Example #4
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
Example #5
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
Example #6
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
Example #7
0
def assembleHierarchicalBasisMatrix(NPatchCoarse, NCoarseElement):
    NPatchFine = NPatchCoarse * NCoarseElement
    NpFine = np.prod(NPatchFine + 1)

    # Use simplest possible hierarchy, divide by two in all dimensions
    NLevelElement = NCoarseElement.copy()
    while np.all(np.mod(NLevelElement, 2) == 0):
        NLevelElement /= 2

    assert np.all(NLevelElement == 1)

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

    # Loop over levels
    while np.all(NLevelElement <= NCoarseElement):
        # Compute level basis functions on fine mesh
        NCoarseLevel = NCoarseElement / NLevelElement
        NPatchLevel = NPatchCoarse * NCoarseLevel
        PLevel = assembleProlongationMatrix(NPatchLevel, NLevelElement)
        PLevel = PLevel.tocoo()

        # Rows are ok. Columns must be sparsened to fine mesh.
        colsMap = util.pIndexMap(NPatchLevel, NPatchFine, NLevelElement)
        rowsList.append(PLevel.row)
        colsList.append(colsMap[PLevel.col])
        valuesList.append(PLevel.data)

        NLevelElement = 2 * NLevelElement

    # Concatenate lists (backwards so that we can ignore duplicates)
    rows = np.hstack(rowsList[::-1])
    cols = np.hstack(colsList[::-1])
    values = np.hstack(valuesList[::-1])

    # Ignore duplicates
    rows, cols, values = util.ignoreDuplicates(rows, cols, values)

    # Create sparse matrix
    PHier = sparse.csc_matrix((values, (rows, cols)), shape=(NpFine, NpFine))
    PHier.eliminate_zeros()

    return PHier
Example #8
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
Example #9
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)
Example #10
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)