示例#1
0
def localize_problem(p,
                     coarse_grid_resolution,
                     fine_grid_resolution,
                     mus=None,
                     calT=False,
                     calTd=False,
                     calQ=False,
                     dof_codim=2,
                     localization_codim=2,
                     discretizer=None,
                     m=1):

    assert coarse_grid_resolution > (m + 1) * 2
    assert fine_grid_resolution % coarse_grid_resolution == 0

    print("localizing problem")
    global_quantities = {}
    global_quantities["coarse_grid_resolution"] = coarse_grid_resolution
    local_quantities = {}

    # Diskretisierung auf dem feinen Gitter:
    diameter = 1. / fine_grid_resolution
    global_quantities["diameter"] = diameter
    if discretizer is None:
        discretizer = discretize_stationary_cg
    d, data = discretizer(p, diameter=diameter)
    grid = data["grid"]

    global_quantities["d"] = d
    global_quantities["data"] = data

    global_operator = d.operator.assemble(mus)
    global_quantities["op"] = global_operator
    global_quantities["op_not_assembled"] = d.operator
    global_rhs = d.rhs.assemble(mus)
    global_quantities["rhs"] = global_rhs

    op_fixed = copy.deepcopy(d.operator)

    # Skalierung der Dirichlet-Freiheitsgrade:
    try:
        dirichlet_dofs = data['boundary_info'].dirichlet_boundaries(dof_codim)
        for op in op_fixed.operators:
            op.assemble(mus).matrix[dirichlet_dofs, dirichlet_dofs] *= 1e5
        # d.rhs.assemble(mus)._matrix[:, dirichlet_dofs] *= 1e5
    except KeyError:
        pass

    global_operator_fixed = op_fixed.assemble(mus)
    global_quantities["op_fixed"] = global_operator_fixed
    global_quantities["op_fixed_not_assembled"] = op_fixed

    global_quantities["p"] = p

    try:
        dmask = data['boundary_info'].dirichlet_mask(dof_codim)
    except KeyError:
        dmask = None

    # Konstruktion der Teilraeume:
    subspaces, subspaces_per_codim = build_subspaces(
        *partition_any_grid(grid,
                            num_intervals=(coarse_grid_resolution,
                                           coarse_grid_resolution),
                            dmask=dmask,
                            codim=dof_codim))
    global_quantities["subspaces"] = subspaces
    global_quantities["subspaces_per_codim"] = subspaces_per_codim
    localizer = NumpyLocalizer(d.solution_space, subspaces['dofs'])
    global_quantities["localizer"] = localizer

    def create_m_patch(xspace, m):
        for i in range(m):
            space = xspace
            cspace = tuple(
                set(i for k in space if subspaces[k]['codim'] == 0
                    for i in subspaces[k]['cpatch'] if i not in space))
            xspace = tuple(
                set(i for k in cspace if subspaces[k]['codim'] == 1
                    for i in subspaces[k]['env']) | set(space))
        cxspace = tuple(
            set(i for k in xspace if subspaces[k]['codim'] == 0
                for i in subspaces[k]['cpatch'] if i not in xspace))
        return xspace, cxspace

    pou = localized_pou(subspaces, subspaces_per_codim, localizer,
                        coarse_grid_resolution, grid, localization_codim,
                        dof_codim)
    global_quantities["pou"] = pou
    spaces = [subspaces[s_id]["env"] for s_id in subspaces_per_codim[2]]
    global_quantities["spaces"] = spaces

    full_l2_product = d.products["l2"].assemble()
    full_h1_semi_product = d.products["h1_semi"].assemble()
    k_product = LincombOperator((full_h1_semi_product, full_l2_product),
                                (1, mus["k"]**2)).assemble()
    global_quantities["full_norm"] = induced_norm(k_product)
    global_quantities["k_product"] = k_product
    for xpos in range(coarse_grid_resolution - 1):
        for ypos in range(coarse_grid_resolution - 1):
            # print "localizing..."
            s_id = subspaces_per_codim[localization_codim][
                ypos + xpos * (coarse_grid_resolution - 1)]
            space = subspaces[s_id]["env"]
            ldict = {}
            local_quantities[space] = ldict
            ldict["pos"] = (xpos, ypos)

            # Konstruktion der lokalen Raeume:
            range_space = subspaces[s_id]["env"]
            ldict["range_space"] = range_space
            omega_space = tuple(
                sorted(
                    set(subspaces[s_id]['env'])
                    | set(subspaces[s_id]['cenv'])))
            ldict["omega_space"] = omega_space
            training_space, source_space = create_m_patch(range_space, m)
            # source_space = subspaces[s_id]["cxenv"]
            ldict["source_space"] = source_space
            # training_space = subspaces[s_id]["xenv"]
            ldict["training_space"] = training_space
            omega_star_space = tuple(
                sorted(set(training_space) | set(source_space)))
            ldict["omega_star_space"] = omega_star_space

            # lokale Shift-Loesung mit f(Dirichlet)
            local_op = localizer.localize_operator(global_operator,
                                                   training_space,
                                                   training_space)
            local_rhs = localizer.localize_operator(global_rhs, None,
                                                    training_space)
            local_solution = local_op.apply_inverse(local_rhs.as_range_array())
            local_solution = localizer.to_space(local_solution, training_space,
                                                range_space)
            local_solution = pou[range_space](local_solution)
            ldict["local_solution_dirichlet"] = local_solution

            # Dirichlet Transferoperator:
            rhsop = localizer.localize_operator(global_operator,
                                                training_space, source_space)
            transop_dirichlet = create_dirichlet_transfer(
                localizer, local_op, rhsop, source_space, training_space,
                range_space, pou)
            ldict["dirichlet_transfer"] = transop_dirichlet

            # subgrid
            xmin = max(0, xpos - m)
            xsize = min(xpos + 2 + m, coarse_grid_resolution) - xmin
            ymin = max(0, ypos - m)
            ysize = min(ypos + 2 + m, coarse_grid_resolution) - ymin
            ldict["posext"] = [(xmin / coarse_grid_resolution,
                                ymin / coarse_grid_resolution),
                               ((xmin + xsize) / coarse_grid_resolution,
                                (ymin + ysize) / coarse_grid_resolution)]
            mysubgrid = getsubgrid(grid,
                                   xmin,
                                   ymin,
                                   coarse_grid_resolution,
                                   xsize=xsize,
                                   ysize=ysize)
            mysubbi = SubGridBoundaryInfo(mysubgrid, grid,
                                          data['boundary_info'], 'robin')
            ld, ldata = discretizer(p, grid=mysubgrid, boundary_info=mysubbi)
            lop = ld.operator.assemble(mus)

            # index conversion
            ndofsext = len(ldata['grid'].parent_indices(dof_codim))
            global_dofnrsext = -100000000 * np.ones(
                shape=(d.solution_space.dim, ))
            global_dofnrsext[ldata['grid'].parent_indices(
                dof_codim)] = np.array(range(ndofsext))
            lvecext = localizer.localize_vector_array(
                NumpyVectorSpace.make_array(global_dofnrsext),
                omega_star_space).data[0]

            # Robin Transferoperator:
            bilifo = NumpyMatrixOperator(lop.matrix[:, lvecext][lvecext, :])
            transop_robin = create_robin_transfer(localizer, bilifo,
                                                  source_space,
                                                  omega_star_space,
                                                  range_space, pou)
            ldict["robin_transfer"] = transop_robin

            # lokale Shift-Loesung mit f(Robin)
            lrhs = ld.rhs.assemble(mus)
            llrhs = NumpyMatrixOperator(lrhs.matrix[lvecext.astype(int)])
            local_solution = bilifo.apply_inverse(llrhs.as_range_array())
            ldict["local_sol2"] = local_solution
            local_solution = localizer.to_space(local_solution,
                                                omega_star_space, range_space)
            local_solution_pou = pou[range_space](local_solution)
            ldict["local_solution_robin"] = local_solution_pou

            if calT:
                # Transfer-Matrix:
                ldict["transfer_matrix_robin"] = transop_robin.as_range_array(
                ).data.T

            if calTd:
                # Transfer-Matrix:
                ldict[
                    "transfer_matrix_dirichlet"] = transop_dirichlet.as_range_array(
                    ).data.T

            # Konstruktion der Produkte:
            range_k = localizer.localize_operator(k_product, range_space,
                                                  range_space)
            omstar_k = LincombOperator((NumpyMatrixOperator(
                ld.products["h1_semi"].assemble().matrix[:,
                                                         lvecext][lvecext, :]),
                                        NumpyMatrixOperator(
                                            ld.products["l2"].assemble(
                                            ).matrix[:, lvecext][lvecext, :])),
                                       (1, mus["k"]**2)).assemble()

            ldict["omega_star_product"] = omstar_k
            ldict["range_product"] = range_k

            if calQ:
                # Loesungs-Matrix:
                solution_op_robin = create_robin_solop(localizer, bilifo,
                                                       source_space,
                                                       omega_star_space)
                Q_r = solution_op_robin.as_range_array()
                ldict["solution_matrix_robin"] = Q_r.data.T
                source_Q_r_product = NumpyMatrixOperator(
                    omstar_k.apply(Q_r).data.T)
                ldict["source_product"] = source_Q_r_product

            lproduct = localizer.localize_operator(full_l2_product,
                                                   source_space, source_space)
            lmat = lproduct.matrix.tocoo()
            lmat.data = np.array([
                4. / 6. * diameter if (row == col) else diameter / 6.
                for row, col in zip(lmat.row, lmat.col)
            ])
            ldict["source_product"] = NumpyMatrixOperator(lmat.tocsc().astype(
                np.cfloat))

    return global_quantities, local_quantities