def test_convertpCoordIndexToLinearIndex(self): N = np.array([100]) coord = np.array([44]) self.assertTrue(util.convertpCoordIndexToLinearIndex(N, coord) == 44) N = np.array([100, 200]) coord = np.array([44, 55]) self.assertTrue(util.convertpCoordIndexToLinearIndex(N, coord) == 44+55*101)
def assembleBasisCorrectors(world, patchT, basisCorrectorsListT, periodic=False): '''Compute the basis correctors given the elementwise basis correctors for each coarse element. Adapted from gridlod.pglod.assembleBasisCorrectors with newly added periodic functionality. In the periodic case, you are also allowed to hand over just a single basisCorrectorsList if these local correctors are the same for every element (e.g. for periodic coefficients). ''' 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 = [] for TInd in range(NtCoarse): if periodic and not (isinstance(basisCorrectorsListT, tuple)): # if only one CorrectorsList is given in periodic case basisCorrectorsList = basisCorrectorsListT else: basisCorrectorsList = basisCorrectorsListT[TInd] patch = patchT[TInd] NPatchFine = patch.NPatchCoarse * NCoarseElement iPatchWorldFine = patch.iPatchWorldCoarse * NCoarseElement patchpIndexMap = util.lowerLeftpIndexMap(NPatchFine, NWorldFine) patchpStartIndex = util.convertpCoordIndexToLinearIndex(NWorldFine, iPatchWorldFine) if periodic: rowsTpCoord = (iPatchWorldFine.T + util.convertpLinearIndexToCoordIndex(NWorldFine, patchpIndexMap).T) \ % NWorldFine rowsT = util.convertpCoordIndexToLinearIndex(NWorldFine, rowsTpCoord) colsTbase = TpStartIndices[TInd] + TpIndexMap colsTpCoord = util.convertpLinearIndexToCoordIndex(NWorldCoarse, colsTbase).T % NWorldCoarse colsT = util.convertpCoordIndexToLinearIndex(NWorldCoarse, colsTpCoord) else: colsT = TpStartIndices[TInd] + TpIndexMap rowsT = patchpStartIndex + patchpIndexMap dataT = np.hstack(basisCorrectorsList) 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)) return basisCorrectors
def assembleMsStiffnessMatrix(world, patchT, KmsijT, periodic=False): '''Compute the multiscale Petrov-Galerkin stiffness matrix given Kmsij for each coarse element. Adapted from gridlod.pglod.assembleMsStiffnessMatrix with newly added periodic functionality. In the periodic case, you are also allowed to hand over just a single Kmsij if this local matrix is the same for every element (e.g. for periodic coefficients). ''' 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 = [] for TInd in range(NtCoarse): if periodic and not ( isinstance(KmsijT, tuple) or isinstance(KmsijT, list)): # if only one matrix is given in periodic case Kmsij = KmsijT else: Kmsij = KmsijT[TInd] patch = patchT[TInd] NPatchCoarse = patch.NPatchCoarse patchpIndexMap = util.lowerLeftpIndexMap(NPatchCoarse, NWorldCoarse) patchpStartIndex = util.convertpCoordIndexToLinearIndex(NWorldCoarse, patch.iPatchWorldCoarse) if periodic: rowsTpCoord = (patch.iPatchWorldCoarse.T + util.convertpLinearIndexToCoordIndex(NWorldCoarse, patchpIndexMap).T) \ % NWorldCoarse rowsT = util.convertpCoordIndexToLinearIndex(NWorldCoarse, rowsTpCoord) colsTbase = TpStartIndices[TInd] + TpIndexMap colsTpCoord = util.convertpLinearIndexToCoordIndex(NWorldCoarse, colsTbase).T % NWorldCoarse colsT = util.convertpCoordIndexToLinearIndex(NWorldCoarse, colsTpCoord) else: rowsT = patchpStartIndex + patchpIndexMap colsT = TpStartIndices[TInd] + TpIndexMap dataT = 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)) return Kms
def test_tCoordinates(self): NWorld = np.array([5]) xt = util.tCoordinates(NWorld) self.assertTrue(np.isclose(np.max(np.abs(xt.T - np.array([1., 3., 5., 7., 9.])/10)), 0)) NWorld = np.array([9, 9, 9, 9]) xt = util.tCoordinates(NWorld) ind = util.convertpCoordIndexToLinearIndex(NWorld-1, [7, 3, 6, 0]) self.assertTrue(np.allclose(xt[ind] - np.array([15., 7., 13., 1.])/18., 0))
def test_pCoordinates(self): NWorld = np.array([5]) xp = util.pCoordinates(NWorld) self.assertTrue(np.allclose(xp.T - np.array([0., 1., 2., 3., 4., 5.])/5, 0)) NWorld = np.array([9, 9, 9, 9]) xp = util.pCoordinates(NWorld) ind = util.convertpCoordIndexToLinearIndex(NWorld, [7, 3, 6, 0]) self.assertTrue(np.allclose(xp[ind] - np.array([7., 3., 6., 0.])/9., 0))
def test_computeFullDomain(self): NWorldCoarse = np.array([1, 1, 1], dtype='int64') NCoarseElement = np.array([4, 2, 3], dtype='int64') NWorldFine = NWorldCoarse*NCoarseElement np.random.seed(0) world = World(NWorldCoarse, NCoarseElement) d = np.size(NWorldCoarse) k = np.max(NWorldCoarse) IWorld = interp.nodalPatchMatrix(Patch(world, k, 0)) aWorld = np.exp(np.random.rand(world.NtFine)) elementpIndexMap = util.lowerLeftpIndexMap(np.ones_like(NWorldCoarse), NWorldCoarse) elementpIndexMapFine = util.lowerLeftpIndexMap(NCoarseElement, NWorldFine) coarsepBasis = util.linearpIndexBasis(NWorldCoarse) finepBasis = util.linearpIndexBasis(NWorldFine) correctors = np.zeros((world.NpFine, world.NpCoarse)) basis = np.zeros((world.NpFine, world.NpCoarse)) for iElementWorldCoarse in it.product(*[np.arange(n, dtype='int64') for n in NWorldCoarse]): iElementWorldCoarse = np.array(iElementWorldCoarse) TInd = util.convertpCoordIndexToLinearIndex(NWorldCoarse, iElementWorldCoarse) patch = Patch(world, k, TInd) correctorsList = lod.computeBasisCorrectors(patch, IWorld, aWorld) worldpIndices = np.dot(coarsepBasis, iElementWorldCoarse) + elementpIndexMap correctors[:,worldpIndices] += np.column_stack(correctorsList) worldpFineIndices = np.dot(finepBasis, iElementWorldCoarse*NCoarseElement) + elementpIndexMapFine basis[np.ix_(worldpFineIndices, worldpIndices)] = world.localBasis AGlob = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, aWorld) alpha = np.random.rand(world.NpCoarse) vH = np.dot(basis, alpha) QvH = np.dot(correctors, alpha) # Check norm inequality self.assertTrue(np.dot(QvH.T, AGlob*QvH) <= np.dot(vH.T, AGlob*vH)) # Check that correctors are really fine functions self.assertTrue(np.isclose(np.linalg.norm(IWorld*correctors, ord=np.inf), 0)) v = np.random.rand(world.NpFine, world.NpCoarse) v[util.boundarypIndexMap(NWorldFine)] = 0 # The chosen interpolation operator doesn't ruin the boundary conditions. vf = v-np.dot(basis, IWorld*v) vf = vf/np.sqrt(np.sum(vf*(AGlob*vf), axis=0)) # Check orthogonality self.assertTrue(np.isclose(np.linalg.norm(np.dot(vf.T, AGlob*(correctors - basis)), ord=np.inf), 0))
def assembleBasisCorrectors(self): ''' Constructs {Q\lambda_x}_x by the sum Q\lambda_x = \sum_T Q_T\lambda_x ''' if self.basis_correctors is not None: return self.basis_correctors 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.convertpCoordIndexToLinearIndex( 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) basis_correctors = sparse.csc_matrix((data, (rows, cols)), shape=(NpFine, NpCoarse)) self.basis_correctors = basis_correctors return basis_correctors
def compute_localized_node_correction(self, b_patch, a_patch, IPatch, prev_fs_sol, node_index): '''Compute the fine correctors over the node based patch. Compute the correctors, for all z \in V^f(U(\omega_{x,k})): a(\phi_x, z) + \tau b(\phi_x, z) = a(\lambda_x, z) + \tau b(\lambda_x, z) ''' world = self.world NCoarseElement = world.NCoarseElement NPatchCoarse = self.NPatchCoarse iPatchWorldCoarse = self.iPatchWorldCoarse NPatchFine = NPatchCoarse * NCoarseElement NtFine = np.prod(NPatchFine) NpFine = np.prod(NPatchFine + 1) iPatchWorldFine = iPatchWorldCoarse * NCoarseElement patchpIndexMap = util.lowerLeftpIndexMap(NPatchFine, world.NWorldFine) patchpStartIndex = util.convertpCoordIndexToLinearIndex( world.NWorldFine, iPatchWorldFine) patch_indices = patchpStartIndex + patchpIndexMap b_patch = b_patch.aFine a_patch = a_patch.aFine assert (np.size(b_patch) == NtFine) S_patch = fem.assemblePatchMatrix(NPatchFine, world.ALocFine, b_patch) K_patch = fem.assemblePatchMatrix(NPatchFine, world.ALocFine, a_patch) bPatchFull = np.zeros(NpFine) if prev_fs_sol is not None: if type(prev_fs_sol) is not np.ndarray: bPatchFull += K_patch * prev_fs_sol.toarray( )[:, node_index][patch_indices] #bPatchFull += prev_fs_sol.toarray()[:, node_index][patch_indices].T * K_patch else: bPatchFull += K_patch * prev_fs_sol[patch_indices] #bPatchFull += prev_fs_sol[patch_indices].T * K_patch fs_patch_solution = ritzProjectionToFinePatchWithGivenSaddleSolver( world, self.iPatchWorldCoarse, NPatchCoarse, S_patch + K_patch, [bPatchFull], IPatch, self.saddleSolver) fs_solution = np.zeros(world.NpFine) fs_solution[patch_indices] += fs_patch_solution[0] return fs_solution
def test_computeSingleT(self): NWorldCoarse = np.array([4, 5, 6]) NCoarseElement = np.array([5, 2, 3]) world = World(NWorldCoarse, NCoarseElement) d = np.size(NWorldCoarse) k = 1 iElementWorldCoarse = np.array([2, 1, 2]) TInd = util.convertpCoordIndexToLinearIndex(NWorldCoarse, iElementWorldCoarse) patch = Patch(world, k, TInd) IPatch = interp.L2ProjectionPatchMatrix(patch) NtPatch = patch.NtFine aPatch = np.ones(NtPatch) basisCorrectorsList = lod.computeBasisCorrectors(patch, IPatch, aPatch) correctorSum = reduce(np.add, basisCorrectorsList) self.assertTrue(np.allclose(correctorSum, 0)) csi = lod.computeBasisCoarseQuantities(patch, basisCorrectorsList, aPatch) # Test that the matrices have the constants in their null space #self.assertTrue(np.allclose(np.sum(ec.csi.LTPrimeij, axis=1), 0)) #self.assertTrue(np.allclose(np.sum(ec.csi.LTPrimeij, axis=2), 0)) self.assertTrue(np.allclose(np.sum(csi.Kij, axis=0), 0)) self.assertTrue(np.allclose(np.sum(csi.Kij, axis=1), 0)) self.assertTrue(np.allclose(np.sum(csi.Kmsij, axis=0), 0)) self.assertTrue(np.allclose(np.sum(csi.Kmsij, axis=1), 0)) # I had difficulties come up with test cases here. This test # verifies that most "energy" is in the element T. elementTIndex = util.convertpCoordIndexToLinearIndex(patch.NPatchCoarse-1, patch.iElementPatchCoarse) self.assertTrue(np.all(csi.muTPrime[elementTIndex] >= csi.muTPrime)) self.assertTrue(not np.all(csi.muTPrime[elementTIndex+1] >= csi.muTPrime))
def localizeCoefficient(patch, aFine, periodic=False): ''' localizes a coefficient aFine to patch. Optional argument whether erveything is to be interpreted in periodic manner. Adapted from gridlod.coef.localizeCoefficient, periodicty functionality is newly added''' iPatchWorldCoarse = patch.iPatchWorldCoarse NPatchCoarse = patch.NPatchCoarse NCoarseElement = patch.world.NCoarseElement NPatchFine = NPatchCoarse * NCoarseElement iPatchWorldFine = iPatchWorldCoarse * NCoarseElement NWorldFine = patch.world.NWorldFine NtPatchFine = np.prod(NPatchFine) d = np.size(iPatchWorldCoarse) # a coarsetIndexMap = util.lowerLeftpIndexMap(NPatchFine - 1, NWorldFine - 1) coarsetStartIndex = util.convertpCoordIndexToLinearIndex(NWorldFine - 1, iPatchWorldFine) if periodic: coarsetIndCoord = (iPatchWorldFine.T + util.convertpLinearIndexToCoordIndex(NWorldFine - 1, coarsetIndexMap).T) \ % NWorldFine coarsetIndices = util.convertpCoordIndexToLinearIndex(NWorldFine - 1, coarsetIndCoord) aFineLocalized = aFine[coarsetIndices] else: aFineLocalized = aFine[coarsetStartIndex + coarsetIndexMap] return aFineLocalized
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.convertpCoordIndexToLinearIndex( 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
def test_testCsi_Kmsij(self): NWorldCoarse = np.array([4, 5, 6]) NCoarseElement = np.array([5, 2, 3]) world = World(NWorldCoarse, NCoarseElement) d = np.size(NWorldCoarse) k = 1 iElementWorldCoarse = np.array([2, 1, 2]) TInd = util.convertpCoordIndexToLinearIndex(NWorldCoarse, iElementWorldCoarse) patch = Patch(world, k, TInd) IPatch = interp.L2ProjectionPatchMatrix(patch) NtPatch = patch.NtFine np.random.seed(1) aPatch = np.random.rand(NtPatch) basisCorrectorsList = lod.computeBasisCorrectors(patch, IPatch, aPatch) csi = lod.computeBasisCoarseQuantities(patch, basisCorrectorsList, aPatch) TFinetIndexMap = util.extractElementFine(patch.NPatchCoarse, NCoarseElement, patch.iElementPatchCoarse, extractElements=True) TFinepIndexMap = util.extractElementFine(patch.NPatchCoarse, NCoarseElement, patch.iElementPatchCoarse, extractElements=False) TCoarsepIndexMap = util.extractElementFine(patch.NPatchCoarse, np.ones_like(NCoarseElement), patch.iElementPatchCoarse, extractElements=False) APatchFine = fem.assemblePatchMatrix(patch.NPatchFine, world.ALocFine, aPatch) AElementFine = fem.assemblePatchMatrix(NCoarseElement, world.ALocFine, aPatch[TFinetIndexMap]) basisPatch = fem.assembleProlongationMatrix(patch.NPatchCoarse, NCoarseElement) correctorsPatch = np.column_stack(basisCorrectorsList) localBasis = world.localBasis KmsijShouldBe = -basisPatch.T*(APatchFine*(correctorsPatch)) KmsijShouldBe[TCoarsepIndexMap,:] += np.dot(localBasis.T, AElementFine*localBasis) self.assertTrue(np.isclose(np.max(np.abs(csi.Kmsij-KmsijShouldBe)), 0))
def computeErrorIndicatorCoarse_helmholtz(patch, muTPrime, aPatchOld, aPatchNew): ''' Compute the coarse error idicator E(T) with explicit value of AOld and ANew. This requires muTPrime from CSI and the new and old coefficient. ''' while callable(muTPrime): muTPrime = muTPrime() while callable(aPatchOld): aPatchOld = aPatchOld() while callable(aPatchNew): aPatchNew = aPatchNew() aOld = aPatchOld aNew = aPatchNew world = patch.world NPatchCoarse = patch.NPatchCoarse NCoarseElement = world.NCoarseElement NPatchFine = NPatchCoarse * NCoarseElement iElementPatchCoarse = patch.iElementPatchCoarse elementCoarseIndex = util.convertpCoordIndexToLinearIndex( NPatchCoarse - 1, iElementPatchCoarse) TPrimeFinetStartIndices = util.pIndexMap(NPatchCoarse - 1, NPatchFine - 1, NCoarseElement) TPrimeFinetIndexMap = util.lowerLeftpIndexMap(NCoarseElement - 1, NPatchFine - 1) TPrimeIndices = np.add.outer(TPrimeFinetStartIndices, TPrimeFinetIndexMap) aTPrime = aNew[TPrimeIndices] aOldTPrime = aOld[TPrimeIndices] deltaMaxTPrime = np.max(np.abs(aTPrime - aOldTPrime), axis=1) epsilonTSquare = np.sum((deltaMaxTPrime**2) * muTPrime) return np.sqrt(epsilonTSquare)
def compute_localized_basis_node(self, b_patch, a_patch, IPatch, basis, node_index): ''' Description ''' world = self.world NCoarseElement = world.NCoarseElement NPatchCoarse = self.NPatchCoarse iPatchWorldCoarse = self.iPatchWorldCoarse NPatchFine = NPatchCoarse * NCoarseElement NtFine = np.prod(NPatchFine) NpFine = np.prod(NPatchFine + 1) iPatchWorldFine = iPatchWorldCoarse * NCoarseElement patchpIndexMap = util.lowerLeftpIndexMap(NPatchFine, world.NWorldFine) patchpStartIndex = util.convertpCoordIndexToLinearIndex( world.NWorldFine, iPatchWorldFine) patch_indices = patchpStartIndex + patchpIndexMap b_patch = b_patch.aFine a_patch = a_patch.aFine assert (np.size(b_patch) == NtFine) S_patch = fem.assemblePatchMatrix(NPatchFine, world.ALocFine, b_patch) K_patch = fem.assemblePatchMatrix(NPatchFine, world.ALocFine, a_patch) bPatchFull = np.zeros(NpFine) bPatchFull += K_patch * basis.toarray()[:, node_index][patch_indices] bPatchFull += S_patch * basis.toarray()[:, node_index][patch_indices] ms_basis_patch_solution = ritzProjectionToFinePatchWithGivenSaddleSolver( world, self.iPatchWorldCoarse, NPatchCoarse, S_patch + K_patch, [bPatchFull], IPatch, self.saddleSolver) ms_basis_solution = np.zeros(world.NpFine) ms_basis_solution[patch_indices] += ms_basis_patch_solution[0] return ms_basis_solution
def compute_rb_node_correction_test(self, b_patch, a_patch, IPatch, prev_fs_sol, V): world = self.world NCoarseElement = world.NCoarseElement NPatchCoarse = self.NPatchCoarse NPatchFine = NPatchCoarse * NCoarseElement NtFine = np.prod(NPatchFine) NpCoarse = np.prod(NPatchCoarse + 1) NpFine = np.prod(NPatchFine + 1) iPatchWorldCoarse = self.iPatchWorldCoarse iPatchWorldFine = iPatchWorldCoarse * NCoarseElement patchpIndexMap = util.lowerLeftpIndexMap(NPatchFine, world.NWorldFine) patchpStartIndex = util.convertpCoordIndexToLinearIndex( world.NWorldFine, iPatchWorldFine) patch_indices = patchpStartIndex + patchpIndexMap b_patch = b_patch.aFine a_patch = a_patch.aFine assert (np.size(b_patch) == NtFine) SPatchFull = fem.assemblePatchMatrix(NPatchFine, world.ALocFine, b_patch) KPatchFull = fem.assemblePatchMatrix(NPatchFine, world.ALocFine, a_patch) bPatchFullList = [] bPatchFull = np.zeros(len((V.todense()))) V = V[:, patch_indices] bPatchFull += prev_fs_sol[patch_indices].T * KPatchFull * V.T bPatchFullList.append(bPatchFull) SPatchFull = V * SPatchFull * V.T KPatchFull = V * KPatchFull * V.T correctorsList = linalg.linSolve(KPatchFull + SPatchFull, bPatchFull.T) return correctorsList
def performTPrimeLoop_helmholtz(patch, lambdasList, correctorsList, aPatch, kPatch, k2Patch, accumulate): while callable(aPatch): aPatch = aPatch() while callable(kPatch): kPatch = kPatch() while callable(k2Patch): k2Patch = k2Patch() world = patch.world NCoarseElement = world.NCoarseElement NPatchCoarse = patch.NPatchCoarse NPatchFine = NPatchCoarse * NCoarseElement NTPrime = np.prod(NPatchCoarse) NpPatchCoarse = np.prod(NPatchCoarse + 1) d = np.size(NPatchCoarse) assert (aPatch.ndim == 1 or aPatch.ndim == 3) assert (kPatch.ndim == 1) assert (k2Patch.ndim == 1) if aPatch.ndim == 1: ALocFine = world.ALocFine elif aPatch.ndim == 3: ALocFine = world.ALocMatrixFine MLocFine = world.MLocFine BdLocFine = fem.localBoundaryMassMatrixGetter(NCoarseElement * world.NWorldCoarse) lambdas = np.column_stack(lambdasList) numLambdas = len(lambdasList) 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.convertpCoordIndexToLinearIndex(NPatchCoarse - 1, patch.iElementPatchCoarse) QPatch = np.column_stack(correctorsList) # global boundary bdMapWorld = world.boundaryConditions == 1 for (TPrimeInd, TPrimeCoarsepStartIndex, TPrimeFinetStartIndex, TPrimeFinepStartIndex) \ in zip(np.arange(NTPrime), TPrimeCoarsepStartIndices, TPrimeFinetStartIndices, TPrimeFinepStartIndices): aTPrime = aPatch[TPrimeFinetStartIndex + TPrimeFinetIndexMap] kTPrime = kPatch[TPrimeFinetStartIndex + TPrimeFinetIndexMap] k2TPrime = k2Patch[TPrimeFinetStartIndex + TPrimeFinetIndexMap] KTPrime = fem.assemblePatchMatrix(NCoarseElement, ALocFine, aTPrime) MTPrime = fem.assemblePatchMatrix(NCoarseElement, MLocFine, k2TPrime) L2TPrime = fem.assemblePatchMatrix(NCoarseElement, MLocFine) # boundary on element bdMapElement = np.zeros([d, 2], dtype='bool') iElementTPrime = patch.iPatchWorldCoarse + util.convertpLinearIndexToCoordIndex( NPatchCoarse - 1, TPrimeInd) inheritElement0 = iElementTPrime == 0 inheritElement1 = (iElementTPrime + np.ones(d)) == world.NWorldCoarse bdMapElement[inheritElement0, 0] = bdMapWorld[inheritElement0, 0] bdMapElement[inheritElement1, 1] = bdMapWorld[inheritElement1, 1] BdTPrime = fem.assemblePatchBoundaryMatrix(NCoarseElement, BdLocFine, kTPrime, bdMapElement) P = lambdas Q = QPatch[TPrimeFinepStartIndex + TPrimeFinepIndexMap, :] _KTPrimeij = np.dot(P.T, KTPrime * Q) TPrimei = TPrimeCoarsepStartIndex + TPrimeCoarsepIndexMap _MTPrimeij = np.dot(P.T, MTPrime * Q) _BdTPrimeij = np.dot(P.T, BdTPrime * Q) CTPrimeij = np.dot(Q.T, L2TPrime * Q) BTPrimeij = np.dot(P.T, L2TPrime * Q) accumulate(TPrimeInd, TPrimei, P, Q, KTPrime, _KTPrimeij, MTPrime, BdTPrime, _MTPrimeij, _BdTPrimeij, L2TPrime, CTPrimeij, BTPrimeij)
def computeBasisCoarseQuantities_helmholtz(patch, correctorsList, aPatch, kPatch, k2Patch): ''' Compute the coarse quantities for the basis and its correctors Compute the tensors (T is implicit by the patch definition) and return them in a CoarseScaleInformation object: Kij = (A \nabla lambda_j, \nabla lambda_i)_{T} KmsTij = (A \nabla (lambda_j - corrector_j), \nabla lambda_i)_{U_k(T)} Mij = (k^2n lambda_j, lambda_i)_{T} Mmsij = (k^2n (lambda_j - corrector_j), lambda_i)_{U_k(T)} Bdij = (k lambda_j, lambda_i)_{\partial T \cap \partial \Omega} Bdmsij = (k (lambda_j - corrector_j), lambda_i)_{\partial T \cap \partial \Omega} muTT' = max_{\alpha_j} || \alpha_j (\chi_T lambda_j - corrector_j) ||^2_T' / || \alpha_j lambda_j ||^2_T Auxiliary quantities are computed, but not saved ''' lambdasList = list(patch.world.localBasis.T) NPatchCoarse = patch.NPatchCoarse NTPrime = np.prod(NPatchCoarse) NpPatchCoarse = np.prod(NPatchCoarse + 1) numLambdas = len(lambdasList) TInd = util.convertpCoordIndexToLinearIndex(patch.NPatchCoarse - 1, patch.iElementPatchCoarse) Kmsij = np.zeros((NpPatchCoarse, numLambdas), dtype='complex128') Mmsij = np.zeros((NpPatchCoarse, numLambdas), dtype='complex128') Bdmsij = np.zeros((NpPatchCoarse, numLambdas), dtype='complex128') LTPrimeij = np.zeros((NTPrime, numLambdas, numLambdas), dtype='complex128') Kij = np.zeros((numLambdas, numLambdas), dtype='complex128') Mij = np.zeros((numLambdas, numLambdas), dtype='complex128') Bdij = np.zeros((numLambdas, numLambdas), dtype='complex128') L2ij = np.zeros((numLambdas, numLambdas), dtype='complex128') def accumulate(TPrimeInd, TPrimei, P, Q, KTPrime, _KTPrimeij, MTPrime, BdTPrime, _MTPrimeij, _BdTPrimeij, L2TPrime, CTPrimeij, BTPrimeij): if TPrimeInd == TInd: Kij[:] = np.dot(P.T, KTPrime * P) Mij[:] = np.dot(P.T, MTPrime * P) Bdij[:] = np.dot(P.T, BdTPrime * P) L2ij[:] = np.dot(P.T, L2TPrime * P) LTPrimeij[TPrimeInd] = CTPrimeij \ - BTPrimeij \ - BTPrimeij.T \ + L2ij Kmsij[TPrimei, :] += Kij - _KTPrimeij Mmsij[TPrimei, :] += Mij - _MTPrimeij Bdmsij[TPrimei, :] += Bdij - _BdTPrimeij else: LTPrimeij[TPrimeInd] = CTPrimeij Kmsij[TPrimei, :] += -_KTPrimeij Mmsij[TPrimei, :] += -_MTPrimeij Bdmsij[TPrimei, :] += -_BdTPrimeij performTPrimeLoop_helmholtz(patch, lambdasList, correctorsList, aPatch, kPatch, k2Patch, accumulate) muTPrime = np.zeros(NTPrime, dtype='complex128') cutRows = 0 while np.linalg.cond(L2ij[cutRows:, cutRows:]) > 1e8: cutRows = cutRows + 1 for TPrimeInd in np.arange(NTPrime): # Solve eigenvalue problem LTPrimeij x = mu_TPrime Mij x eigenvalues = scipy.linalg.eigvals( LTPrimeij[TPrimeInd][cutRows:, cutRows:], L2ij[cutRows:, cutRows:]) muTPrime[TPrimeInd] = np.max(np.real(eigenvalues)) return CoarseScaleInformation_helmholtz(Kij, Kmsij, muTPrime, Mij, Mmsij, Bdij, Bdmsij)
def test_computeCoarseErrorIndicatorFlux(self): NWorldCoarse = np.array([7, 7], dtype='int64') NCoarseElement = np.array([10, 10], dtype='int64') NWorldFine = NWorldCoarse * NCoarseElement NpWorldFine = np.prod(NWorldFine + 1) NpWorldCoarse = np.prod(NWorldCoarse + 1) NtWorldFine = np.prod(NWorldCoarse * NCoarseElement) NtWorldCoarse = np.prod(NWorldCoarse) np.random.seed(0) world = World(NWorldCoarse, NCoarseElement) d = np.size(NWorldCoarse) aBase = np.exp(np.random.rand(NtWorldFine)) k = np.max(NWorldCoarse) iElementWorldCoarse = np.array([3, 3]) rCoarseFirst = 1 + 3 * np.random.rand(NtWorldCoarse) coefFirst = coef.CoefficientCoarseFactor(NWorldCoarse, NCoarseElement, aBase, rCoarseFirst) IPatchGenerator = lambda i, N: interp.L2ProjectionPatchMatrix( i, N, NWorldCoarse, NCoarseElement) ec = lod_flux.CoarseBasisElementCorrectorFlux(world, k, iElementWorldCoarse, IPatchGenerator) ec.computeCorrectors(coefFirst) ec.computeCoarseQuantities() # If both rCoarseFirst and rCoarseSecond are equal, the error indicator should be zero rCoarseSecond = np.array(rCoarseFirst) self.assertTrue( np.isclose(ec.computeCoarseErrorIndicatorFlux(rCoarseSecond), 0)) coefSecond = coef.CoefficientCoarseFactor(NWorldCoarse, NCoarseElement, aBase, rCoarseSecond) self.assertTrue(np.isclose(ec.computeErrorIndicatorFine(coefSecond), 0)) # If rCoarseSecond is not rCoarseFirst, the error indicator should not be zero rCoarseSecond = 2 * np.array(rCoarseFirst) self.assertTrue( ec.computeCoarseErrorIndicatorFlux(rCoarseSecond) >= 0.1) coefSecond = coef.CoefficientCoarseFactor(NWorldCoarse, NCoarseElement, aBase, rCoarseSecond) self.assertTrue(ec.computeErrorIndicatorFine(coefSecond) >= 0.1) # Fine should be smaller than coarse estimate self.assertTrue( ec.computeErrorIndicatorFine(coefSecond) < ec.computeCoarseErrorIndicatorFlux(rCoarseSecond)) # If rCoarseSecond is different in the element itself, the error # indicator should be large elementCoarseIndex = util.convertpCoordIndexToLinearIndex( NWorldCoarse - 1, iElementWorldCoarse) rCoarseSecond = np.array(rCoarseFirst) rCoarseSecond[elementCoarseIndex] *= 2 saveForNextTest = ec.computeCoarseErrorIndicatorFlux(rCoarseSecond) self.assertTrue(saveForNextTest >= 0.1) coefSecond = coef.CoefficientCoarseFactor(NWorldCoarse, NCoarseElement, aBase, rCoarseSecond) fineResult = ec.computeErrorIndicatorFine(coefSecond) self.assertTrue(fineResult >= 0.1) self.assertTrue( ec.computeErrorIndicatorFine(coefSecond) < ec.computeCoarseErrorIndicatorFlux(rCoarseSecond)) # A difference in the perifery should be smaller than in the center rCoarseSecond = np.array(rCoarseFirst) rCoarseSecond[0] *= 2 self.assertTrue( saveForNextTest > ec.computeCoarseErrorIndicatorFlux(rCoarseSecond) ) # Again, but closer rCoarseSecond = np.array(rCoarseFirst) rCoarseSecond[elementCoarseIndex - 1] *= 2 self.assertTrue( saveForNextTest > ec.computeCoarseErrorIndicatorFlux(rCoarseSecond) )
def computeErrorIndicatorFineMultiple(patch, correctorsList, aRefList, mu, aPatchNew=None): ''' Compute the fine error indicator e(T) for given vector mu. This requires reference coefficients (already localized) and their correctors. New coefficient is optional, otherwise assumed to be weighted sum of mu and reference coefficients. ''' while callable(aPatchNew): aPatchNew = aPatchNew() if aRefList[0].ndim != 1: NotImplementedError("matrix-valued coefficient not yet supported") lambdasList = list(patch.world.localBasis.T) NPatchCoarse = patch.NPatchCoarse world = patch.world NCoarseElement = world.NCoarseElement NPatchFine = NPatchCoarse * NCoarseElement nref = len(aRefList) a = aPatchNew ALocFine = world.ALocFine P = np.column_stack(lambdasList) TFinetIndexMap = util.lowerLeftpIndexMap(NCoarseElement - 1, NPatchFine - 1) iElementPatchFine = patch.iElementPatchCoarse * NCoarseElement TFinetStartIndex = util.convertpCoordIndexToLinearIndex( NPatchFine - 1, iElementPatchFine) TFinepIndexMap = util.lowerLeftpIndexMap(NCoarseElement, NPatchFine) TFinepStartIndex = util.convertpCoordIndexToLinearIndex( NPatchFine, iElementPatchFine) A = np.zeros_like(world.ALocCoarse) aBar = np.einsum('i, ij->j', mu, aRefList) if aPatchNew is None: a = aBar else: a = aPatchNew bTcoeff = np.sqrt(a) * (1 - aBar / a) bT = bTcoeff[TFinetStartIndex + TFinetIndexMap] TNorm = fem.assemblePatchMatrix(NCoarseElement, ALocFine, bT**2) nnz = np.where(mu != 0)[0] def addtoA(A, kk): ii = kk[0] jj = kk[1] bij = (mu[ii] * np.sqrt(a) * (1 - aRefList[ii] / a)) * (mu[jj] * np.sqrt(a) * (1 - aRefList[jj] / a)) PatchNorm = fem.assemblePatchMatrix(NPatchFine, ALocFine, bij) Q1 = np.column_stack(correctorsList[ii]) Q2 = np.column_stack(correctorsList[jj]) A += np.dot(Q1.T, PatchNorm * Q2) if aPatchNew is not None: bii = mu[ii] * np.sqrt(a) * (1 - aRefList[ii] / a) bjj = mu[jj] * np.sqrt(a) * (1 - aRefList[jj] / a) bTii = bT * bii[TFinetStartIndex + TFinetIndexMap] bTjj = bT * bjj[TFinetStartIndex + TFinetIndexMap] TNormPQ = fem.assemblePatchMatrix(NCoarseElement, ALocFine, bTjj) TNormQP = fem.assemblePatchMatrix(NCoarseElement, ALocFine, bTii) QT1 = Q1[TFinepStartIndex + TFinepIndexMap, :] QT2 = Q2[TFinepStartIndex + TFinepIndexMap, :] A -= np.dot(P.T, TNormPQ * QT2) A -= np.dot(QT1.T, TNormQP * P) assembleA = lambda kk: addtoA(A, kk) import itertools list(map(assembleA, itertools.product(nnz, repeat=2))) if aPatchNew is not None: A += np.dot(P.T, TNorm * P) BNorm = fem.assemblePatchMatrix(NCoarseElement, ALocFine, a[TFinetStartIndex + TFinetIndexMap]) 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)