Пример #1
0
def solveFine(world, aFine, MbFine, AbFine, boundaryConditions):
    NWorldCoarse = world.NWorldCoarse
    NWorldFine = world.NWorldCoarse * world.NCoarseElement
    NpFine = np.prod(NWorldFine + 1)

    if MbFine is None:
        MbFine = np.zeros(NpFine)

    if AbFine is None:
        AbFine = np.zeros(NpFine)

    boundaryMap = boundaryConditions == 0
    fixedFine = util.boundarypIndexMap(NWorldFine, boundaryMap=boundaryMap)
    freeFine = np.setdiff1d(np.arange(NpFine), fixedFine)
    AFine = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, aFine)
    MFine = fem.assemblePatchMatrix(NWorldFine, world.MLocFine)

    bFine = MFine * MbFine + AFine * AbFine

    AFineFree = AFine[freeFine][:, freeFine]
    bFineFree = bFine[freeFine]

    uFineFree = linalg.linSolve(AFineFree, bFineFree)
    uFineFull = np.zeros(NpFine)
    uFineFull[freeFine] = uFineFree
    uFineFull = uFineFull

    return uFineFull, AFine, MFine
Пример #2
0
    def solveTrueCoefficient(self, f, g, boundaryConditions, aFine):
        assert (f is None)

        world = self.world
        NWorldCoarse = world.NWorldCoarse
        NCoarseElement = world.NCoarseElement
        NWorldFine = NWorldCoarse * NCoarseElement
        NpCoarse = np.prod(NWorldCoarse + 1)

        basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement)
        basisCorrectors = self.assembleBasisCorrectors()
        modifiedBasis = basis - basisCorrectors

        AFine = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, aFine)

        KmsFull = basis.T * (AFine * modifiedBasis)

        fixed = util.boundarypIndexMap(NWorldCoarse, boundaryConditions == 0)
        free = np.setdiff1d(np.arange(NpCoarse), fixed)
        bFull = KmsFull * g

        KmsFree = KmsFull[free][:, free]
        bFree = bFull[free]

        uFree = sparse.linalg.spsolve(KmsFree, bFree)

        uFull = np.zeros(NpCoarse)
        uFull[free] = uFree

        return uFull, uFree, modifiedBasis
Пример #3
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)
Пример #4
0
def solveCoarse(world, aFine, MbFine, AbFine, boundaryConditions):
    NWorldCoarse = world.NWorldCoarse
    NWorldFine = world.NWorldCoarse * world.NCoarseElement
    NCoarseElement = world.NCoarseElement

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

    if MbFine is None:
        MbFine = np.zeros(NpFine)

    if AbFine is None:
        AbFine = np.zeros(NpFine)

    boundaryMap = boundaryConditions == 0
    fixedCoarse = util.boundarypIndexMap(NWorldCoarse, boundaryMap=boundaryMap)
    freeCoarse = np.setdiff1d(np.arange(NpCoarse), fixedCoarse)

    AFine = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, aFine)
    MFine = fem.assemblePatchMatrix(NWorldFine, world.MLocFine)

    bFine = MFine * MbFine + AFine * AbFine

    basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement)
    bCoarse = basis.T * bFine
    ACoarse = basis.T * (AFine * basis)

    ACoarseFree = ACoarse[freeCoarse][:, freeCoarse]
    bCoarseFree = bCoarse[freeCoarse]

    uCoarseFree = linalg.linSolve(ACoarseFree, bCoarseFree)
    uCoarseFull = np.zeros(NpCoarse)
    uCoarseFull[freeCoarse] = uCoarseFree
    uCoarseFull = uCoarseFull

    uFineFull = basis * uCoarseFull

    return uCoarseFull, uFineFull
Пример #5
0
def L2ProjectionCoarseElementMatrix(NCoarseElement):
    NpFine = np.prod(NCoarseElement + 1)
    NpCoarse = 2**np.size(NCoarseElement)

    MLoc = fem.localMassMatrix(NCoarseElement)
    MElement = fem.assemblePatchMatrix(NCoarseElement, MLoc)
    Phi = fem.localBasis(NCoarseElement)

    PhiTM = Phi.T * MElement
    PhiTMPhi = np.dot(PhiTM, Phi)

    IDense = np.dot(np.linalg.inv(PhiTMPhi), PhiTM)
    I = sparse.coo_matrix(IDense)
    return I
Пример #6
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
Пример #7
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)
Пример #8
0
    def computeElementCorrector(self,
                                coefficientPatch,
                                IPatch,
                                ARhsList=None,
                                MRhsList=None):
        '''Compute the fine correctors over the patch.

        Compute the correctors

        (A \nabla Q_T_j, \nabla vf)_{U_K(T)} = (A \nabla ARhs_j, \nabla vf)_{T} + (MRhs_j, vf)_{T}
        '''

        assert (ARhsList is not None or MRhsList is not None)
        numRhs = None

        if ARhsList is not None:
            assert (numRhs is None or numRhs == len(ARhsList))
            numRhs = len(ARhsList)

        if MRhsList is not None:
            assert (numRhs is None or numRhs == len(MRhsList))
            numRhs = len(MRhsList)

        world = self.world
        NCoarseElement = world.NCoarseElement
        NPatchCoarse = self.NPatchCoarse
        d = np.size(NCoarseElement)

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

        aPatch = coefficientPatch.aFine

        assert (np.size(aPatch) == NtFine)

        ALocFine = world.ALocFine
        MLocFine = world.MLocFine

        iElementPatchCoarse = self.iElementPatchCoarse
        elementFinetIndexMap = util.extractElementFine(NPatchCoarse,
                                                       NCoarseElement,
                                                       iElementPatchCoarse,
                                                       extractElements=True)
        elementFinepIndexMap = util.extractElementFine(NPatchCoarse,
                                                       NCoarseElement,
                                                       iElementPatchCoarse,
                                                       extractElements=False)

        if ARhsList is not None:
            AElementFull = fem.assemblePatchMatrix(
                NCoarseElement, ALocFine, aPatch[elementFinetIndexMap])
        if MRhsList is not None:
            MElementFull = fem.assemblePatchMatrix(NCoarseElement, MLocFine)
        APatchFull = fem.assemblePatchMatrix(NPatchFine, ALocFine, aPatch)

        bPatchFullList = []
        for rhsIndex in range(numRhs):
            bPatchFull = np.zeros(NpFine)
            if ARhsList is not None:
                bPatchFull[
                    elementFinepIndexMap] += AElementFull * ARhsList[rhsIndex]
            if MRhsList is not None:
                bPatchFull[
                    elementFinepIndexMap] += MElementFull * MRhsList[rhsIndex]
            bPatchFullList.append(bPatchFull)

        correctorsList = ritzProjectionToFinePatchWithGivenSaddleSolver(
            world, self.iPatchWorldCoarse, NPatchCoarse, APatchFull,
            bPatchFullList, IPatch, self.saddleSolver)
        return correctorsList