def test_assembleProlongationMatrixProperties(self): NPatchCoarse = np.array([2, 2]) NCoarseElement = np.array([4, 4]) P = fem.assembleProlongationMatrix(NPatchCoarse, NCoarseElement) self.assertTrue(np.isclose(np.linalg.norm(P.sum(axis=1) - 1), 0)) self.assertTrue(np.isclose(P[40, 4], 1))
def test_trivial(self): NPatchCoarse = np.array([3,3]) NCoarseElement = np.array([2,2]) NPatchFine = NPatchCoarse*NCoarseElement Nt = np.prod(NPatchFine) Np = np.prod(NPatchFine+1) fixed = util.boundarypIndexMap(NPatchFine) world = World(NPatchCoarse, NCoarseElement) patch = Patch(world, 3, 0) aFlatPatchFine = np.ones(Nt) ALoc = fem.localStiffnessMatrix(NPatchFine) APatchFull = fem.assemblePatchMatrix(NPatchFine, ALoc, aFlatPatchFine) PPatch = fem.assembleProlongationMatrix(NPatchCoarse, NCoarseElement) IPatchNodal = interp.nodalPatchMatrix(patch) #IPatchuncL2 = interp.uncoupledL2ProjectionPatchMatrix(np.array([0, 0]), NPatchCoarse, NPatchCoarse, NCoarseElement) IPatchL2 = interp.L2ProjectionPatchMatrix(patch) for IPatch in [IPatchNodal, IPatchL2]: np.random.seed(0) bPatchFullList = [] self.assertTrue(not lod.ritzProjectionToFinePatch(patch, APatchFull, bPatchFullList, IPatch)) bPatchFullList = [np.zeros(Np)] projections = lod.ritzProjectionToFinePatch(patch, APatchFull, bPatchFullList, IPatch) self.assertEqual(len(projections), 1) self.assertTrue(np.allclose(projections[0], 0*projections[0])) bPatchFull = np.random.rand(Np) bPatchFullList = [bPatchFull] projections = lod.ritzProjectionToFinePatch(patch, APatchFull, bPatchFullList, IPatch) self.assertTrue(np.isclose(np.linalg.norm(IPatch*projections[0]), 0)) self.assertTrue(np.isclose(np.dot(projections[0], APatchFull*projections[0]), np.dot(projections[0], bPatchFullList[0]))) self.assertTrue(np.isclose(np.linalg.norm(projections[0][fixed]), 0)) bPatchFullList = [bPatchFull, -bPatchFull] projections = lod.ritzProjectionToFinePatch(patch, APatchFull, bPatchFullList, IPatch) self.assertTrue(np.allclose(projections[0], -projections[1])) bPatchFullList = [np.random.rand(Np), np.random.rand(Np)] projections = lod.ritzProjectionToFinePatch(patch, APatchFull, bPatchFullList, IPatch) self.assertTrue(np.isclose(np.dot(projections[1], APatchFull*projections[0]), np.dot(projections[1], bPatchFullList[0]))) bPatchFull = np.random.rand(Np) bPatchFullList = [bPatchFull] projectionCheckAgainst = lod.ritzProjectionToFinePatch(patch, APatchFull, bPatchFullList, IPatch)[0] for saddleSolver in [#lod.nullspaceOneLevelHierarchySolver(NPatchCoarse, NCoarseElement), lod.SchurComplementSolver()]: projection = lod.ritzProjectionToFinePatch(patch, APatchFull, bPatchFullList, IPatch, saddleSolver)[0] self.assertTrue(np.isclose(np.max(np.abs(projectionCheckAgainst-projection)), 0))
def VcLod(pglod, world, Anew, eps, updated=0, numberofcorrectors=5): NWorldFine = world.NWorldFine NWorldCoarse = world.NWorldCoarse NCoarseElement = world.NCoarseElement boundaryConditions = world.boundaryConditions NpFine = np.prod(NWorldFine + 1) NpCoarse = np.prod(NWorldCoarse + 1) ##### tolerance = certain ###### eps = [x for x in eps if x != 0] eps.sort() epssize = np.size(eps) until = int(round((numberofcorrectors / 100. * epssize) + 0.49, 0)) if epssize != 0: until = int(round((until * 256. / epssize) + 0.49, 0)) tolrev = [] for i in range(epssize - 1, -1, -1): tolrev.append(eps[i]) if epssize == 0: print('nothing to update') else: if until >= epssize: tol = 0 else: tol = tolrev[until] vistol, _ = pglod.updateCorrectors(Anew, tol, clearFineQuantities=False, mc=True, Testing=True) updated += np.sum(vistol) print(('Updated correctors: ' + str(updated))) KFull = pglod.assembleMsStiffnessMatrix() MFull = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) free = util.interiorpIndexMap(NWorldCoarse) bFull = MFull * f KFree = KFull[free][:, free] bFree = bFull[free] xFree = sparse.linalg.spsolve(KFree, bFree) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basisCorrectors = pglod.assembleBasisCorrectors() modifiedBasis = basis - basisCorrectors xFull = np.zeros(NpCoarse) xFull[free] = xFree uCoarse = xFull uVcLod = modifiedBasis * xFull return uVcLod, updated
def test_stiffessMatrix(self): # Compare stiffness matrix from PG object with the one # computed from correctors and fine stiffness matrix NWorldFine = np.array([10, 10]) NpFine = np.prod(NWorldFine + 1) NtFine = np.prod(NWorldFine) NWorldCoarse = np.array([2, 2]) NCoarseElement = NWorldFine / NWorldCoarse NtCoarse = np.prod(NWorldCoarse) NpCoarse = np.prod(NWorldCoarse + 1) world = World(NWorldCoarse, NCoarseElement) np.random.seed(0) aBase = np.random.rand(NtFine) aCoef = coef.coefficientFine(NWorldCoarse, NCoarseElement, aBase) IPatchGenerator = lambda i, N: interp.L2ProjectionPatchMatrix( i, N, NWorldCoarse, NCoarseElement) IWorld = IPatchGenerator(0 * NWorldCoarse, NWorldCoarse) k = 2 printLevel = 0 pglod = pg.PetrovGalerkinLOD(world, k, IPatchGenerator, 0, printLevel) pglod.updateCorrectors(aCoef, clearFineQuantities=False) KmsFull = pglod.assembleMsStiffnessMatrix() KFull = pglod.assembleStiffnessMatrix() basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basisCorrectors = pglod.assembleBasisCorrectors() self.assertTrue( np.isclose(np.linalg.norm(IWorld * basisCorrectors.todense()), 0)) modifiedBasis = basis - basisCorrectors AFine = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, aBase) KmsRef = np.dot(basis.T, AFine * modifiedBasis) KRef = np.dot(basis.T, AFine * basis) self.assertTrue( np.isclose(np.linalg.norm(KFull.todense() - KRef.todense()), 0)) self.assertTrue( np.isclose(np.linalg.norm(KmsFull.todense() - KmsRef.todense()), 0))
def solveCoarse_fem(world, aFine, bFine, MbFine, U, tau, boundaryConditions, i): 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) boundaryMap = boundaryConditions == 0 fixedCoarse = util.boundarypIndexMap(NWorldCoarse, boundaryMap=boundaryMap) freeCoarse = np.setdiff1d(np.arange(NpCoarse), fixedCoarse) AFine = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, aFine) BFine = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, bFine) MFine = fem.assemblePatchMatrix(NWorldFine, world.MLocFine) bFine = MFine * MbFine basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) ACoarse = basis.T * (AFine * basis) BCoarse = basis.T * (BFine * basis) MCoarse = basis.T * (MFine * basis) bCoarse = basis.T * bFine ACoarseFree = ACoarse[freeCoarse][:, freeCoarse] BCoarseFree = BCoarse[freeCoarse][:, freeCoarse] MCoarseFree = MCoarse[freeCoarse][:, freeCoarse] bCoarseFree = bCoarse[freeCoarse] A = (1. / tau**2) * MCoarseFree + (1. / tau) * ACoarseFree + BCoarseFree if i == 0: b = bCoarseFree + (1. / tau) * ACoarseFree * U[i][freeCoarse] + ( 1. / tau) * MCoarseFree * ((2. / tau) * U[i][freeCoarse]) else: b = bCoarseFree + (1. / tau) * ACoarseFree * U[i][freeCoarse] + ( 1. / tau) * MCoarseFree * ((2. / tau) * U[i][freeCoarse] - (1. / tau) * U[i - 1][freeCoarse]) uCoarseFree = linalg.linSolve(A, b) uCoarseFull = np.zeros(NpCoarse) uCoarseFull[freeCoarse] = uCoarseFree uCoarseFull = uCoarseFull return uCoarseFull
def standard_fem(world, N, fine, tau, tot_time_steps, aFine, bFine, f): # mesh parameters NWorldCoarse = np.array([N, N]) NFine = np.array([fine, fine]) NCoarseElement = NFine // NWorldCoarse NWorldFine = world.NWorldCoarse * world.NCoarseElement bc = world.boundaryConditions world = World(NWorldCoarse, NCoarseElement, bc) NpCoarse = np.prod(NWorldCoarse + 1) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) Uo = np.zeros(NpCoarse) # coarse v^(-1) and v^0 V = [Uo] V.append(Uo) # compute ms matrices S = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, aFine) K = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, bFine) M = fem.assemblePatchMatrix(NWorldFine, world.MLocFine) free = util.interiorpIndexMap(NWorldCoarse) SmsFree = (basis.T * S * basis)[free][:, free] KmsFree = (basis.T * K * basis)[free][:, free] MmsFree = (basis.T * M * basis)[free][:, free] LmsFree = (basis.T * M * f)[free] for i in range(tot_time_steps): n = i + 1 # linear system A = (1. / (tau ** 2)) * MmsFree + (1. / tau) * SmsFree + KmsFree b = LmsFree + (1. / tau) * SmsFree * V[n][free] + (2. / (tau ** 2)) * MmsFree * V[n][free] \ - (1. / (tau ** 2)) * MmsFree * V[n - 1][free] # solve system VFree = linalg.linSolve(A, b) VFull = np.zeros(NpCoarse) VFull[free] = VFree # append solution for current time step V.append(VFull) return basis * V[-1]
def compute_basis_correctors_node(self, localized=False): ''' Why did I construct this one..? ''' world = self.world k = self.k IPatchGenerator = self.IPatchGenerator b_coef = self.b_coefconvertpCoordIndexToLinea a_coef = self.a_coef NpCoarse = np.prod(world.NWorldCoarse + 1) if localized: ms_basis_list = [] for node_index in range(NpCoarse): node_index_arr = compute_2d_node(world.NWorldCoarse, node_index) ecT = lod_node.nodeCorrector(world, k, node_index_arr) b_patch = b_coef.localize(ecT.iPatchWorldCoarse, ecT.NPatchCoarse) a_patch = a_coef.localize(ecT.iPatchWorldCoarse, ecT.NPatchCoarse) IPatch = IPatchGenerator(ecT.iPatchWorldCoarse, ecT.NPatchCoarse) basis = fem.assembleProlongationMatrix(world.NWorldCoarse, world.NCoarseElement) ms_basis_solution = ecT.compute_localized_basis_node( b_patch, a_patch, IPatch, basis, node_index) ms_basis_list.append(ms_basis_solution) else: ecT = lod_node.nodeCorrector(world, k, 0) b_patch = b_coef.localize(ecT.iPatchWorldCoarse, ecT.NPatchCoarse) a_patch = a_coef.localize(ecT.iPatchWorldCoarse, ecT.NPatchCoarse) IPatch = IPatchGenerator(ecT.iPatchWorldCoarse, ecT.NPatchCoarse) ms_basis_list = ecT.compute_node_correction( b_patch, a_patch, IPatch, prev_fs_sol) self.ms_basis_list = ms_basis_list
def test_testCsi(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]) ec = lod.elementCorrector(world, k, iElementWorldCoarse) IPatch = interp.L2ProjectionPatchMatrix(ec.iPatchWorldCoarse, ec.NPatchCoarse, NWorldCoarse, NCoarseElement) NtPatch = np.prod(ec.NPatchCoarse*NCoarseElement) np.random.seed(1) aPatch = np.random.rand(NtPatch) coefficientPatch = coef.coefficientFine(ec.NPatchCoarse, NCoarseElement, aPatch) ec.computeCorrectors(coefficientPatch, IPatch) ec.computeCoarseQuantities() TFinetIndexMap = util.extractElementFine(ec.NPatchCoarse, NCoarseElement, ec.iElementPatchCoarse, extractElements=True) TFinepIndexMap = util.extractElementFine(ec.NPatchCoarse, NCoarseElement, ec.iElementPatchCoarse, extractElements=False) TCoarsepIndexMap = util.extractElementFine(ec.NPatchCoarse, np.ones_like(NCoarseElement), ec.iElementPatchCoarse, extractElements=False) APatchFine = fem.assemblePatchMatrix(ec.NPatchCoarse*NCoarseElement, world.ALocFine, aPatch) AElementFine = fem.assemblePatchMatrix(NCoarseElement, world.ALocFine, aPatch[TFinetIndexMap]) basisPatch = fem.assembleProlongationMatrix(ec.NPatchCoarse, NCoarseElement) correctorsPatch = np.column_stack(ec.fsi.correctorsList) localBasis = world.localBasis KmsijShouldBe = -basisPatch.T*(APatchFine*(correctorsPatch)) KmsijShouldBe[TCoarsepIndexMap,:] += np.dot(localBasis.T, AElementFine*localBasis) self.assertTrue(np.isclose(np.max(np.abs(ec.csi.Kmsij-KmsijShouldBe)), 0))
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 PGsolver(world, ABase, f,k): NWorldFine = world.NWorldFine NWorldCoarse = world.NWorldCoarse NCoarseElement = world.NCoarseElement boundaryConditions = world.boundaryConditions NpFine = np.prod(NWorldFine+1) NpCoarse = np.prod(NWorldCoarse+1) #interpolant IPatchGenerator = lambda i, N: interp.L2ProjectionPatchMatrix(i, N, NWorldCoarse, NCoarseElement, boundaryConditions) #Coefficient (need flatten form) aCoef = coef.coefficientFine(NWorldCoarse, NCoarseElement, ABase) pglod = pg_pert.PerturbedPetrovGalerkinLOD(aCoef, world, k, IPatchGenerator, 0) pglod.originCorrectors(clearFineQuantities=False) KFull = pglod.assembleMsStiffnessMatrix() MFull = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) free = util.interiorpIndexMap(NWorldCoarse) bFull = MFull*f KFree = KFull[free][:,free] bFree = bFull[free] xFree = sparse.linalg.spsolve(KFree, bFree) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basisCorrectors = pglod.assembleBasisCorrectors() modifiedBasis = basis - basisCorrectors xFull = np.zeros(NpCoarse) xFull[free] = xFree uLodCoarse = xFull uLodFine = modifiedBasis*xFull return uLodCoarse, uLodFine
def solve(self, f): world = self.world KFull = self.assembleMsStiffnessMatrix() MFull = fem.assemblePatchMatrix(world.NWorldFine, world.MLocFine) free = util.interiorpIndexMap(world.NWorldCoarse) basis = fem.assembleProlongationMatrix(world.NWorldCoarse, world.NCoarseElement) bFull = MFull * f bFull = basis.T * bFull KFree = KFull[free][:, free] bFree = bFull[free] xFree = sparse.linalg.spsolve(KFree, bFree) basisCorrectors = self.assembleBasisCorrectors() modifiedBasis = basis - basisCorrectors NpCoarse = np.prod(world.NWorldCoarse + 1) xFull = np.zeros(NpCoarse) xFull[free] = xFree uLodCoarse = xFull uLodFine = modifiedBasis * xFull return uLodFine, uLodCoarse, basis
def Monte_Carlo_simulation(): print('Computing Monte Carlo step') global aFine_ref global aFine_trans global aFine_pert global k global KmsijT global correctorsListT aFine_ref = aFine_ref_shaped.flatten() psi, cq1 = create_psi_function() # plt.figure('domain mapping') # plt.plot(np.arange(0, fine + 1), cq1[0, :], label='$id(x) - \psi(x)$') # plt.plot(np.arange(0, fine), ref_array * 0.01) # plt.title('Domain mapping') # plt.legend() xpFine_pert = psi.evaluate(xpFine) xpFine_ref = psi.inverse_evaluate(xpFine) xtFine_pert = psi.evaluate(xtFine) xtFine_ref = psi.inverse_evaluate(xtFine) aFine_pert = func.evaluateDQ0(NFine, aFine_ref, xtFine_ref) aBack_ref = func.evaluateDQ0(NFine, aFine_pert, xtFine_pert) print('Psi is invertible if this is zero: {}'.format( np.linalg.norm(aBack_ref - aFine_ref))) every_psi_was_valid.append(np.linalg.norm(aBack_ref - aFine_ref)) #aFine_trans is the transformed perturbed reference coefficient aFine_trans = np.einsum('tji, t, tkj, t -> tik', psi.Jinv(xtFine), aFine_ref, psi.Jinv(xtFine), psi.detJ(xtFine)) f_pert = np.ones(np.prod(NFine + 1)) f_ref = func.evaluateCQ1(NFine, f_pert, xpFine_pert) f_trans = np.einsum('t, t -> t', f_ref, psi.detJ(xpFine)) uFineFull_pert, AFine_pert, MFine = femsolver.solveFine( world, aFine_pert, f_pert, None, boundaryConditions) uFineFull_trans, AFine_trans, _ = femsolver.solveFine( world, aFine_trans, f_trans, None, boundaryConditions) uFineFull_trans_pert = func.evaluateCQ1(NFine, uFineFull_trans, xpFine_ref) energy_norm = np.sqrt(np.dot(uFineFull_pert, AFine_pert * uFineFull_pert)) energy_error = np.sqrt( np.dot((uFineFull_trans_pert - uFineFull_pert), AFine_pert * (uFineFull_trans_pert - uFineFull_pert))) print("Energy norm {}, error {}, rel. error {}".format( energy_norm, energy_error, energy_error / energy_norm)) Aeye = np.tile(np.eye(2), [np.prod(NFine), 1, 1]) aFine_ref = np.einsum('tji, t-> tji', Aeye, aFine_ref) print('compute domain mapping error indicators') epsFine, epsCoarse = zip(*map(computeIndicators, range(world.NtCoarse))) print('apply tolerance') Elements_to_be_updated = [] TOL = 0.1 for i in range(world.NtCoarse): if epsFine[i] >= TOL: Elements_to_be_updated.append(i) print('.... to be updated for domain mapping: {}%'.format( np.size(Elements_to_be_updated) / np.size(epsFine) * 100)) print('update correctors') if np.size(Elements_to_be_updated) == 0: correctorsListTNew, KmsijTNew = correctorsListT, KmsijT else: patchT_irrelevant, correctorsListTNew, KmsijTNew, csiTNew = zip( *map(UpdateCorrectors, Elements_to_be_updated)) KmsijT_list = list(KmsijT) correctorsListT_list = list(correctorsListT) i = 0 for T in Elements_to_be_updated: KmsijT_list[T] = KmsijTNew[i] correctorsListT_list[T] = correctorsListTNew[i] i += 1 KmsijT = tuple(KmsijT_list) correctorsListT = tuple(correctorsListT_list) print('solve the system') KFull = pglod.assembleMsStiffnessMatrix(world, patchT, KmsijT) MFull = fem.assemblePatchMatrix(NFine, world.MLocFine) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basisCorrectors = pglod.assembleBasisCorrectors(world, patchT, correctorsListT) modifiedBasis = basis - basisCorrectors bFull = MFull * f_trans bFull = basis.T * bFull uFull, _ = pglod.solve(world, KFull, bFull, boundaryConditions) uLodFine = modifiedBasis * uFull uLodFine_METHOD = uLodFine newErrorFine = np.sqrt( np.dot(uLodFine - uFineFull_trans, AFine_trans * (uLodFine - uFineFull_trans))) print('Method error: {}'.format(newErrorFine)) print('update all correctors') patchT_irrelevant, correctorsListT, KmsijT, csiTNew = zip( *map(UpdateCorrectors, range(world.NtCoarse))) print('solve the system') KFull = pglod.assembleMsStiffnessMatrix(world, patchT, KmsijT) MFull = fem.assemblePatchMatrix(NFine, world.MLocFine) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basisCorrectors = pglod.assembleBasisCorrectors(world, patchT, correctorsListT) modifiedBasis = basis - basisCorrectors bFull = MFull * f_trans bFull = basis.T * bFull uFull, _ = pglod.solve(world, KFull, bFull, boundaryConditions) uLodFine = modifiedBasis * uFull newErrorFine = np.sqrt( np.dot(uLodFine - uFineFull_trans, AFine_trans * (uLodFine - uFineFull_trans))) print('Exact LOD error: {}'.format(newErrorFine)) return uLodFine_METHOD, uLodFine, uFineFull_pert, MFine
def test_1d(self): # Example from Peterseim, Variational Multiscale Stabilization and the Exponential Decay of correctors, p. 2 # Two modifications: A with minus and u(here) = 1/4*u(paper). NFine = np.array([3200]) NpFine = np.prod(NFine + 1) NList = [10, 20, 40, 80, 160] epsilon = 1024. / NFine epsilon = 1. / 320 k = 2 pi = np.pi xt = util.tCoordinates(NFine).flatten() xp = util.pCoordinates(NFine).flatten() #aFine = (2 + np.cos(2*pi*xt/epsilon))**(-1) aFine = (2 - np.cos(2 * pi * xt / epsilon))**(-1) uSol = 4 * (xp - xp**2) - 4 * epsilon * ( 1 / (4 * pi) * np.sin(2 * pi * xp / epsilon) - 1 / (2 * pi) * xp * np.sin(2 * pi * xp / epsilon) - epsilon / (4 * pi**2) * np.cos(2 * pi * xp / epsilon) + epsilon / (4 * pi**2)) uSol = uSol / 4 previousErrorCoarse = np.inf previousErrorFine = np.inf for N in NList: NWorldCoarse = np.array([N]) NCoarseElement = NFine / NWorldCoarse boundaryConditions = np.array([[0, 0]]) world = World(NWorldCoarse, NCoarseElement, boundaryConditions) xpCoarse = util.pCoordinates(NWorldCoarse).flatten() NpCoarse = np.prod(NWorldCoarse + 1) IPatchGenerator = lambda i, N: interp.L2ProjectionPatchMatrix( i, N, NWorldCoarse, NCoarseElement, boundaryConditions) aCoef = coef.coefficientFine(NWorldCoarse, NCoarseElement, aFine) pglod = pg.PetrovGalerkinLOD(world, k, IPatchGenerator, 0) pglod.updateCorrectors(aCoef, clearFineQuantities=False) KFull = pglod.assembleMsStiffnessMatrix() MFull = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) free = util.interiorpIndexMap(NWorldCoarse) f = np.ones(NpCoarse) bFull = MFull * f KFree = KFull[free][:, free] bFree = bFull[free] xFree = sparse.linalg.spsolve(KFree, bFree) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basisCorrectors = pglod.assembleBasisCorrectors() modifiedBasis = basis - basisCorrectors xFull = np.zeros(NpCoarse) xFull[free] = xFree uLodCoarse = basis * xFull uLodFine = modifiedBasis * xFull AFine = fem.assemblePatchMatrix(NFine, world.ALocFine, aFine) MFine = fem.assemblePatchMatrix(NFine, world.MLocFine) newErrorCoarse = np.sqrt( np.dot(uSol - uLodCoarse, MFine * (uSol - uLodCoarse))) newErrorFine = np.sqrt( np.dot(uSol - uLodFine, AFine * (uSol - uLodFine))) self.assertTrue(newErrorCoarse < previousErrorCoarse) self.assertTrue(newErrorFine < previousErrorFine)
def result(pglod, world, A, R, f, k, String): print(("-------------- " + String + " ---------------")) NWorldFine = world.NWorldFine NWorldCoarse = world.NWorldCoarse NCoarseElement = world.NCoarseElement boundaryConditions = world.boundaryConditions NpFine = np.prod(NWorldFine + 1) NpCoarse = np.prod(NWorldCoarse + 1) # new Coefficient ANew = R.flatten() Anew = coef.coefficientFine(NWorldCoarse, NCoarseElement, ANew) start_solver = timeit.default_timer() # reference solution f_fine = np.ones(NpFine) uFineFem, AFine, MFine = femsolver.solveFine(world, ANew, f_fine, None, boundaryConditions) print(('Runtime: it took {} sec to compute the reference solution'.format( timeit.default_timer() - start_solver))) start_solve_system = timeit.default_timer() # worst solution KFull = pglod.assembleMsStiffnessMatrix() MFull = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) free = util.interiorpIndexMap(NWorldCoarse) bFull = MFull * f KFree = KFull[free][:, free] bFree = bFull[free] xFree = sparse.linalg.spsolve(KFree, bFree) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basisCorrectors = pglod.assembleBasisCorrectors() modifiedBasis = basis - basisCorrectors xFull = np.zeros(NpCoarse) xFull[free] = xFree uCoarse = xFull uLodFine = modifiedBasis * xFull print(('Runtime: It took {} sec to apply LOD with given correctors'.format( timeit.default_timer() - start_solve_system))) uLodFineWorst = uLodFine # energy error errorworst = np.sqrt( np.dot(uFineFem - uLodFineWorst, AFine * (uFineFem - uLodFineWorst))) start_runtime = timeit.default_timer() # tolerance = 0 vis, eps = pglod.updateCorrectors(Anew, 0, clearFineQuantities=False, Computing=False) print(('Runtime: It took {} sec to compute the error indicators.'.format( timeit.default_timer() - start_runtime))) PotentialCorrectors = np.sum(vis) elemente = np.arange(np.prod(NWorldCoarse)) # identify tolerances epsnozero = [x for x in eps if x != 0] assert (np.size(epsnozero) != 0) mini = np.min(epsnozero) minilog = int(round(np.log10(mini) - 0.49)) epsnozero.append(10**(minilog)) ToleranceListcomplete = [] for i in range(0, int(np.size(epsnozero))): ToleranceListcomplete.append(epsnozero[i]) ToleranceListcomplete.sort() ToleranceListcomplete = np.unique(ToleranceListcomplete) # with tolerance errorplotinfo = [] tolerancesafe = [] errorBest = [] errorWorst = [] recomputefractionsafe = [] recomputefraction = 0 Correctors = 0 runtime = [] total_time = 0 leng = np.size(ToleranceListcomplete) for k in range(leng - 1, -1, -1): tol = ToleranceListcomplete[k] print( (" --- " + str(-k + leng) + "/" + str(leng) + " --- Tolerance: " + str(round(tol, 5)) + " in " + String + " ---- ")) start_runtime = timeit.default_timer() vistol, time_to_compute = pglod.updateCorrectors( Anew, tol, clearFineQuantities=False, Testing=True, runtime=True) total_time += timeit.default_timer() - start_runtime - time_to_compute runtime.append(total_time) Correctors += np.sum(vistol) recomputefraction += float(np.sum(vistol)) / PotentialCorrectors * 100 recomputefractionsafe.append(recomputefraction) KFull = pglod.assembleMsStiffnessMatrix() MFull = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) free = util.interiorpIndexMap(NWorldCoarse) bFull = MFull * f KFree = KFull[free][:, free] bFree = bFull[free] xFree = sparse.linalg.spsolve(KFree, bFree) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basisCorrectors = pglod.assembleBasisCorrectors() modifiedBasis = basis - basisCorrectors xFull = np.zeros(NpCoarse) xFull[free] = xFree uCoarse = xFull uLodFine = modifiedBasis * xFull # energy error errortol = np.sqrt( np.dot(uFineFem - uLodFine, AFine * (uFineFem - uLodFine))) errorplotinfo.append(errortol) tolerancesafe.append(tol) # 100% updating uLodFinebest = uLodFine errorbest = np.sqrt( np.dot(uFineFem - uLodFinebest, AFine * (uFineFem - uLodFinebest))) print(('Runtime: Total time of updating: {} sec.'.format(total_time))) for k in range(leng - 1, -1, -1): errorBest.append(errorbest) errorWorst.append(errorworst) return vis, eps, PotentialCorrectors, recomputefractionsafe, errorplotinfo, errorWorst, errorBest, runtime
def helmholtz_nonlinear_adaptive(mapper, fineLvl, coarseLvl, maxit): fineExp = fineLvl NFine = np.array([2**fineLvl, 2**fineLvl]) NpFine = np.prod(NFine + 1) N = 2**coarseLvl tolList = [2.0, 1.0, 0.5, 0.25, 0.125, 0.0625, 0.] ell = 2 # localization parameter k = 15. # wavenumber maxit_Fine = 200 xt = util.tCoordinates(NFine) xp = util.pCoordinates(NFine) # multiscale coefficients on the scale NFine-2 np.random.seed(444) sizeK = np.size(xt[:, 0]) nFine = NFine[0] # determine domain D_eps = supp(1-n) = supp(1-A) (all equal for the moment) indicesIn = (xt[:, 0] > 0.15) & (xt[:, 0] < 0.85) & (xt[:, 1] > 0.15) & ( xt[:, 1] < 0.85) indicesInEps = (xt[:, 0] > 0.15) & (xt[:, 0] < 0.85) & ( xt[:, 1] > 0.15) & (xt[:, 1] < 0.85) # coefficients aFine = np.ones(xt.shape[0]) cn = .05 # lower bound on n Cn = 1. # upper bound on n nEpsPro = coeffi(xt[:, 0], xt[:, 1], fineLvl) k2Fine = k**2 * np.ones(xt.shape[0]) k2Fine[indicesIn] = k**2 * ((Cn - cn) * nEpsPro[indicesIn] + cn) kFine = k * np.ones(xt.shape[0]) Ceps = 0.3 # upper bound on eps (lower bound is 0) epsEpsPro = np.ones(sizeK) epsFine = np.zeros(xt.shape[0]) epsFine[indicesInEps] = Ceps * epsEpsPro[indicesInEps] # 0 OR Ceps plotC = np.ones(sizeK) plotC[indicesIn] = nEpsPro[indicesIn] drawCoefficient(NFine, plotC) xC = xp[:, 0] yC = xp[:, 1] # define right-hand side and boundary condition def funcF(x, y): res = 100 * np.ones(x.shape, dtype='complex128') return res f = funcF(xC, yC) # reference solution uSol = np.zeros(NpFine, dtype='complex128') # boundary conditions boundaryConditions = np.array([[1, 1], [1, 1]]) worldFine = World(NFine, np.array([1, 1]), boundaryConditions) # fine matrices BdFineFEM = fem.assemblePatchBoundaryMatrix( NFine, fem.localBoundaryMassMatrixGetter(NFine)) MFineFEM = fem.assemblePatchMatrix(NFine, fem.localMassMatrix(NFine)) KFineFEM = fem.assemblePatchMatrix( NFine, fem.localStiffnessMatrix(NFine)) # , aFine) kBdFine = fem.assemblePatchBoundaryMatrix( NFine, fem.localBoundaryMassMatrixGetter(NFine), kFine) KFine = fem.assemblePatchMatrix(NFine, fem.localStiffnessMatrix(NFine), aFine) print('***computing reference solution***') uOldFine = np.zeros(NpFine, dtype='complex128') for it in np.arange(maxit_Fine): print('-- itFine = %d' % it) knonlinUpreFine = np.abs(uOldFine) knonlinUFine = func.evaluateCQ1(NFine, knonlinUpreFine, xt) k2FineUfine = np.copy(k2Fine) k2FineUfine[indicesInEps] *= ( 1. + epsFine[indicesInEps] * knonlinUFine[indicesInEps]**2 ) # full coefficient, including nonlinearity k2MFine = fem.assemblePatchMatrix( NFine, fem.localMassMatrix(NFine), k2FineUfine) # weighted mass matrix, updated in every iteration nodesFine = np.arange(worldFine.NpFine) fixFine = util.boundarypIndexMap(NFine, boundaryConditions == 0) freeFine = np.setdiff1d(nodesFine, fixFine) # right-hand side fhQuad = MFineFEM * f # fine system lhsh = KFine[freeFine][:, freeFine] - k2MFine[ freeFine][:, freeFine] + 1j * kBdFine[freeFine][:, freeFine] rhsh = fhQuad[freeFine] xFreeFine = sparse.linalg.spsolve(lhsh, rhsh) xFullFine = np.zeros(worldFine.NpFine, dtype='complex128') xFullFine[freeFine] = xFreeFine uOldFine = np.copy(xFullFine) # residual - used as stopping criterion knonlinU = np.abs(uOldFine) knonlinUFineIt = func.evaluateCQ1(NFine, knonlinU, xt) k2FineUfineIt = np.copy(k2Fine) k2FineUfineIt[indicesInEps] *= ( 1. + epsFine[indicesInEps] * knonlinUFineIt[indicesInEps]**2 ) # update full coefficient, including nonlinearity k2MFineIt = fem.assemblePatchMatrix(NFine, fem.localMassMatrix(NFine), k2FineUfineIt) Ares = KFine - k2MFineIt + 1j * kBdFine residual = np.linalg.norm(Ares * xFullFine - fhQuad) / np.linalg.norm( Ares * xFullFine) print('---- residual = %.4e' % residual) if residual < 1e-12: break # stopping criterion uSol = xFullFine # final fine reference solution print('***reference solution computed***\n') counter = 0 # for figures print('***computing multiscale approximations***') relErrEnergy = np.zeros([len(tolList), maxit]) for tol in tolList: counter += 1 print('H = %.4e, tol = %.4e' % (1. / N, tol)) NWorldCoarse = np.array([N, N]) NCoarseElement = NFine // NWorldCoarse world = World(NWorldCoarse, NCoarseElement, boundaryConditions) NpCoarse = np.prod(NWorldCoarse + 1) uOldUps = np.zeros(NpFine, dtype='complex128') for it in np.arange(maxit): print('-- it = %d:' % it) knonlinUpre = np.abs(uOldUps) knonlinU = func.evaluateCQ1(NFine, knonlinUpre, xt) k2FineU = np.copy(k2Fine) k2FineU[indicesInEps] *= ( 1. + epsFine[indicesInEps] * knonlinU[indicesInEps]**2) print('---- starting computation of correctors') def computeLocalContribution(TInd): patch = Patch(world, ell, TInd) IPatch = lambda: interp.L2ProjectionPatchMatrix( patch, boundaryConditions) aPatch = lambda: coef.localizeCoefficient(patch, aFine) kPatch = lambda: coef.localizeCoefficient(patch, kFine) k2Patch = lambda: coef.localizeCoefficient(patch, k2FineU) correctorsList = lod.computeBasisCorrectors_helmholtz( patch, IPatch, aPatch, kPatch, k2Patch) # adapted for Helmholtz setting csi = lod.computeBasisCoarseQuantities_helmholtz( patch, correctorsList, aPatch, kPatch, k2Patch) # adapted for Helmholtz setting return patch, correctorsList, csi.Kmsij, csi.Mmsij, csi.Bdmsij, csi.muTPrime def computeIndicators(TInd): k2FineUPatch = lambda: coef.localizeCoefficient( patchT[TInd], k2FineU) k2FineUOldPatch = lambda: coef.localizeCoefficient( patchT[TInd], k2FineUOld) E_vh = lod.computeErrorIndicatorCoarse_helmholtz( patchT[TInd], muTPrime[TInd], k2FineUOldPatch, k2FineUPatch) return E_vh def UpdateCorrectors(TInd): patch = Patch(world, ell, TInd) IPatch = lambda: interp.L2ProjectionPatchMatrix( patch, boundaryConditions) aPatch = lambda: coef.localizeCoefficient(patch, aFine) kPatch = lambda: coef.localizeCoefficient(patch, kFine) k2Patch = lambda: coef.localizeCoefficient(patch, k2FineU) correctorsList = lod.computeBasisCorrectors_helmholtz( patch, IPatch, aPatch, kPatch, k2Patch) csi = lod.computeBasisCoarseQuantities_helmholtz( patch, correctorsList, aPatch, kPatch, k2Patch) # adapted for Helmholtz setting return patch, correctorsList, csi.Kmsij, csi.Mmsij, csi.Bdmsij, csi.muTPrime def UpdateElements(tol, E, Kmsij_old, Mmsij_old, Bdmsij_old, correctors_old, mu_old): print('---- apply tolerance') Elements_to_be_updated = [] for (i, eps) in E.items(): if eps > tol * k**2: Elements_to_be_updated.append(i) if len(E) > 0: print( '---- percentage of non-zero element correctors to be updated: %.4f' % (100 * np.size(Elements_to_be_updated) / len(E)), flush=True) print( '---- total percentage of element correctors to be updated: %.4f' % (100 * np.size(Elements_to_be_updated) / len(mu_old)), flush=True) print('---- update local contributions') KmsijT_list = list(np.copy(Kmsij_old)) MmsijT_list = list(np.copy(Mmsij_old)) BdmsijT_list = list(np.copy(Bdmsij_old)) muT_list = np.copy(mu_old) for T in np.setdiff1d(range(world.NtCoarse), Elements_to_be_updated): patch = Patch(world, ell, T) aPatch = lambda: coef.localizeCoefficient(patch, aFine) kPatch = lambda: coef.localizeCoefficient(patch, kFine) k2Patch = lambda: coef.localizeCoefficient(patch, k2FineU) csi = lod.computeBasisCoarseQuantities_helmholtz( patch, correctors_old[T], aPatch, kPatch, k2Patch) KmsijT_list[T] = csi.Kmsij MmsijT_list[T] = csi.Mmsij BdmsijT_list[T] = csi.Bdmsij muT_list[T] = csi.muTPrime if np.size(Elements_to_be_updated) != 0: #print('---- update correctors') patchT_irrelevant, correctorsListTNew, KmsijTNew, MmsijTNew, BdmsijTNew, muTPrimeNew = zip( *mapper(UpdateCorrectors, Elements_to_be_updated)) #print('---- update correctorsList') correctorsListT_list = list(np.copy(correctors_old)) i = 0 for T in Elements_to_be_updated: KmsijT_list[T] = KmsijTNew[i] correctorsListT_list[T] = correctorsListTNew[i] MmsijT_list[T] = MmsijTNew[i] BdmsijT_list[T] = BdmsijTNew[i] muT_list[T] = muTPrimeNew[i] i += 1 KmsijT = tuple(KmsijT_list) correctorsListT = tuple(correctorsListT_list) MmsijT = tuple(MmsijT_list) BdmsijT = tuple(BdmsijT_list) muTPrime = tuple(muT_list) return correctorsListT, KmsijT, MmsijT, BdmsijT, muTPrime else: KmsijT = tuple(KmsijT_list) MmsijT = tuple(MmsijT_list) BdmsijT = tuple(BdmsijT_list) muTPrime = tuple(muT_list) return correctors_old, KmsijT, MmsijT, BdmsijT, muTPrime if it == 0: patchT, correctorsListT, KmsijT, MmsijT, BdmsijT, muTPrime = zip( *mapper(computeLocalContribution, range(world.NtCoarse))) else: E_vh = list(mapper(computeIndicators, range(world.NtCoarse))) print( '---- maximal value error estimator for basis correctors {}' .format(np.max(E_vh))) E = {i: E_vh[i] for i in range(np.size(E_vh)) if E_vh[i] > 0} # loop over elements with possible recomputation of correctors correctorsListT, KmsijT, MmsijT, BdmsijT, muTPrime = UpdateElements( tol, E, KmsijT, MmsijT, BdmsijT, correctorsListT, muTPrime) # tol scaled by maximal error indicator print('---- finished computation of correctors') KLOD = pglod.assembleMsStiffnessMatrix( world, patchT, KmsijT) # ms stiffness matrix k2MLOD = pglod.assembleMsStiffnessMatrix(world, patchT, MmsijT) # ms mass matrix kBdLOD = pglod.assembleMsStiffnessMatrix( world, patchT, BdmsijT) # ms boundary matrix MFEM = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) BdFEM = fem.assemblePatchBoundaryMatrix( NWorldCoarse, fem.localBoundaryMassMatrixGetter(NWorldCoarse)) print('---- coarse matrices assembled') nodes = np.arange(world.NpCoarse) fix = util.boundarypIndexMap(NWorldCoarse, boundaryConditions == 0) free = np.setdiff1d(nodes, fix) assert (nodes.all() == free.all()) # compute global interpolation matrix patchGlobal = Patch(world, NFine[0] + 2, 0) IH = interp.L2ProjectionPatchMatrix(patchGlobal, boundaryConditions) assert (IH.shape[0] == NpCoarse) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) fHQuad = basis.T * MFineFEM * f print('---- solving coarse system') # coarse system lhsH = KLOD[free][:, free] - k2MLOD[ free][:, free] + 1j * kBdLOD[free][:, free] rhsH = fHQuad[free] xFree = sparse.linalg.spsolve(lhsH, rhsH) basisCorrectors = pglod.assembleBasisCorrectors( world, patchT, correctorsListT) modifiedBasis = basis - basisCorrectors xFull = np.zeros(world.NpCoarse, dtype='complex128') xFull[free] = xFree uLodCoarse = basis * xFull uLodFine = modifiedBasis * xFull uOldUps = np.copy(uLodFine) k2FineUOld = np.copy(k2FineU) Err = np.sqrt( np.dot((uSol - uLodFine).conj(), KFineFEM * (uSol - uLodFine)) + k**2 * np.dot((uSol - uLodFine).conj(), MFineFEM * (uSol - uLodFine))) ErrEnergy = Err / np.sqrt( np.dot((uSol).conj(), KFineFEM * (uSol)) + k**2 * np.dot((uSol).conj(), MFineFEM * (uSol))) print('---- ', np.abs(ErrEnergy), '\n***********************************************') # save errors in arrays relErrEnergy[counter - 1, it] = ErrEnergy print('\n') its = np.arange(1, maxit + 1) plt.figure(1) plt.title( 'Relative energy errors w.r.t iterations for different tolerances - Ex 3' ) plt.plot(its, relErrEnergy[0, :], 'x--', color='black', label='tol = 2') plt.plot(its, relErrEnergy[1, :], 'x-', color='blue', label='tol = 1') plt.plot(its, relErrEnergy[2, :], 'x-', color='green', label='tol = 0.5') plt.plot(its, relErrEnergy[3, :], 'x-', color='orange', label='tol = 0.25') plt.plot(its, relErrEnergy[4, :], 'x-', color='red', label='tol = 0.125') plt.plot(its, relErrEnergy[5, :], 'x-', color='magenta', label='tol = 0.0625') plt.plot(its, relErrEnergy[6, :], 'x--', color='black', label='tol = 0') plt.yscale('log') plt.legend() plt.show()
def StartAlgorithm(self): assert (self.init) # only start the algorithm once # in case not every element is affected, the percentage would be missleading. eps_size = np.size(self.E_vh) self.E_vh = { i: self.E_vh[i] for i in range(np.size(self.E_vh)) if self.E_vh[i] > 0 } full_percentage = len(self.E_vh) / eps_size world = self.world print('starting algorithm ...... ') TOLt = [] to_be_updatedT = [] energy_errorT = [] rel_energy_errorT = [] tmp_errorT = [] offset = [] TOL = 100 # not relevant for i in range(len(self.E_vh) + 1): if self.init: pass else: offset = self.UpdateNextElement(offset, Printing=False) if self.init: to_be_updated = np.size(offset) / len(self.E_vh) * 100 to_be_updatedT.append(to_be_updated) pass else: to_be_updated = np.size(offset) / len(self.E_vh) * 100 to_be_updatedT.append(to_be_updated * full_percentage) KFull = pglod.assembleMsStiffnessMatrix(world, self.patchT, self.KmsijT) RFull = pglod.assemblePatchFunction(world, self.patchT, self.RmsijT) Rf = pglod.assemblePatchFunction(world, self.patchT, self.correctorsRhsT) basis = fem.assembleProlongationMatrix(world.NWorldCoarse, world.NCoarseElement) bFull = basis.T * self.MFull * self.f_trans - RFull basisCorrectors = pglod.assembleBasisCorrectors( world, self.patchT, self.correctorsListT) modifiedBasis = basis - basisCorrectors uFull, _ = pglod.solve(world, KFull, bFull, self.boundaryConditions) uLodFine = modifiedBasis * uFull uLodFine += Rf uFineFull_trans_LOD = uLodFine if self.init: uFineFull_trans_LOD_old = uLodFine energy_norm = np.sqrt( np.dot(uFineFull_trans_LOD, self.AFine_trans * uFineFull_trans_LOD)) # tmp_error tmp_energy_error = np.sqrt( np.dot((uFineFull_trans_LOD - uFineFull_trans_LOD_old), self.AFine_trans * (uFineFull_trans_LOD - uFineFull_trans_LOD_old))) # actual error if self.compare_with_best_LOD: energy_error = np.sqrt( np.dot((uFineFull_trans_LOD - self.u_best_LOD), self.AFine_trans * (uFineFull_trans_LOD - self.u_best_LOD))) else: energy_error = np.sqrt( np.dot((uFineFull_trans_LOD - self.uFineFull_trans), self.AFine_trans * (uFineFull_trans_LOD - self.uFineFull_trans))) uFineFull_trans_LOD_old = uFineFull_trans_LOD if self.init: self.init = 0 print( ' step({:3d}/{}) T: {} updates: {:7.3f}%, energy error: {:f}, tmp_error: {:f}, relative energy error: {:f}' .format(i, len(self.E_vh), ' - ', to_be_updated * full_percentage, energy_error, tmp_energy_error, energy_error / energy_norm)) else: print( ' step({:3d}/{}) T: {:3d} updates: {:7.3f}%, energy error: {:f}, tmp_error: {:f}, relative energy error: {:f}' .format(i, len(self.E_vh), offset[-1], to_be_updated * full_percentage, energy_error, tmp_energy_error, energy_error / energy_norm)) rel_energy_errorT.append(energy_error / energy_norm) energy_errorT.append(energy_error) tmp_errorT.append(tmp_energy_error) return to_be_updatedT, energy_errorT, tmp_errorT, rel_energy_errorT, TOLt, uFineFull_trans_LOD
def StartAlgorithm(self): assert (self.init) # only start the algorithm once # in case not every element is affected, the percentage would be missleading. eps_size = np.size(self.E_vh) self.E_vh = { i: self.E_vh[i] for i in range(np.size(self.E_vh)) if self.E_vh[i] > 0 } list = [v for v in self.E_vh.values()] list.append(0) tols = np.sort(list)[::-1] eps_size_f = np.size(self.E_vh) self.E_f = { i: self.E_f[i] for i in range(np.size(self.E_f)) if self.E_f[i] > 0 } list_f = [v for v in self.E_f.values()] list_f.append(0) tols_f = np.sort(list)[::-1] # make sure we only update one element all the time for i in range(1, np.size(tols)): if tols[i] == tols[i - 1]: tols[i] -= 1e-7 for i in range(1, np.size(tols_f)): if tols_f[i] == tols_f[i - 1]: tols_f[i] -= 1e-7 full_percentage = len(self.E_vh) / eps_size full_percentage_f = len(self.E_f) / eps_size_f world = self.world print('starting algorithm ...... ') TOLt = [] to_be_updatedT = [] energy_errorT = [] rel_energy_errorT = [] tmp_errorT = [] offset = [] TOL = 100 # not relevant for i in range(np.size(tols)): if TOL == 0: pass else: TOL = tols[i] TOLt.append(TOL) offset = self.UpdateNextElement(TOL, offset, Printing=False) if self.init: to_be_updated = np.size(offset) / len(self.E_vh) * 100 to_be_updatedT.append(to_be_updated) pass else: to_be_updated = np.size(offset) / len(self.E_vh) * 100 to_be_updatedT.append(to_be_updated * full_percentage) KFull = pglod.assembleMsStiffnessMatrix(world, self.patchT, self.KmsijT) RFull = pglod.assemblePatchFunction(world, self.patchT, self.RmsijT) Rf = pglod.assemblePatchFunction(world, self.patchT, self.correctorsRhsT) basis = fem.assembleProlongationMatrix(world.NWorldCoarse, world.NCoarseElement) bFull = basis.T * self.MFull * self.f_trans - RFull basisCorrectors = pglod.assembleBasisCorrectors( world, self.patchT, self.correctorsListT) modifiedBasis = basis - basisCorrectors uFull, _ = pglod.solve(world, KFull, bFull, self.boundaryConditions) uLodFine = modifiedBasis * uFull uLodFine += Rf uFineFull_trans_LOD = uLodFine if self.init: self.init = 0 uFineFull_trans_LOD_old = uLodFine energy_norm = np.sqrt( np.dot(uFineFull_trans_LOD, self.AFine_trans * uFineFull_trans_LOD)) # tmp_error tmp_energy_error = np.sqrt( np.dot((uFineFull_trans_LOD - uFineFull_trans_LOD_old), self.AFine_trans * (uFineFull_trans_LOD - uFineFull_trans_LOD_old))) # actual error if self.compare_with_best_LOD: energy_error = np.sqrt( np.dot((uFineFull_trans_LOD - self.u_best_LOD), self.AFine_trans * (uFineFull_trans_LOD - self.u_best_LOD))) else: energy_error = np.sqrt( np.dot((uFineFull_trans_LOD - self.uFineFull_trans), self.AFine_trans * (uFineFull_trans_LOD - self.uFineFull_trans))) uFineFull_trans_LOD_old = uFineFull_trans_LOD print( ' step({:3d}/{}) TOL: {:f}, updates: {:7.3f}%, energy error: {:f}, tmp_error: {:f}, relative energy error: {:f}' .format(i, np.size(tols), TOL, to_be_updated * full_percentage, energy_error, tmp_energy_error, energy_error / energy_norm)) rel_energy_errorT.append(energy_error / energy_norm) energy_errorT.append(energy_error) tmp_errorT.append(tmp_energy_error) if TOL == 0: # stop now break return to_be_updatedT, energy_errorT, tmp_errorT, rel_energy_errorT, TOLt, uFineFull_trans_LOD
def StartAlgorithm(self): assert (self.init) # only start the algorithm once # in case not every element is affected, the percentage would be missleading. eps_size = np.size(self.E_vh) self.E_vh = { i: self.E_vh[i] for i in range(np.size(self.E_vh)) if self.E_vh[i] > 0 } full_percentage = len(self.E_vh) / eps_size world = self.world print('starting algorithm ...... ') TOL = self.StartingTolerance TOLt = [] to_be_updatedT = [] energy_errorT = [] rel_energy_errorT = [] tmp_errorT = [] offset = [] continue_computing = 1 while continue_computing: TOLt.append(TOL) offset, computed = self.UpdateElements(TOL, offset, Printing=False) if computed: pass else: if self.init: pass else: to_be_updated = np.size(offset) / len(self.E_vh) * 100 to_be_updatedT.append(to_be_updated * full_percentage) energy_errorT.append(energy_error) tmp_errorT.append(old_tmp_energy_error) if np.size(offset) / len(self.E_vh) == 1: print(' every corrector has been updated') continue_computing = 0 continue else: print(' skipping TOL {}'.format(TOL)) TOL *= 3 / 4. continue to_be_updated = np.size(offset) / len(self.E_vh) * 100 to_be_updatedT.append(to_be_updated * full_percentage) KFull = pglod.assembleMsStiffnessMatrix(world, self.patchT, self.KmsijT) RFull = pglod.assemblePatchFunction(world, self.patchT, self.RmsijT) Rf = pglod.assemblePatchFunction(world, self.patchT, self.correctorsRhsT) basis = fem.assembleProlongationMatrix(world.NWorldCoarse, world.NCoarseElement) bFull = basis.T * self.MFull * self.f_trans - RFull basisCorrectors = pglod.assembleBasisCorrectors( world, self.patchT, self.correctorsListT) modifiedBasis = basis - basisCorrectors uFull, _ = pglod.solve(world, KFull, bFull, self.boundaryConditions) uLodFine = modifiedBasis * uFull uLodFine += Rf uFineFull_trans_LOD = uLodFine if self.init: uFineFull_trans_LOD_old = uLodFine self.init = 0 energy_norm = np.sqrt( np.dot(uFineFull_trans_LOD, self.AFine_trans * uFineFull_trans_LOD)) # tmp_error tmp_energy_error = np.sqrt( np.dot((uFineFull_trans_LOD - uFineFull_trans_LOD_old), self.AFine_trans * (uFineFull_trans_LOD - uFineFull_trans_LOD_old))) old_tmp_energy_error = tmp_energy_error # actual error energy_error = np.sqrt( np.dot((uFineFull_trans_LOD - self.uFineFull_trans), self.AFine_trans * (uFineFull_trans_LOD - self.uFineFull_trans))) uFineFull_trans_LOD_old = uFineFull_trans_LOD print( ' TOL: {:f}, updates: {:7.3f}%, energy error: {:f}, tmp_error: {:f}, relative energy error: {:f}' .format(TOL, to_be_updated * full_percentage, energy_error, tmp_energy_error, energy_error / energy_norm)) rel_energy_errorT.append(energy_error / energy_norm) energy_errorT.append(energy_error) tmp_errorT.append(tmp_energy_error) if tmp_energy_error > 1e-5: TOL *= 3 / 4. else: if int(np.size(offset) / len(self.E_vh)) == 1: if computed: print(' stop computing') continue_computing = 0 return to_be_updatedT, energy_errorT, tmp_errorT, rel_energy_errorT, TOLt, uFineFull_trans_LOD
def standard_method(world, N, fine, tau, tot_time_steps, k, aFine, bFine, f): # coarse mesh parameters NWorldCoarse = np.array([N, N]) NFine = np.array([fine, fine]) NpFine = np.prod(NFine + 1) NCoarseElement = NFine // NWorldCoarse NWorldFine = world.NWorldCoarse * world.NCoarseElement bc = world.boundaryConditions world = World(NWorldCoarse, NCoarseElement, bc) NpCoarse = np.prod(NWorldCoarse + 1) def IPatchGenerator(i, N): return interp.L2ProjectionPatchMatrix(i, N, NWorldCoarse, NCoarseElement, bc) b_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, bFine) a_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, aFine / tau) # compute basis correctors lod = lod_wave.LodWave(b_coef, world, k, IPatchGenerator, a_coef) lod.compute_basis_correctors() # compute ms basis basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basis_correctors = lod.assembleBasisCorrectors() ms_basis = basis - basis_correctors # compute finescale solution correctors prev_fs_sol = ms_basis fs_solutions_new = [] for i in range(tot_time_steps): print('Calculating correction at N = %d, i = %d' % (N, i)) # solve localized system lod = lod_wave.LodWave(b_coef, world, k, IPatchGenerator, a_coef, prev_fs_sol) lod.solve_fs_system(localized=True) # store sparse solution prev_fs_sol = sparse.csc_matrix(np.array(np.column_stack(lod.fs_list))) fs_solutions_new.append(prev_fs_sol) # initial value Uo = np.zeros(NpCoarse) # coarse v^(-1) and v^0 V = [Uo] V.append(Uo) # compute ms matrices S = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, aFine) K = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, bFine) M = fem.assemblePatchMatrix(NWorldFine, world.MLocFine) free = util.interiorpIndexMap(NWorldCoarse) SmsFree = (ms_basis.T * S * ms_basis)[free][:, free] KmsFree = (ms_basis.T * K * ms_basis)[free][:, free] MmsFree = (ms_basis.T * M * ms_basis)[free][:, free] # load vector f = np.ones(NpFine) LmsFree = (ms_basis.T * M * f)[free] RmsFreeList = [] for i in range(tot_time_steps): n = i + 1 # linear system A = (1. / (tau ** 2)) * MmsFree + (1. / tau) * SmsFree + KmsFree b = LmsFree + (1. / tau) * SmsFree * V[n][free] + (2. / (tau ** 2)) * MmsFree * V[n][free] \ - (1. / (tau ** 2)) * MmsFree * V[n - 1][free] # store ms matrix R^{ms',h}_{H,i,k} RmsFull = ms_basis.T * S * sparse.csc_matrix(fs_solutions_new[i]) RmsFree = RmsFull[free][:, free] RmsFreeList.append(RmsFree) # add sum to linear system if i != 0: for j in range(i): b += (1. / tau) * RmsFreeList[j] * V[n - 1 - j][free] # solve system VFree = linalg.linSolve(A, b) VFull = np.zeros(NpCoarse) VFull[free] = VFree # append solution for current time step V.append(VFull) VFine = ms_basis * V[-1] WFine = 0 for j in range(tot_time_steps): WFine += sparse.csc_matrix(fs_solutions_new[j]) * V[n - j] return VFine + WFine, ms_basis * Uo
def helmholtz_nonlinear_adaptive(mapper, fineLvl, maxCoarseLvl, maxit): NFine = np.array([2**fineLvl, 2**fineLvl]) NpFine = np.prod(NFine + 1) NList = 2**np.arange(1, maxCoarseLvl + 1) ell = 2 # localization parameter k = 30. # wavenumber maxit_Fine = 250 tol = 0.5 # coupled to maximal error indicator xt = util.tCoordinates(NFine) xp = util.pCoordinates(NFine) # multiscale coefficients on the scale NFine-2 np.random.seed(123) sizeK = np.size(xt[:, 0]) nFine = NFine[0] # determine domain D_eps = supp(1-n) = supp(1-A) (all equal for this experiment) indicesIn = (xt[:, 0] > 0.25) & (xt[:, 0] < 0.75) & (xt[:, 1] > 0.25) & ( xt[:, 1] < 0.75) indicesInEps = (xt[:, 0] > 0.25) & (xt[:, 0] < 0.75) & ( xt[:, 1] > 0.25) & (xt[:, 1] < 0.75) # coefficients cA = .2 # lower bound on A CA = 1. # upper bound on A aEps = np.random.uniform(0, 1, sizeK // 16) aEpsPro = np.zeros(sizeK) for i in range((nFine) // 4): aEpsPro[4 * i * (nFine):4 * (i + 1) * (nFine)] = np.tile( np.repeat(aEps[i * (nFine) // 4:(i + 1) * (nFine) // 4], 4), 4) aFine = np.ones(xt.shape[0]) aFine[indicesIn] = (CA - cA) * aEpsPro[indicesIn] + cA cn = 1. # lower bound on n Cn = 1. # upper bound on n nEps = np.random.uniform(0, 1, sizeK // 16) nEpsPro = np.zeros(sizeK) for i in range((nFine) // 4): nEpsPro[4 * i * (nFine):4 * (i + 1) * (nFine)] = np.tile( np.repeat(nEps[i * (nFine) // 4:(i + 1) * (nFine) // 4], 4), 4) k2Fine = k**2 * np.ones(xt.shape[0]) k2Fine[indicesIn] = k**2 * ((Cn - cn) * nEpsPro[indicesIn] + cn) kFine = k * np.ones(xt.shape[0]) Ceps = .85 # upper bound on eps (lower bound is 0) lvl = 4 epsEps = np.random.randint(2, size=(sizeK // lvl**2)) epsEpsPro = np.zeros(sizeK) for i in range((nFine) // lvl): epsEpsPro[lvl * i * (nFine):lvl * (i + 1) * (nFine)] = np.tile( np.repeat(epsEps[i * (nFine) // lvl:(i + 1) * (nFine) // lvl], lvl), lvl) epsFine = np.zeros(xt.shape[0]) epsFine[indicesInEps] = Ceps * epsEpsPro[indicesInEps] # 0 OR Ceps drawCoefficient(NFine, epsFine) xC = xp[:, 0] yC = xp[:, 1] fact = 100. mult = .8 a = .5 b = .25 k2 = 30. # define right-hand side and boundary condition def funcF(x, y): res = mult * (-np.exp(-1.j * k2 * (a * x - b)) * (2 * a**2 * fact**2 * np.sinh(fact * (a * x - b))**2 / (np.cosh(fact * (a * x - b)) + 1)**3 - a**2 * fact**2 * np.cosh(fact * (a * x - b)) / (np.cosh(fact * (a * x - b)) + 1)**2) + a**2 * k2**2 * np.exp(-1.j * k2 * (a * x - b)) / (np.cosh(fact * (a * x - b)) + 1) - 2.j * a**2 * fact * k2 * np.exp(-1.j * k2 * (a * x - b)) * np.sinh(fact * (a * x - b)) / (np.cosh(fact * (a * x - b)) + 1)**2 - k**2 * np.exp(-1.j * k2 * (a * x - b)) / (np.cosh(fact * (a * x - b)) + 1)) return res f = funcF(xC, yC) g = np.zeros(NpFine, dtype='complex128') # bottom boundary g[0:(NFine[0] + 1)] = mult * 1.j * k * 1. / (np.cosh(fact * (a * xC[0:(NFine[0] + 1)] - b)) + 1) * np.exp( -1.j * k2 * (a * xC[0:(NFine[0] + 1)] - b)) # top boundary g[(NpFine - NFine[0] - 1):] = mult * 1.j * k * 1. / (np.cosh(fact * (a * xC[ (NpFine - NFine[0] - 1):NpFine] - b)) + 1) * np.exp( -1.j * k2 * (a * xC[(NpFine - NFine[0] - 1):NpFine] - b)) # left boundary g[0:(NpFine - NFine[0]):( NFine[0] + 1)] = mult * 1.j * k * np.ones_like(yC[0:(NpFine - NFine[0]):( NFine[0] + 1)]) / (np.cosh(fact * (a * 0 - b)) + 1) * np.exp( -1.j * k2 * (a * 0 - b)) + mult * np.ones_like( yC[0:(NpFine - NFine[0]):(NFine[0] + 1)]) * ( a * 1.j * k2 * np.exp(-1.j * k2 * (a * 0 - b)) / (np.cosh((a * 0 - b) * fact) + 1) + a * fact * np.sinh( (a * 0 - b) * fact) * np.exp(-1.j * k2 * (a * 0 - b)) / (np.cosh((a * 0 - b) * fact) + 1)**2) # right boundary g[NFine[0]:NpFine:( NFine[0] + 1)] = mult * 1.j * k * np.ones_like(yC[NFine[0]:NpFine:( NFine[0] + 1)]) / (np.cosh(fact * (a * 1. - b)) + 1) * np.exp( -1.j * k2 * (a * 1. - b)) - mult * np.ones_like( yC[NFine[0]:NpFine:(NFine[0] + 1)]) * ( a * 1.j * k2 * np.exp(-1.j * k2 * (a * 1. - b)) / (np.cosh( (a * 1. - b) * fact) + 1) + a * fact * np.sinh( (a * 1. - b) * fact) * np.exp(-1.j * k2 * (a * 1. - b)) / (np.cosh((a * 1. - b) * fact) + 1)**2) # reference solution uSol = np.zeros(NpFine, dtype='complex128') # boundary conditions boundaryConditions = np.array([[1, 1], [1, 1]]) # Robin boundary worldFine = World(NFine, np.array([1, 1]), boundaryConditions) # fine matrices BdFineFEM = fem.assemblePatchBoundaryMatrix( NFine, fem.localBoundaryMassMatrixGetter(NFine)) MFineFEM = fem.assemblePatchMatrix(NFine, fem.localMassMatrix(NFine)) KFineFEM = fem.assemblePatchMatrix(NFine, fem.localStiffnessMatrix(NFine)) kBdFine = fem.assemblePatchBoundaryMatrix( NFine, fem.localBoundaryMassMatrixGetter(NFine), kFine) KFine = fem.assemblePatchMatrix(NFine, fem.localStiffnessMatrix(NFine), aFine) # incident beam uInc = mult / (np.cosh(fact * (a * xC - b)) + 1) * np.exp(-1.j * k2 * (a * xC - b)) print('***computing reference solution***') uOldFine = np.zeros(NpFine, dtype='complex128') for it in np.arange(maxit_Fine): print('-- itFine = %d' % it) knonlinUpreFine = np.abs(uOldFine) knonlinUFine = func.evaluateCQ1(NFine, knonlinUpreFine, xt) k2FineUfine = np.copy(k2Fine) k2FineUfine[indicesInEps] *= ( 1. + epsFine[indicesInEps] * knonlinUFine[indicesInEps]**2 ) # full coefficient, including nonlinearity k2MFine = fem.assemblePatchMatrix( NFine, fem.localMassMatrix(NFine), k2FineUfine) # weighted mass matrix, updated in every iteration nodesFine = np.arange(worldFine.NpFine) fixFine = util.boundarypIndexMap(NFine, boundaryConditions == 0) freeFine = np.setdiff1d(nodesFine, fixFine) # right-hand side (including boundary condition) fhQuad = MFineFEM * f + BdFineFEM * g # fine system lhsh = KFine[freeFine][:, freeFine] - k2MFine[ freeFine][:, freeFine] + 1j * kBdFine[freeFine][:, freeFine] rhsh = fhQuad[freeFine] xFreeFine = sparse.linalg.spsolve(lhsh, rhsh) xFullFine = np.zeros(worldFine.NpFine, dtype='complex128') xFullFine[freeFine] = xFreeFine uOldFine = np.copy(xFullFine) # residual - used as stopping criterion knonlinU = np.abs(uOldFine) knonlinUFineIt = func.evaluateCQ1(NFine, knonlinU, xt) k2FineUfineIt = np.copy(k2Fine) k2FineUfineIt[indicesInEps] *= ( 1. + epsFine[indicesInEps] * knonlinUFineIt[indicesInEps]**2 ) # update full coefficient, including nonlinearity k2MFineIt = fem.assemblePatchMatrix(NFine, fem.localMassMatrix(NFine), k2FineUfineIt) Ares = KFine - k2MFineIt + 1j * kBdFine residual = np.linalg.norm(Ares * xFullFine - fhQuad) / np.linalg.norm( Ares * xFullFine) print('---- residual = %.4e' % residual) if residual < 1e-12: break # stopping criterion uSol = xFullFine # final fine reference solution print('***reference solution computed***\n') ###################################################################################### print('***computing multiscale approximations***') relErrEnergy = np.zeros([len(NList), maxit]) counter = 0 for N in NList: counter += 1 print('H = %.4e' % (1. / N)) NWorldCoarse = np.array([N, N]) NCoarseElement = NFine // NWorldCoarse world = World(NWorldCoarse, NCoarseElement, boundaryConditions) NpCoarse = np.prod(NWorldCoarse + 1) uOldUps = np.zeros(NpFine, dtype='complex128') for it in np.arange(maxit): print('-- it = %d:' % it) knonlinUpre = np.abs(uOldUps) knonlinU = func.evaluateCQ1(NFine, knonlinUpre, xt) k2FineU = np.copy(k2Fine) k2FineU[indicesInEps] *= ( 1. + epsFine[indicesInEps] * knonlinU[indicesInEps]**2) print('---- starting computation of correctors') def computeLocalContribution(TInd): patch = Patch(world, ell, TInd) IPatch = lambda: interp.L2ProjectionPatchMatrix( patch, boundaryConditions) aPatch = lambda: coef.localizeCoefficient(patch, aFine) kPatch = lambda: coef.localizeCoefficient(patch, kFine) k2Patch = lambda: coef.localizeCoefficient(patch, k2FineU) correctorsList = lod.computeBasisCorrectors_helmholtz( patch, IPatch, aPatch, kPatch, k2Patch) csi = lod.computeBasisCoarseQuantities_helmholtz( patch, correctorsList, aPatch, kPatch, k2Patch) return patch, correctorsList, csi.Kmsij, csi.Mmsij, csi.Bdmsij, csi.muTPrime def computeIndicators(TInd): k2FineUPatch = lambda: coef.localizeCoefficient( patchT[TInd], k2FineU) k2FineUOldPatch = lambda: coef.localizeCoefficient( patchT[TInd], k2FineUOld) E_vh = lod.computeErrorIndicatorCoarse_helmholtz( patchT[TInd], muTPrime[TInd], k2FineUOldPatch, k2FineUPatch) return E_vh def UpdateCorrectors(TInd): patch = Patch(world, ell, TInd) IPatch = lambda: interp.L2ProjectionPatchMatrix( patch, boundaryConditions) aPatch = lambda: coef.localizeCoefficient(patch, aFine) kPatch = lambda: coef.localizeCoefficient(patch, kFine) k2Patch = lambda: coef.localizeCoefficient(patch, k2FineU) correctorsList = lod.computeBasisCorrectors_helmholtz( patch, IPatch, aPatch, kPatch, k2Patch) csi = lod.computeBasisCoarseQuantities_helmholtz( patch, correctorsList, aPatch, kPatch, k2Patch) return patch, correctorsList, csi.Kmsij, csi.Mmsij, csi.Bdmsij, csi.muTPrime def UpdateElements(tol, E, Kmsij_old, Mmsij_old, Bdmsij_old, correctors_old, mu_old): print('---- apply tolerance') Elements_to_be_updated = [] for (i, eps) in E.items(): if eps > tol: Elements_to_be_updated.append(i) if len(E) > 0: print( '---- total percentage of element correctors to be updated: %.4f' % (100 * np.size(Elements_to_be_updated) / len(mu_old)), flush=True) print('---- update local contributions') KmsijT_list = list(np.copy(Kmsij_old)) MmsijT_list = list(np.copy(Mmsij_old)) BdmsijT_list = list(np.copy(Bdmsij_old)) muT_list = np.copy(mu_old) for T in np.setdiff1d(range(world.NtCoarse), Elements_to_be_updated): patch = Patch(world, ell, T) aPatch = lambda: coef.localizeCoefficient(patch, aFine) kPatch = lambda: coef.localizeCoefficient(patch, kFine) k2Patch = lambda: coef.localizeCoefficient(patch, k2FineU) csi = lod.computeBasisCoarseQuantities_helmholtz( patch, correctors_old[T], aPatch, kPatch, k2Patch) KmsijT_list[T] = csi.Kmsij MmsijT_list[T] = csi.Mmsij BdmsijT_list[T] = csi.Bdmsij muT_list[T] = csi.muTPrime if np.size(Elements_to_be_updated) != 0: #print('---- update correctors') patchT_irrelevant, correctorsListTNew, KmsijTNew, MmsijTNew, BdmsijTNew, muTPrimeNew = zip( *mapper(UpdateCorrectors, Elements_to_be_updated)) #print('---- update correctorsList') correctorsListT_list = list(np.copy(correctors_old)) i = 0 for T in Elements_to_be_updated: KmsijT_list[T] = KmsijTNew[i] correctorsListT_list[T] = correctorsListTNew[i] MmsijT_list[T] = MmsijTNew[i] BdmsijT_list[T] = BdmsijTNew[i] muT_list[T] = muTPrimeNew[i] i += 1 KmsijT = tuple(KmsijT_list) correctorsListT = tuple(correctorsListT_list) MmsijT = tuple(MmsijT_list) BdmsijT = tuple(BdmsijT_list) muTPrime = tuple(muT_list) return correctorsListT, KmsijT, MmsijT, BdmsijT, muTPrime else: KmsijT = tuple(KmsijT_list) MmsijT = tuple(MmsijT_list) BdmsijT = tuple(BdmsijT_list) muTPrime = tuple(muT_list) return correctors_old, KmsijT, MmsijT, BdmsijT, muTPrime if it == 0: patchT, correctorsListT, KmsijT, MmsijT, BdmsijT, muTPrime = zip( *mapper(computeLocalContribution, range(world.NtCoarse))) else: E_vh = list(mapper(computeIndicators, range(world.NtCoarse))) print( '---- maximal value error estimator for basis correctors {}' .format(np.max(E_vh))) E = {i: E_vh[i] for i in range(np.size(E_vh)) if E_vh[i] > 0} # loop over elements with possible recomputation of correctors correctorsListT, KmsijT, MmsijT, BdmsijT, muTPrime = UpdateElements( tol * np.max(E_vh), E, KmsijT, MmsijT, BdmsijT, correctorsListT, muTPrime) # tol scaled by maximal error indicator print('---- finished computation of correctors') KLOD = pglod.assembleMsStiffnessMatrix( world, patchT, KmsijT) # ms stiffness matrix k2MLOD = pglod.assembleMsStiffnessMatrix(world, patchT, MmsijT) # ms mass matrix kBdLOD = pglod.assembleMsStiffnessMatrix( world, patchT, BdmsijT) # ms boundary matrix MFEM = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) BdFEM = fem.assemblePatchBoundaryMatrix( NWorldCoarse, fem.localBoundaryMassMatrixGetter(NWorldCoarse)) print('---- coarse matrices assembled') nodes = np.arange(world.NpCoarse) fix = util.boundarypIndexMap(NWorldCoarse, boundaryConditions == 0) free = np.setdiff1d(nodes, fix) assert (nodes.all() == free.all()) # compute global interpolation matrix patchGlobal = Patch(world, NFine[0] + 2, 0) IH = interp.L2ProjectionPatchMatrix(patchGlobal, boundaryConditions) assert (IH.shape[0] == NpCoarse) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) fHQuad = basis.T * MFineFEM * f + basis.T * BdFineFEM * g print('---- solving coarse system') # coarse system lhsH = KLOD[free][:, free] - k2MLOD[ free][:, free] + 1j * kBdLOD[free][:, free] rhsH = fHQuad[free] xFree = sparse.linalg.spsolve(lhsH, rhsH) basisCorrectors = pglod.assembleBasisCorrectors( world, patchT, correctorsListT) modifiedBasis = basis - basisCorrectors xFull = np.zeros(world.NpCoarse, dtype='complex128') xFull[free] = xFree uLodCoarse = basis * xFull uLodFine = modifiedBasis * xFull uOldUps = np.copy(uLodFine) k2FineUOld = np.copy(k2FineU) # visualization if it == maxit - 1 and N == 2**4: grid = uLodFine.reshape(NFine + 1, order='C') plt.figure(2) plt.title('LOD_ad, Hlvl=4 - Ex 2') plt.imshow(grid.real, extent=(xC.min(), xC.max(), yC.min(), yC.max()), cmap=plt.cm.hot, origin='lower', vmin=-.6, vmax=.6) plt.colorbar() grid2 = uSol.reshape(NFine + 1, order='C') plt.figure(1) plt.title('reference solution - Ex 2') plt.imshow(grid2.real, extent=(xC.min(), xC.max(), yC.min(), yC.max()), cmap=plt.cm.hot, origin='lower', vmin=-.6, vmax=.6) plt.colorbar() grid3 = uInc.reshape(NFine + 1, order='C') plt.figure(6) plt.title('incident beam - Ex 2') plt.imshow(grid3.real, extent=(xC.min(), xC.max(), yC.min(), yC.max()), cmap=plt.cm.hot, origin='lower', vmin=-.6, vmax=.6) plt.colorbar() Err = np.sqrt( np.dot((uSol - uLodFine).conj(), KFineFEM * (uSol - uLodFine)) + k**2 * np.dot((uSol - uLodFine).conj(), MFineFEM * (uSol - uLodFine))) ErrEnergy = Err / np.sqrt( np.dot((uSol).conj(), KFineFEM * (uSol)) + k**2 * np.dot((uSol).conj(), MFineFEM * (uSol))) print('---- ', np.abs(ErrEnergy), '\n***********************************************') # save errors in arrays relErrEnergy[counter - 1, it] = ErrEnergy print('\n') ###################################################################################### print( '***computing multiscale approximations without updates of correctors***' ) relErrEnergyNoUpdate = np.zeros([len(NList), maxit]) counter = 0 for N in NList: counter += 1 print('H = %.4e' % (1. / N)) NWorldCoarse = np.array([N, N]) NCoarseElement = NFine // NWorldCoarse world = World(NWorldCoarse, NCoarseElement, boundaryConditions) NpCoarse = np.prod(NWorldCoarse + 1) uOldUps = np.zeros(NpFine, dtype='complex128') for it in np.arange(maxit): print('-- it = %d:' % it) knonlinUpre = np.abs(uOldUps) knonlinU = func.evaluateCQ1(NFine, knonlinUpre, xt) k2FineU = np.copy(k2Fine) k2FineU[indicesInEps] *= ( 1. + epsFine[indicesInEps] * knonlinU[indicesInEps]**2) print('---- starting computation of correctors') def computeLocalContribution(TInd): patch = Patch(world, ell, TInd) IPatch = lambda: interp.L2ProjectionPatchMatrix( patch, boundaryConditions) aPatch = lambda: coef.localizeCoefficient(patch, aFine) kPatch = lambda: coef.localizeCoefficient(patch, kFine) k2Patch = lambda: coef.localizeCoefficient(patch, k2FineU) correctorsList = lod.computeBasisCorrectors_helmholtz( patch, IPatch, aPatch, kPatch, k2Patch) # adapted for Helmholtz setting csi = lod.computeBasisCoarseQuantities_helmholtz( patch, correctorsList, aPatch, kPatch, k2Patch) # adapted for Helmholtz setting return patch, correctorsList, csi.Kmsij, csi.Mmsij, csi.Bdmsij, csi.muTPrime def computeIndicators(TInd): k2FineUPatch = lambda: coef.localizeCoefficient( patchT[TInd], k2FineU) k2FineUOldPatch = lambda: coef.localizeCoefficient( patchT[TInd], k2FineUOld) E_vh = lod.computeErrorIndicatorCoarse_helmholtz( patchT[TInd], muTPrime[TInd], k2FineUOldPatch, k2FineUPatch) return E_vh def UpdateCorrectors(TInd): patch = Patch(world, ell, TInd) IPatch = lambda: interp.L2ProjectionPatchMatrix( patch, boundaryConditions) aPatch = lambda: coef.localizeCoefficient(patch, aFine) kPatch = lambda: coef.localizeCoefficient(patch, kFine) k2Patch = lambda: coef.localizeCoefficient(patch, k2FineU) correctorsList = lod.computeBasisCorrectors_helmholtz( patch, IPatch, aPatch, kPatch, k2Patch) csi = lod.computeBasisCoarseQuantities_helmholtz( patch, correctorsList, aPatch, kPatch, k2Patch) # adapted for Helmholtz setting return patch, correctorsList, csi.Kmsij, csi.Mmsij, csi.Bdmsij, csi.muTPrime def UpdateElements(tol, E, Kmsij_old, Mmsij_old, Bdmsij_old, correctors_old, mu_old): print('---- apply tolerance') Elements_to_be_updated = [] for (i, eps) in E.items(): if eps > tol: Elements_to_be_updated.append(i) if len(E) > 0: print( '---- total percentage of element correctors to be updated: %.4f' % (100 * np.size(Elements_to_be_updated) / len(mu_old)), flush=True) print('---- update local contributions') KmsijT_list = list(np.copy(Kmsij_old)) MmsijT_list = list(np.copy(Mmsij_old)) BdmsijT_list = list(np.copy(Bdmsij_old)) muT_list = np.copy(mu_old) for T in np.setdiff1d(range(world.NtCoarse), Elements_to_be_updated): patch = Patch(world, ell, T) aPatch = lambda: coef.localizeCoefficient(patch, aFine) kPatch = lambda: coef.localizeCoefficient(patch, kFine) k2Patch = lambda: coef.localizeCoefficient(patch, k2FineU) csi = lod.computeBasisCoarseQuantities_helmholtz( patch, correctors_old[T], aPatch, kPatch, k2Patch) KmsijT_list[T] = csi.Kmsij MmsijT_list[T] = csi.Mmsij BdmsijT_list[T] = csi.Bdmsij muT_list[T] = csi.muTPrime if np.size(Elements_to_be_updated) != 0: #print('---- update correctors') patchT_irrelevant, correctorsListTNew, KmsijTNew, MmsijTNew, BdmsijTNew, muTPrimeNew = zip( *mapper(UpdateCorrectors, Elements_to_be_updated)) #print('---- update correctorsList') correctorsListT_list = list(np.copy(correctors_old)) i = 0 for T in Elements_to_be_updated: KmsijT_list[T] = KmsijTNew[i] correctorsListT_list[T] = correctorsListTNew[i] MmsijT_list[T] = MmsijTNew[i] BdmsijT_list[T] = BdmsijTNew[i] muT_list[T] = muTPrimeNew[i] i += 1 KmsijT = tuple(KmsijT_list) correctorsListT = tuple(correctorsListT_list) MmsijT = tuple(MmsijT_list) BdmsijT = tuple(BdmsijT_list) muTPrime = tuple(muT_list) return correctorsListT, KmsijT, MmsijT, BdmsijT, muTPrime else: KmsijT = tuple(KmsijT_list) MmsijT = tuple(MmsijT_list) BdmsijT = tuple(BdmsijT_list) muTPrime = tuple(muT_list) return correctors_old, KmsijT, MmsijT, BdmsijT, muTPrime if it == 0: patchT, correctorsListT, KmsijT, MmsijT, BdmsijT, muTPrime = zip( *mapper(computeLocalContribution, range(world.NtCoarse))) else: E_vh = list(mapper(computeIndicators, range(world.NtCoarse))) print( '---- maximal value error estimator for basis correctors {}' .format(np.max(E_vh))) E = {i: E_vh[i] for i in range(np.size(E_vh)) if E_vh[i] > 0} # loop over elements with possible recomputation of correctors correctorsListT, KmsijT, MmsijT, BdmsijT, muTPrime = UpdateElements( 2. * np.max(E_vh), E, KmsijT, MmsijT, BdmsijT, correctorsListT, muTPrime) # no updates print('---- finished computation of correctors') KLOD = pglod.assembleMsStiffnessMatrix( world, patchT, KmsijT) # ms stiffness matrix k2MLOD = pglod.assembleMsStiffnessMatrix(world, patchT, MmsijT) # ms mass matrix kBdLOD = pglod.assembleMsStiffnessMatrix( world, patchT, BdmsijT) # ms boundary matrix MFEM = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) BdFEM = fem.assemblePatchBoundaryMatrix( NWorldCoarse, fem.localBoundaryMassMatrixGetter(NWorldCoarse)) print('---- coarse matrices assembled') nodes = np.arange(world.NpCoarse) fix = util.boundarypIndexMap(NWorldCoarse, boundaryConditions == 0) free = np.setdiff1d(nodes, fix) assert (nodes.all() == free.all()) # compute global interpolation matrix patchGlobal = Patch(world, NFine[0] + 2, 0) IH = interp.L2ProjectionPatchMatrix(patchGlobal, boundaryConditions) assert (IH.shape[0] == NpCoarse) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) fHQuad = basis.T * MFineFEM * f + basis.T * BdFineFEM * g print('---- solving coarse system') # coarse system lhsH = KLOD[free][:, free] - k2MLOD[ free][:, free] + 1j * kBdLOD[free][:, free] rhsH = fHQuad[free] xFree = sparse.linalg.spsolve(lhsH, rhsH) basisCorrectors = pglod.assembleBasisCorrectors( world, patchT, correctorsListT) modifiedBasis = basis - basisCorrectors xFull = np.zeros(world.NpCoarse, dtype='complex128') xFull[free] = xFree uLodCoarse = basis * xFull uLodFine = modifiedBasis * xFull uOldUps = np.copy(uLodFine) k2FineUOld = np.copy(k2FineU) # visualization if it == maxit - 1 and N == 2**4: grid = uLodFine.reshape(NFine + 1, order='C') plt.figure(3) plt.title('LOD_inf, Hlvl=4 - Ex 2') plt.imshow(grid.real, extent=(xC.min(), xC.max(), yC.min(), yC.max()), cmap=plt.cm.hot, origin='lower', vmin=-.6, vmax=.6) plt.colorbar() Err = np.sqrt( np.dot((uSol - uLodFine).conj(), KFineFEM * (uSol - uLodFine)) + k**2 * np.dot((uSol - uLodFine).conj(), MFineFEM * (uSol - uLodFine))) ErrEnergy = Err / np.sqrt( np.dot((uSol).conj(), KFineFEM * (uSol)) + k**2 * np.dot((uSol).conj(), MFineFEM * (uSol))) print('---- ', np.abs(ErrEnergy), '\n***********************************************') # save errors in arrays relErrEnergyNoUpdate[counter - 1, it] = ErrEnergy print('\n') ###################################################################################### print( '***computing multiscale approximations where all correctors in the part of the domain with active nonlinearity are recomputed***' ) relErrEnergyFullUpdate = np.zeros([len(NList), maxit]) counter = 0 for N in NList: counter += 1 print('H = %.4e' % (1. / N)) NWorldCoarse = np.array([N, N]) NCoarseElement = NFine // NWorldCoarse world = World(NWorldCoarse, NCoarseElement, boundaryConditions) NpCoarse = np.prod(NWorldCoarse + 1) uOldUps = np.zeros(NpFine, dtype='complex128') for it in np.arange(maxit): print('-- it = %d:' % it) knonlinUpre = np.abs(uOldUps) knonlinU = func.evaluateCQ1(NFine, knonlinUpre, xt) k2FineU = np.copy(k2Fine) k2FineU[indicesInEps] *= ( 1. + epsFine[indicesInEps] * knonlinU[indicesInEps]**2) print('---- starting computation of correctors') def computeLocalContribution(TInd): patch = Patch(world, ell, TInd) IPatch = lambda: interp.L2ProjectionPatchMatrix( patch, boundaryConditions) aPatch = lambda: coef.localizeCoefficient(patch, aFine) kPatch = lambda: coef.localizeCoefficient(patch, kFine) k2Patch = lambda: coef.localizeCoefficient(patch, k2FineU) correctorsList = lod.computeBasisCorrectors_helmholtz( patch, IPatch, aPatch, kPatch, k2Patch) # adapted for Helmholtz setting csi = lod.computeBasisCoarseQuantities_helmholtz( patch, correctorsList, aPatch, kPatch, k2Patch) # adapted for Helmholtz setting return patch, correctorsList, csi.Kmsij, csi.Mmsij, csi.Bdmsij, csi.muTPrime def computeIndicators(TInd): k2FineUPatch = lambda: coef.localizeCoefficient( patchT[TInd], k2FineU) k2FineUOldPatch = lambda: coef.localizeCoefficient( patchT[TInd], k2FineUOld) E_vh = lod.computeErrorIndicatorCoarse_helmholtz( patchT[TInd], muTPrime[TInd], k2FineUOldPatch, k2FineUPatch) return E_vh def UpdateCorrectors(TInd): patch = Patch(world, ell, TInd) IPatch = lambda: interp.L2ProjectionPatchMatrix( patch, boundaryConditions) aPatch = lambda: coef.localizeCoefficient(patch, aFine) kPatch = lambda: coef.localizeCoefficient(patch, kFine) k2Patch = lambda: coef.localizeCoefficient(patch, k2FineU) correctorsList = lod.computeBasisCorrectors_helmholtz( patch, IPatch, aPatch, kPatch, k2Patch) csi = lod.computeBasisCoarseQuantities_helmholtz( patch, correctorsList, aPatch, kPatch, k2Patch) # adapted for Helmholtz setting return patch, correctorsList, csi.Kmsij, csi.Mmsij, csi.Bdmsij, csi.muTPrime def UpdateElements(tol, E, Kmsij_old, Mmsij_old, Bdmsij_old, correctors_old, mu_old): print('---- apply tolerance') Elements_to_be_updated = [] for (i, eps) in E.items(): if eps > tol: Elements_to_be_updated.append(i) if len(E) > 0: print( '---- total percentage of element correctors to be updated: %.4f' % (100 * np.size(Elements_to_be_updated) / len(mu_old)), flush=True) print('---- update local contributions') KmsijT_list = list(np.copy(Kmsij_old)) MmsijT_list = list(np.copy(Mmsij_old)) BdmsijT_list = list(np.copy(Bdmsij_old)) muT_list = np.copy(mu_old) for T in np.setdiff1d(range(world.NtCoarse), Elements_to_be_updated): patch = Patch(world, ell, T) aPatch = lambda: coef.localizeCoefficient(patch, aFine) kPatch = lambda: coef.localizeCoefficient(patch, kFine) k2Patch = lambda: coef.localizeCoefficient(patch, k2FineU) csi = lod.computeBasisCoarseQuantities_helmholtz( patch, correctors_old[T], aPatch, kPatch, k2Patch) KmsijT_list[T] = csi.Kmsij MmsijT_list[T] = csi.Mmsij BdmsijT_list[T] = csi.Bdmsij muT_list[T] = csi.muTPrime if np.size(Elements_to_be_updated) != 0: #print('---- update correctors') patchT_irrelevant, correctorsListTNew, KmsijTNew, MmsijTNew, BdmsijTNew, muTPrimeNew = zip( *mapper(UpdateCorrectors, Elements_to_be_updated)) #print('---- update correctorsList') correctorsListT_list = list(np.copy(correctors_old)) i = 0 for T in Elements_to_be_updated: KmsijT_list[T] = KmsijTNew[i] correctorsListT_list[T] = correctorsListTNew[i] MmsijT_list[T] = MmsijTNew[i] BdmsijT_list[T] = BdmsijTNew[i] muT_list[T] = muTPrimeNew[i] i += 1 KmsijT = tuple(KmsijT_list) correctorsListT = tuple(correctorsListT_list) MmsijT = tuple(MmsijT_list) BdmsijT = tuple(BdmsijT_list) muTPrime = tuple(muT_list) return correctorsListT, KmsijT, MmsijT, BdmsijT, muTPrime else: KmsijT = tuple(KmsijT_list) MmsijT = tuple(MmsijT_list) BdmsijT = tuple(BdmsijT_list) muTPrime = tuple(muT_list) return correctors_old, KmsijT, MmsijT, BdmsijT, muTPrime if it == 0: patchT, correctorsListT, KmsijT, MmsijT, BdmsijT, muTPrime = zip( *mapper(computeLocalContribution, range(world.NtCoarse))) else: E_vh = list(mapper(computeIndicators, range(world.NtCoarse))) print( '---- maximal value error estimator for basis correctors {}' .format(np.max(E_vh))) E = {i: E_vh[i] for i in range(np.size(E_vh)) if E_vh[i] > 0} # loop over elements with possible recomputation of correctors correctorsListT, KmsijT, MmsijT, BdmsijT, muTPrime = UpdateElements( 0., E, KmsijT, MmsijT, BdmsijT, correctorsListT, muTPrime) # no updates print('---- finished computation of correctors') KLOD = pglod.assembleMsStiffnessMatrix( world, patchT, KmsijT) # ms stiffness matrix k2MLOD = pglod.assembleMsStiffnessMatrix(world, patchT, MmsijT) # ms mass matrix kBdLOD = pglod.assembleMsStiffnessMatrix( world, patchT, BdmsijT) # ms boundary matrix MFEM = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) BdFEM = fem.assemblePatchBoundaryMatrix( NWorldCoarse, fem.localBoundaryMassMatrixGetter(NWorldCoarse)) print('---- coarse matrices assembled') nodes = np.arange(world.NpCoarse) fix = util.boundarypIndexMap(NWorldCoarse, boundaryConditions == 0) free = np.setdiff1d(nodes, fix) assert (nodes.all() == free.all()) # compute global interpolation matrix patchGlobal = Patch(world, NFine[0] + 2, 0) IH = interp.L2ProjectionPatchMatrix(patchGlobal, boundaryConditions) assert (IH.shape[0] == NpCoarse) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) fHQuad = basis.T * MFineFEM * f + basis.T * BdFineFEM * g print('---- solving coarse system') # coarse system lhsH = KLOD[free][:, free] - k2MLOD[ free][:, free] + 1j * kBdLOD[free][:, free] rhsH = fHQuad[free] xFree = sparse.linalg.spsolve(lhsH, rhsH) basisCorrectors = pglod.assembleBasisCorrectors( world, patchT, correctorsListT) modifiedBasis = basis - basisCorrectors xFull = np.zeros(world.NpCoarse, dtype='complex128') xFull[free] = xFree uLodCoarse = basis * xFull uLodFine = modifiedBasis * xFull uOldUps = np.copy(uLodFine) k2FineUOld = np.copy(k2FineU) # visualization if it == maxit - 1 and N == 2**4: grid = uLodFine.reshape(NFine + 1, order='C') plt.figure(7) plt.title('LOD_inf, Hlvl=4 - Ex 2') plt.imshow(grid.real, extent=(xC.min(), xC.max(), yC.min(), yC.max()), cmap=plt.cm.hot, origin='lower', vmin=-.6, vmax=.6) plt.colorbar() Err = np.sqrt( np.dot((uSol - uLodFine).conj(), KFineFEM * (uSol - uLodFine)) + k**2 * np.dot((uSol - uLodFine).conj(), MFineFEM * (uSol - uLodFine))) ErrEnergy = Err / np.sqrt( np.dot((uSol).conj(), KFineFEM * (uSol)) + k**2 * np.dot((uSol).conj(), MFineFEM * (uSol))) print('---- ', np.abs(ErrEnergy), '\n***********************************************') # save errors in arrays relErrEnergyFullUpdate[counter - 1, it] = ErrEnergy print('\n') ###################################################################################### print('***computing FEM approximations***') FEMrelErrEnergy = np.zeros([len(NList), maxit]) counter = 0 for N in NList: counter += 1 print('H = %.4e' % (1. / N)) NWorldCoarse = np.array([N, N]) NCoarseElement = NFine // NWorldCoarse world = World(NWorldCoarse, NCoarseElement, boundaryConditions) NpCoarse = np.prod(NWorldCoarse + 1) xT = util.tCoordinates(NWorldCoarse) xP = util.pCoordinates(NWorldCoarse) uOld = np.zeros(NpCoarse, dtype='complex128') # compute coarse coefficients by averaging NtC = np.prod(NWorldCoarse) aCoarse = np.zeros(NtC) kCoarse = k * np.ones(xT.shape[0]) k2Coarse = np.zeros(NtC) epsCoarse = np.zeros(NtC) for Q in range(NtC): patch = Patch(world, 0, Q) aPatch = coef.localizeCoefficient(patch, aFine) epsPatch = coef.localizeCoefficient(patch, epsFine) k2Patch = coef.localizeCoefficient(patch, k2Fine) aCoarse[Q] = np.sum(aPatch) / (len(aPatch)) k2Coarse[Q] = np.sum(k2Patch) / (len(k2Patch)) epsCoarse[Q] = np.sum(epsPatch) / (len(epsPatch)) # coarse matrices KFEM = fem.assemblePatchMatrix(NWorldCoarse, fem.localStiffnessMatrix(NWorldCoarse), aCoarse) kBdFEM = fem.assemblePatchBoundaryMatrix( NWorldCoarse, fem.localBoundaryMassMatrixGetter(NWorldCoarse), kCoarse) MFEM = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) BdFEM = fem.assemblePatchBoundaryMatrix( NWorldCoarse, fem.localBoundaryMassMatrixGetter(NWorldCoarse)) for it in np.arange(maxit): print('-- it = %d:' % it) knonlinUpre = np.abs(uOld) knonlinU = func.evaluateCQ1(NWorldCoarse, knonlinUpre, xT) k2CoarseU = np.copy(k2Coarse) k2CoarseU *= (1. + epsCoarse * knonlinU**2) # update weighted mass matrix k2MFEM = fem.assemblePatchMatrix(NWorldCoarse, fem.localMassMatrix(NWorldCoarse), k2CoarseU) nodes = np.arange(world.NpCoarse) fix = util.boundarypIndexMap(NWorldCoarse, boundaryConditions == 0) free = np.setdiff1d(nodes, fix) assert (nodes.all() == free.all()) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) fHQuad = basis.T * MFineFEM * f + basis.T * BdFineFEM * g print('---- solving coarse system') # coarse system lhsH = KFEM[free][:, free] - k2MFEM[ free][:, free] + 1j * kBdFEM[free][:, free] rhsH = fHQuad[free] xFree = sparse.linalg.spsolve(lhsH, rhsH) xFull = np.zeros(world.NpCoarse, dtype='complex128') xFull[free] = xFree uCoarseInt = basis * xFull uOld = np.copy(xFull) # visualization if it == maxit - 1 and N == 2**4: grid = uCoarseInt.reshape(NFine + 1, order='C') plt.figure(4) plt.title('FEM, Hlvl=4 - Ex 2') plt.imshow(grid.real, extent=(xC.min(), xC.max(), yC.min(), yC.max()), cmap=plt.cm.hot, origin='lower', vmin=-.6, vmax=.6) plt.colorbar() Err = np.sqrt( np.dot((uSol - uCoarseInt).conj(), KFineFEM * (uSol - uCoarseInt)) + k**2 * np.dot( (uSol - uCoarseInt).conj(), MFineFEM * (uSol - uCoarseInt))) ErrEnergy = Err / np.sqrt( np.dot((uSol).conj(), KFineFEM * (uSol)) + k**2 * np.dot((uSol).conj(), MFineFEM * (uSol))) print('---- ', np.abs(ErrEnergy), '\n***********************************************') # save errors in arrays FEMrelErrEnergy[counter - 1, it] = ErrEnergy print('\n') # error plots errLOD_2 = np.min(relErrEnergy, 1) errLOD0_2 = np.min(relErrEnergyNoUpdate, 1) errLODall_2 = np.min(relErrEnergyFullUpdate, 1) errFEM_2 = np.min(FEMrelErrEnergy, 1) Hs = 0.5**np.arange(1, maxCoarseLvl + 1) plt.figure(5) plt.title('Relative energy errors w.r.t H - Ex 2') plt.plot(Hs, errLOD_2, 'x-', color='blue', label='LOD_ad') plt.plot(Hs, errLOD0_2, 'x-', color='green', label='LOD_inf') plt.plot(Hs, errLODall_2, 'x-', color='orange', label='LOD_0') plt.plot(Hs, errFEM_2, 'x-', color='red', label='FEM') plt.plot([0.5, 0.0078125], [0.75, 0.01171875], color='black', linestyle='dashed', label='order 1') plt.yscale('log') plt.xscale('log') plt.legend() plt.show()
def standard_lod(world, N, fine, tau, tot_time_steps, k, aFine, bFine, f, damp_corr=False, both_coef=False): # mesh parameters NWorldCoarse = np.array([N, N]) NFine = np.array([fine, fine]) NCoarseElement = NFine // NWorldCoarse NWorldFine = world.NWorldCoarse * world.NCoarseElement bc = world.boundaryConditions world = World(NWorldCoarse, NCoarseElement, bc) def IPatchGenerator(i, N): return interp.L2ProjectionPatchMatrix(i, N, NWorldCoarse, NCoarseElement, bc) b_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, bFine) a_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, aFine / tau) NpCoarse = np.prod(NWorldCoarse + 1) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) # compute basis correctors if damp_corr: b_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, np.zeros_like(bFine)) a_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, aFine / tau) elif both_coef: b_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, bFine) a_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, aFine) else: a_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, np.zeros_like(aFine)) b_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, bFine) lod = lod_wave.LodWave(b_coef, world, k, IPatchGenerator, a_coef) lod.compute_basis_correctors() # compute ms basis basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basis_correctors = lod.assembleBasisCorrectors() mod_basis = basis - basis_correctors Uo = np.zeros(NpCoarse) # coarse v^(-1) and v^0 V = [Uo] V.append(Uo) # compute ms matrices S = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, aFine) K = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, bFine) M = fem.assemblePatchMatrix(NWorldFine, world.MLocFine) free = util.interiorpIndexMap(NWorldCoarse) SmsFree = (mod_basis.T * S * mod_basis)[free][:, free] KmsFree = (mod_basis.T * K * mod_basis)[free][:, free] MmsFree = (mod_basis.T * M * mod_basis)[free][:, free] LmsFree = (mod_basis.T * M * f)[free] for i in range(tot_time_steps): n = i + 1 # linear system A = (1. / (tau ** 2)) * MmsFree + (1. / tau) * SmsFree + KmsFree b = LmsFree + (1. / tau) * SmsFree * V[n][free] + (2. / (tau ** 2)) * MmsFree * V[n][free] \ - (1. / (tau ** 2)) * MmsFree * V[n - 1][free] # solve system VFree = linalg.linSolve(A, b) VFull = np.zeros(NpCoarse) VFull[free] = VFree # append solution for current time step V.append(VFull) return mod_basis * V[-1]
def test_1d_core(mapper): # Example from Peterseim, Variational Multiscale Stabilization and the Exponential Decay of correctors, p. 2 # Two modifications: A with minus and u(here) = 1/4*u(paper). NFine = np.array([3200]) NpFine = np.prod(NFine + 1) NList = [10, 20, 40, 80, 160] epsilon = 1. / 320 k = 2 pi = np.pi xt = util.tCoordinates(NFine).flatten() xp = util.pCoordinates(NFine).flatten() aFine = (2 - np.cos(2 * pi * xt / epsilon))**(-1) uSol = 4 * (xp - xp**2) - 4 * epsilon * ( 1 / (4 * pi) * np.sin(2 * pi * xp / epsilon) - 1 / (2 * pi) * xp * np.sin(2 * pi * xp / epsilon) - epsilon / (4 * pi**2) * np.cos(2 * pi * xp / epsilon) + epsilon / (4 * pi**2)) uSol = uSol / 4 previousErrorCoarse = np.inf previousErrorFine = np.inf for N in NList: NWorldCoarse = np.array([N]) NCoarseElement = NFine // NWorldCoarse boundaryConditions = np.array([[0, 0]]) world = World(NWorldCoarse, NCoarseElement, boundaryConditions) xpCoarse = util.pCoordinates(NWorldCoarse).flatten() def computeKmsij(TInd): patch = Patch(world, k, TInd) IPatch = lambda: interp.L2ProjectionPatchMatrix( patch, boundaryConditions) aPatch = lambda: coef.localizeCoefficient(patch, aFine) correctorsList = lod.computeBasisCorrectors( patch, IPatch, aPatch) csi = lod.computeBasisCoarseQuantities( patch, correctorsList, aPatch) return patch, correctorsList, csi.Kmsij # Use mapper to distribute computations (mapper could be the 'map' built-in or e.g. an ipyparallel map) patchT, correctorsListT, KmsijT = zip( *mapper(computeKmsij, range(world.NtCoarse))) KFull = pglod.assembleMsStiffnessMatrix(world, patchT, KmsijT) MFull = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) free = util.interiorpIndexMap(NWorldCoarse) f = np.ones(world.NpCoarse) bFull = MFull * f KFree = KFull[free][:, free] bFree = bFull[free] xFree = sparse.linalg.spsolve(KFree, bFree) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basisCorrectors = pglod.assembleBasisCorrectors( world, patchT, correctorsListT) modifiedBasis = basis - basisCorrectors xFull = np.zeros(world.NpCoarse) xFull[free] = xFree uLodCoarse = basis * xFull uLodFine = modifiedBasis * xFull AFine = fem.assemblePatchMatrix(NFine, world.ALocFine, aFine) MFine = fem.assemblePatchMatrix(NFine, world.MLocFine) newErrorCoarse = np.sqrt( np.dot(uSol - uLodCoarse, MFine * (uSol - uLodCoarse))) newErrorFine = np.sqrt( np.dot(uSol - uLodFine, AFine * (uSol - uLodFine))) self.assertTrue(newErrorCoarse < previousErrorCoarse) self.assertTrue(newErrorFine < previousErrorFine)
def rb_method_sparse_stop(world, N, fine, tau, tot_time_steps, k, aFine, bFine, f, no_rb_vecs, TOL=None): # coarse mesh parameters NWorldCoarse = np.array([N, N]) NFine = np.array([fine, fine]) NpFine = np.prod(NFine + 1) NCoarseElement = NFine // NWorldCoarse NWorldFine = world.NWorldCoarse * world.NCoarseElement bc = world.boundaryConditions world = World(NWorldCoarse, NCoarseElement, bc) if TOL is None: TOL = 1e-6 NpCoarse = np.prod(NWorldCoarse + 1) def IPatchGenerator(i, N): return interp.L2ProjectionPatchMatrix(i, N, NWorldCoarse, NCoarseElement, bc) b_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, bFine) a_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, aFine / tau) # compute basis correctors lod = lod_wave.LodWave(b_coef, world, k, IPatchGenerator, a_coef) lod.compute_basis_correctors() # compute ms basis basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basis_correctors = lod.assembleBasisCorrectors() ms_basis = basis - basis_correctors fs_solutions_new = [sparse.csc_matrix(np.zeros_like(ms_basis.toarray())) for i in range(tot_time_steps)] for node in range(NpCoarse): prev_fs_sol_new = ms_basis[:, node] snapshots = [] for time_step in range(no_rb_vecs): print('Calculating correction at N = %d, node = %d/%d, time_step = %d' % (N, node, NpCoarse, time_step)) node_index_arr = compute_2d_node(world.NWorldCoarse, node) ecT = lod_node.nodeCorrector(world, k, node_index_arr) b_patch = b_coef.localize(ecT.iPatchWorldCoarse, ecT.NPatchCoarse) a_patch = a_coef.localize(ecT.iPatchWorldCoarse, ecT.NPatchCoarse) IPatch = IPatchGenerator(ecT.iPatchWorldCoarse, ecT.NPatchCoarse) fs_list = ecT.compute_localized_node_correction_test(b_patch, a_patch, IPatch, prev_fs_sol_new, node) prev_fs_sol_new = sparse.csr_matrix(fs_list).T fs_solutions_new[time_step][:, node] = prev_fs_sol_new snapshots.append(fs_list) V = sparse.csc_matrix(gram_schmidt_rb(snapshots, TOL)) if V.get_shape()[0] == time_step: break for i in range(time_step + 1, tot_time_steps): fs_solutions_new[i][:, node] = sparse.csc_matrix(V.T * ecT.compute_rb_node_correction_test(b_patch, a_patch, IPatch, fs_solutions_new[i-1][:, node], V)).T # initial value Uo = np.zeros(NpCoarse) # coarse v^(-1) and v^0 V = [Uo] V.append(Uo) # compute ms matrices S = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, aFine) K = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, bFine) M = fem.assemblePatchMatrix(NWorldFine, world.MLocFine) free = util.interiorpIndexMap(NWorldCoarse) SmsFree = (ms_basis.T * S * ms_basis)[free][:, free] KmsFree = (ms_basis.T * K * ms_basis)[free][:, free] MmsFree = (ms_basis.T * M * ms_basis)[free][:, free] # load vector f = np.ones(NpFine) LmsFree = (ms_basis.T * M * f)[free] RmsFreeList = [] for i in range(tot_time_steps): n = i + 1 # linear system A = (1. / (tau ** 2)) * MmsFree + (1. / tau) * SmsFree + KmsFree b = LmsFree + (1. / tau) * SmsFree * V[n][free] + (2. / (tau ** 2)) * MmsFree * V[n][free] \ - (1. / (tau ** 2)) * MmsFree * V[n - 1][free] # store ms matrix R^{ms',h}_{H,i,k} RmsFull = ms_basis.T * S * sparse.csc_matrix(fs_solutions_new[i]) RmsFree = RmsFull[free][:, free] RmsFreeList.append(RmsFree) # add sum to linear system if i != 0: for j in range(i): b += (1. / tau) * RmsFreeList[j] * V[n - 1 - j][free] # solve system VFree = linalg.linSolve(A, b) VFull = np.zeros(NpCoarse) VFull[free] = VFree # append solution for current time step V.append(VFull) VFine = ms_basis * V[-1] WFine = 0 for j in range(tot_time_steps): WFine += sparse.csc_matrix(fs_solutions_new[j]) * V[n - j] return VFine + WFine, ms_basis * Uo
def test_1d_toReference(self): NWorldFine = np.array([200]) NWorldCoarse = np.array([10]) NCoarseElement = NWorldFine / NWorldCoarse boundaryConditions = np.array([[0, 0]]) world = World(NWorldCoarse, NCoarseElement, boundaryConditions) NpFine = np.prod(NWorldFine + 1) NtFine = np.prod(NWorldFine) NpCoarse = np.prod(NWorldCoarse + 1) aBase = np.zeros(NtFine) aBase[:90] = 1 aBase[90:] = 2 k = 10 IPatchGenerator = lambda i, N: interp.L2ProjectionPatchMatrix( i, N, NWorldCoarse, NCoarseElement, boundaryConditions) aCoef = coef.coefficientFine(NWorldCoarse, NCoarseElement, aBase) pglod = pg.PetrovGalerkinLOD(world, k, IPatchGenerator, 0) pglod.updateCorrectors(aCoef, clearFineQuantities=False) KmsFull = pglod.assembleMsStiffnessMatrix() KFull = pglod.assembleStiffnessMatrix() MFull = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) free = util.interiorpIndexMap(NWorldCoarse) coords = util.pCoordinates(NWorldCoarse) g = 1 - coords[:, 0] bFull = -KmsFull * g KmsFree = KmsFull[free][:, free] bFree = bFull[free] xFree = sparse.linalg.spsolve(KmsFree, bFree) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basisCorrectors = pglod.assembleBasisCorrectors() modifiedBasis = basis - basisCorrectors xFull = np.zeros(NpCoarse) xFull[free] = xFree uLodCoarse = basis * (xFull + g) uLodFine = modifiedBasis * (xFull + g) coordsFine = util.pCoordinates(NWorldFine) gFine = 1 - coordsFine[:, 0] uFineFull, AFine, _ = femsolver.solveFine(world, aBase, None, -gFine, boundaryConditions) uFineFull += gFine errorFine = np.sqrt( np.dot(uFineFull - uLodFine, AFine * (uFineFull - uLodFine))) self.assertTrue(np.isclose(errorFine, 0)) # Also compute upscaled solution and compare with uFineFull uLodFineUpscaled = basis * (xFull + g) - pglod.computeCorrection( ARhsFull=basis * (xFull + g)) self.assertTrue(np.allclose(uLodFineUpscaled, uLodFine))
NpCoarse = np.prod(NWorldCoarse + 1) def IPatchGenerator(i, N): return interp.L2ProjectionPatchMatrix(i, N, NWorldCoarse, NCoarseElement, boundaryConditions) b_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, bFine) a_coef = coef.coefficientFine(NWorldCoarse, NCoarseElement, aFine / tau) # compute basis correctors lod = lod_wave.LodWave(b_coef, world, k_0, IPatchGenerator, a_coef) lod.compute_basis_correctors() # compute ms basis basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basis_correctors = lod.assembleBasisCorrectors() ms_basis = basis - basis_correctors prev_fs_sol = ms_basis fs_solutions = [] for i in range(numTimeSteps): # solve system lod = lod_wave.LodWave(b_coef, world, k_1, IPatchGenerator, a_coef, prev_fs_sol) lod.solve_fs_system() # store sparse solution prev_fs_sol = sparse.csc_matrix(np.array(np.column_stack(lod.fs_list))) fs_solutions.append(prev_fs_sol)
def test_2d_exactSolution(self): NWorldFine = np.array([30, 40]) NpFine = np.prod(NWorldFine + 1) NtFine = np.prod(NWorldFine) NWorldCoarse = np.array([3, 4]) NCoarseElement = NWorldFine / NWorldCoarse NtCoarse = np.prod(NWorldCoarse) NpCoarse = np.prod(NWorldCoarse + 1) boundaryConditions = np.array([[0, 0], [1, 1]]) world = World(NWorldCoarse, NCoarseElement, boundaryConditions) np.random.seed(0) aBaseSquare = np.exp(5 * np.random.random_sample(NWorldFine[0])) aBaseCube = np.tile(aBaseSquare, [NWorldFine[1], 1]) aBaseCube = aBaseCube[..., np.newaxis] aBase = aBaseCube.flatten() IPatchGenerator = lambda i, N: interp.L2ProjectionPatchMatrix( i, N, NWorldCoarse, NCoarseElement, boundaryConditions) rCoarse = np.ones(NtCoarse) aCoef = coef.coefficientCoarseFactor(NWorldCoarse, NCoarseElement, aBase, rCoarse) k = 4 printLevel = 0 epsilonTol = 0.05 pglod = pg.PetrovGalerkinLOD(world, k, IPatchGenerator, epsilonTol, printLevel) pglod.updateCorrectors(aCoef, clearFineQuantities=False) boundaryMap = boundaryConditions == 0 fixed = util.boundarypIndexMap(NWorldCoarse, boundaryMap) free = np.setdiff1d(np.arange(0, NpCoarse), fixed) coords = util.pCoordinates(NWorldCoarse) xC = coords[:, 0] yC = coords[:, 1] g = 1 - xC firstIteration = True # First case is to not modify. Error should be 0 # The other cases modify one, a few or half of the coarse elements to different degrees. rCoarseModPairs = [([], []), ([0], [2.]), ([10], [3.]), ([4, 3, 2], [1.3, 1.5, 1.8])] rCoarseModPairs.append((range(NtCoarse / 2), [2] * NtCoarse)) rCoarseModPairs.append((range(NtCoarse / 2), [0.9] * NtCoarse)) rCoarseModPairs.append((range(NtCoarse / 2), [0.95] * NtCoarse)) for i, rCoarseModPair in zip(count(), rCoarseModPairs): for ind, val in zip(rCoarseModPair[0], rCoarseModPair[1]): rCoarse[ind] *= val aCoef = coef.coefficientCoarseFactor(NWorldCoarse, NCoarseElement, aBase, rCoarse) pglod.updateCorrectors(aCoef, clearFineQuantities=False) KmsFull = pglod.assembleMsStiffnessMatrix() bFull = -KmsFull * g KmsFree = KmsFull[free][:, free] bFree = bFull[free] xFree = sparse.linalg.spsolve(KmsFree, bFree) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basisCorrectors = pglod.assembleBasisCorrectors() modifiedBasis = basis - basisCorrectors xFull = np.zeros(NpCoarse) xFull[free] = xFree uLodFine = modifiedBasis * (xFull + g) gFine = basis * g uFineFull, AFine, MFine = femsolver.solveFine( world, aCoef.aFine, None, -gFine, boundaryConditions) uFineFull += gFine errorFineA = np.sqrt( np.dot(uFineFull - uLodFine, AFine * (uFineFull - uLodFine))) errorFineM = np.sqrt( np.dot(uFineFull - uLodFine, MFine * (uFineFull - uLodFine))) if firstIteration: self.assertTrue(np.isclose(errorFineA, 0)) self.assertTrue(np.isclose(errorFineM, 0)) # Also compute upscaled solution and compare with uFineFull uLodFineUpscaled = basis * ( xFull + g) - pglod.computeCorrection(ARhsFull=basis * (xFull + g)) self.assertTrue(np.allclose(uLodFineUpscaled, uLodFine)) firstIteration = False else: # For this problem, it seems that # error < 1.1*errorTol self.assertTrue(errorFineA <= 1.1 * epsilonTol)