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
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
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)
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
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
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
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)
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