Пример #1
0
    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))
Пример #2
0
    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
Пример #4
0
    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))
Пример #5
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
Пример #6
0
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]
Пример #7
0
    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
Пример #8
0
    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))
Пример #9
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
Пример #11
0
    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
Пример #12
0
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
Пример #13
0
    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)
Пример #14
0
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
Пример #19
0
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()
Пример #21
0
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]
Пример #22
0
        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)
Пример #23
0
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
Пример #24
0
    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))
Пример #25
0
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)
Пример #26
0
    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)