Ejemplo n.º 1
0
def read_fenics_solution(filepath):
    from dolfin import (Mesh, XDMFFile, MeshValueCollection, cpp,
                        FunctionSpace, Function, HDF5File, MPI)
    mesh = Mesh()
    with XDMFFile("%s_triangle.xdmf" % filepath.split('.')[0]) as infile:
        infile.read(mesh)  # read the complete mesh

    #mvc_subdo = MeshValueCollection("size_t", mesh, mesh.geometric_dimension() - 1)
    #with XDMFFile("%s_triangle.xdmf" % filepath.split('.')[0]) as infile:
    #    infile.read(mvc_subdo, "subdomains")  # read the diferent subdomians
    #subdomains = cpp.mesh.MeshFunctionSizet(mesh, mvc_subdo)

    #mvc = MeshValueCollection("size_t", mesh, mesh.geometric_dimension() - 2)
    #with XDMFFile("%s_line.xdmf" % filepath.split('.')[0]) as infile:
    #    infile.read(mvc, "boundary_conditions")  # read the boundary conditions
    #boundary = cpp.mesh.MeshFunctionSizet(mesh, mvc)

    # Define function space and basis functions
    V = FunctionSpace(mesh, "CG", 1)
    U = Function(V)
    input_file = HDF5File(MPI.comm_world,
                          filepath.split('.')[0] + "_solution_field.h5", "r")
    input_file.read(U, "solution")
    input_file.close()

    dofs = V.tabulate_dof_coordinates().reshape(
        V.dim(),
        mesh.geometry().dim())  # coordinates of nodes
    U.set_allow_extrapolation(True)
    return U, mesh, dofs.shape[0]
Ejemplo n.º 2
0
def test_tabulate_all_coordinates(mesh_factory):
    func, args = mesh_factory
    mesh = func(*args)
    V = FunctionSpace(mesh, ("Lagrange", 1))
    W0 = FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    W1 = VectorElement("Lagrange", mesh.ufl_cell(), 1)
    W = FunctionSpace(mesh, W0 * W1)

    D = mesh.geometry.dim
    V_dofmap = V.dofmap
    W_dofmap = W.dofmap

    all_coords_V = V.tabulate_dof_coordinates()
    all_coords_W = W.tabulate_dof_coordinates()
    local_size_V = V_dofmap().index_map.size_local * V_dofmap(
    ).index_map.block_size
    local_size_W = W_dofmap().index_map.size_local * W_dofmap(
    ).index_map.block_size

    all_coords_V = all_coords_V.reshape(local_size_V, D)
    all_coords_W = all_coords_W.reshape(local_size_W, D)

    checked_V = [False] * local_size_V
    checked_W = [False] * local_size_W

    # Check that all coordinates are within the cell it should be
    for i in range(mesh.num_cells()):
        cell = MeshEntity(mesh, mesh.topology.dim, i)
        dofs_V = V_dofmap.cell_dofs(i)
        for di in dofs_V:
            if di >= local_size_V:
                continue
            assert cell.contains(all_coords_V[di])
            checked_V[di] = True

        dofs_W = W_dofmap.cell_dofs(cell.index())
        for di in dofs_W:
            if di >= local_size_W:
                continue
            assert cell.contains(all_coords_W[di])
            checked_W[di] = True

    # Assert that all dofs have been checked by the above
    assert all(checked_V)
    assert all(checked_W)
Ejemplo n.º 3
0
def test_tabulate_all_coordinates(mesh_factory):
    func, args = mesh_factory
    mesh = func(*args)
    V = FunctionSpace(mesh, "Lagrange", 1)
    W0 = FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    W1 = VectorElement("Lagrange", mesh.ufl_cell(), 1)
    W = FunctionSpace(mesh, W0 * W1)

    D = mesh.geometry.dim
    V_dofmap = V.dofmap()
    W_dofmap = W.dofmap()

    all_coords_V = V.tabulate_dof_coordinates()
    all_coords_W = W.tabulate_dof_coordinates()
    local_size_V = V_dofmap.ownership_range()[1] - V_dofmap.ownership_range(
    )[0]
    local_size_W = W_dofmap.ownership_range()[1] - W_dofmap.ownership_range(
    )[0]

    all_coords_V = all_coords_V.reshape(local_size_V, D)
    all_coords_W = all_coords_W.reshape(local_size_W, D)

    checked_V = [False] * local_size_V
    checked_W = [False] * local_size_W

    # Check that all coordinates are within the cell it should be
    for cell in Cells(mesh):
        dofs_V = V_dofmap.cell_dofs(cell.index())
        for di in dofs_V:
            if di >= local_size_V:
                continue
            assert cell.contains(Point(all_coords_V[di]))
            checked_V[di] = True

        dofs_W = W_dofmap.cell_dofs(cell.index())
        for di in dofs_W:
            if di >= local_size_W:
                continue
            assert cell.contains(Point(all_coords_W[di]))
            checked_W[di] = True

    # Assert that all dofs have been checked by the above
    assert all(checked_V)
    assert all(checked_W)
Ejemplo n.º 4
0
def test_multi_ps_matrix_node(mesh):
    """Tests point source when given constructor PointSource(V, source)
    with a matrix when points placed at 3 nodes for 1D, 2D and
    3D. Global points given to constructor from rank 0 processor.

    """

    point = [0.0, 0.5, 1.0]
    rank = MPI.rank(mesh.mpi_comm())
    V = FunctionSpace(mesh, "CG", 1)
    u, v = TrialFunction(V), TestFunction(V)
    w = Function(V)
    A = assemble(Constant(0.0) * u * v * dx)
    dim = mesh.geometry().dim()

    source = []

    point_coords = np.zeros(dim)
    for p in point:
        for i in range(dim):
            point_coords[i - 1] = p
        if rank == 0:
            source.append((Point(point_coords), 10.0))
    ps = PointSource(V, source)
    ps.apply(A)

    # Checks matrix sums to correct value.
    A.get_diagonal(w.vector())
    a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array()))
    assert round(a_sum - len(point) * 10) == 0

    # Check if coordinates are in portion of mesh and if so check that
    # diagonal components sum to the correct value.
    mesh_coords = V.tabulate_dof_coordinates()
    for p in point:
        for i in range(dim):
            point_coords[i - 1] = p

        j = 0
        for i in range(len(mesh_coords) // (dim)):
            mesh_coords_check = mesh_coords[j:j + dim - 1]
            if np.array_equal(point_coords, mesh_coords_check) is True:
                assert np.round(w.vector()[j // (dim)] - 10.0) == 0.0
            j += dim
Ejemplo n.º 5
0
def test_multi_ps_matrix_node(mesh):
    """Tests point source when given constructor PointSource(V, source)
    with a matrix when points placed at 3 nodes for 1D, 2D and
    3D. Global points given to constructor from rank 0 processor.

    """

    point = [0.0, 0.5, 1.0]
    rank = MPI.rank(mesh.mpi_comm())
    V = FunctionSpace(mesh, "CG", 1)
    u, v = TrialFunction(V), TestFunction(V)
    w = Function(V)
    A = assemble(Constant(0.0)*u*v*dx)
    dim = mesh.geometry().dim()

    source = []

    point_coords = np.zeros(dim)
    for p in point:
        for i in range(dim):
            point_coords[i-1] = p
        if rank == 0:
            source.append((Point(point_coords), 10.0))
    ps = PointSource(V, source)
    ps.apply(A)

    # Checks matrix sums to correct value.
    A.get_diagonal(w.vector())
    a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array()))
    assert round(a_sum - len(point)*10) == 0

    # Check if coordinates are in portion of mesh and if so check that
    # diagonal components sum to the correct value.
    mesh_coords = V.tabulate_dof_coordinates()
    for p in point:
        for i in range(dim):
            point_coords[i-1] = p

        j = 0
        for i in range(len(mesh_coords)//(dim)):
            mesh_coords_check = mesh_coords[j:j+dim-1]
            if np.array_equal(point_coords, mesh_coords_check) is True:
                assert np.round(w.vector()[j//(dim)]-10.0) == 0.0
            j += dim
Ejemplo n.º 6
0
def test_multi_ps_vector_node(mesh):
    """Tests point source when given constructor PointSource(V, V, point,
    mag) with a matrix when points placed at 3 node for 1D, 2D and
    3D. Global points given to constructor from rank 0 processor.

    """

    point = [0.0, 0.5, 1.0]
    dim = mesh.geometry().dim()
    rank = MPI.rank(mesh.mpi_comm())
    V = FunctionSpace(mesh, "CG", 1)
    v = TestFunction(V)
    b = assemble(Constant(0.0) * v * dx)

    source = []
    point_coords = np.zeros(dim)
    for p in point:
        for i in range(dim):
            point_coords[i - 1] = p
        if rank == 0:
            source.append((Point(point_coords), 10.0))
    ps = PointSource(V, source)
    ps.apply(b)

    # Checks b sums to correct value
    b_sum = b.sum()
    assert round(b_sum - len(point) * 10.0) == 0

    # Checks values added to correct part of vector
    mesh_coords = V.tabulate_dof_coordinates()
    for p in point:
        for i in range(dim):
            point_coords[i] = p

        j = 0
        for i in range(len(mesh_coords) // (dim)):
            mesh_coords_check = mesh_coords[j:j + dim - 1]
            if np.array_equal(point_coords, mesh_coords_check) is True:
                assert np.round(b.array()[j // (dim)] - 10.0) == 0.0
            j += dim
Ejemplo n.º 7
0
def test_multi_ps_vector_node(mesh):
    """Tests point source when given constructor PointSource(V, V, point,
    mag) with a matrix when points placed at 3 node for 1D, 2D and
    3D. Global points given to constructor from rank 0 processor.

    """

    point = [0.0, 0.5, 1.0]
    dim = mesh.geometry().dim()
    rank = MPI.rank(mesh.mpi_comm())
    V = FunctionSpace(mesh, "CG", 1)
    v = TestFunction(V)
    b = assemble(Constant(0.0)*v*dx)

    source = []
    point_coords = np.zeros(dim)
    for p in point:
        for i in range(dim):
            point_coords[i-1] = p
        if rank == 0:
            source.append((Point(point_coords), 10.0))
    ps = PointSource(V, source)
    ps.apply(b)

    # Checks b sums to correct value
    b_sum = b.sum()
    assert round(b_sum - len(point)*10.0) == 0

    # Checks values added to correct part of vector
    mesh_coords = V.tabulate_dof_coordinates()
    for p in point:
        for i in range(dim):
            point_coords[i] = p

        j = 0
        for i in range(len(mesh_coords)//(dim)):
            mesh_coords_check = mesh_coords[j:j + dim - 1]
            if np.array_equal(point_coords, mesh_coords_check) is True:
                assert np.round(b.array()[j//(dim)]-10.0) == 0.0
            j += dim
Ejemplo n.º 8
0
def eafe_assemble(
    mesh: Mesh,
    diffusion: Coefficient,
    convection: Optional[Coefficient] = None,
    reaction: Optional[Coefficient] = None,
) -> dolfin.Matrix:
    """
    Assembly of stiffness matrix for a generic linear elliptic equation:
    for `u` a continuous piecewise-linear finite element function,
      -div(diffusion * grad(u) + convection * u) + reaction * u = source

    Edge-integral quantities are approximated by a midpoint quadrature rule.

    :param mesh: Mesh defining finite element space
    :param diff: Coefficient for diffusion coefficient
    :param conv: [Optional] Coefficient for convection coefficient
    :param reac: [Optional] Coefficient for reaction coefficient

    :return: dolfin.Matrix pertaining to EAFE stiffness matrix
    """

    if not issubclass(mesh.__class__, Mesh):
        raise TypeError(
            "Invalid mesh parameter: must inherit from dolfin.Mesh")

    logging.getLogger("FFC").setLevel(logging.WARNING)
    quadrature_degree = parameters["form_compiler"]["quadrature_degree"]
    parameters["form_compiler"]["quadrature_degree"] = 2

    spatial_dim: int = mesh.topology().dim()
    cell_vertex_count: int = spatial_dim + 1

    try:
        edge_advection = define_edge_advection(spatial_dim, diffusion,
                                               convection)
        lumped_reaction = define_mass_lumping(cell_vertex_count, reaction)
    except Exception as e:
        parameters["form_compiler"]["quadrature_degree"] = quadrature_degree
        raise e

    V = FunctionSpace(mesh, "Lagrange", 1)
    u = TrialFunction(V)
    v = TestFunction(V)
    a = inner(grad(u), grad(v)) * dx
    A: dolfin.Matrix = assemble(a)
    mat: dolfin.PETScMatrix = as_backend_type(A).mat()

    A.zero()
    dof_map = V.dofmap()
    dof_coord = V.tabulate_dof_coordinates()

    for cell in cells(mesh):
        local_tensor = assemble_local(a, cell)
        local_to_global_map = dof_map.cell_dofs(cell.index())
        cell_vertex = np.empty([cell_vertex_count, spatial_dim])

        for local_dof in range(0, cell_vertex_count):
            dof_id = local_to_global_map[local_dof]
            for coord in range(0, spatial_dim):
                cell_vertex[local_dof, coord] = dof_coord[dof_id, coord]

        for vertex_id in range(0, cell_vertex_count):
            vertex = cell_vertex[vertex_id]
            local_tensor[vertex_id, vertex_id] = lumped_reaction(vertex, cell)

            for edge_id in range(0, cell_vertex_count):
                if edge_id == vertex_id:
                    continue

                edge = cell_vertex[edge_id] - vertex
                local_tensor[vertex_id,
                             edge_id] *= edge_advection(vertex, edge, cell)
                local_tensor[vertex_id, vertex_id] -= local_tensor[vertex_id,
                                                                   edge_id]

        local_to_global_list = local_to_global_map.tolist()
        mat.setValuesLocal(
            local_to_global_list,
            local_to_global_list,
            local_tensor,
            PETSc.InsertMode.ADD,
        )

    A.apply("insert")
    mat.assemble()

    parameters["form_compiler"]["quadrature_degree"] = quadrature_degree
    return A
Ejemplo n.º 9
0
def solve(mesh, Eps, degree):
    V = FunctionSpace(mesh, "CG", degree)
    u = TrialFunction(V)
    v = TestFunction(V)

    n = FacetNormal(mesh)

    gdim = mesh.geometry().dim()

    A = [
        _assemble_eigen(
            Constant(Eps[i, j]) * (u.dx(i) * v.dx(j) * dx - u.dx(i) * n[j] * v * ds)
        ).sparray()
        for j in range(gdim)
        for i in range(gdim)
    ]

    assert_equality = False
    if assert_equality:
        # The sum of the `A`s is exactly that:
        n = FacetNormal(V.mesh())
        AA = _assemble_eigen(
            +dot(dot(as_tensor(Eps), grad(u)), grad(v)) * dx
            - dot(dot(as_tensor(Eps), grad(u)), n) * v * ds
        ).sparray()
        diff = AA - sum(A)
        assert numpy.all(abs(diff.data) < 1.0e-14)
        #
        # ATAsum = sum(a.T.dot(a) for a in A)
        # diff = AA.T.dot(AA) - ATAsum
        # # import betterspy
        # # betterspy.show(ATAsum)
        # # betterspy.show(AA.T.dot(AA))
        # # betterspy.show(ATAsum - AA.T.dot(AA))
        # print(diff.data)
        # assert numpy.all(abs(diff.data) < 1.0e-14)

    tol = 1.0e-10

    def lower(x, on_boundary):
        return on_boundary and x[1] < -1.0 + tol

    def upper(x, on_boundary):
        return on_boundary and x[1] > 1.0 - tol

    def left(x, on_boundary):
        return on_boundary and abs(x[0] + 1.0) < tol

    def right(x, on_boundary):
        return on_boundary and abs(x[0] - 1.0) < tol

    def upper_left(x, on_boundary):
        return on_boundary and x[1] > +1.0 - tol and x[0] < -0.8

    def lower_right(x, on_boundary):
        return on_boundary and x[1] < -1.0 + tol and x[0] > 0.8

    bcs = [
        # DirichletBC(V, Constant(0.0), lower_right),
        # DirichletBC(V, Constant(0.0), upper_left),
        DirichletBC(V, Constant(0.0), lower),
        DirichletBC(V, Constant(0.0), upper),
        # DirichletBC(V, Constant(0.0), upper_left, method='pointwise'),
        # DirichletBC(V, Constant(0.0), lower_left, method='pointwise'),
        # DirichletBC(V, Constant(0.0), lower_right, method='pointwise'),
    ]

    M = _assemble_eigen(u * v * dx).sparray()

    ATMinvAsum = sum(
        numpy.dot(a.toarray().T, numpy.linalg.solve(M.toarray(), a.toarray()))
        for a in A
    )

    AA2 = _assemble_eigen(
        +dot(dot(as_tensor(Eps), grad(u)), grad(v)) * dx
        - dot(dot(as_tensor(Eps), grad(u)), n) * v * ds,
        # bcs=[DirichletBC(V, Constant(0.0), 'on_boundary')]
        # bcs=bcs
        # bcs=[
        #     DirichletBC(V, Constant(0.0), lower),
        #     DirichletBC(V, Constant(0.0), right),
        #     ]
    ).sparray()

    ATA2 = numpy.dot(AA2.toarray().T, numpy.linalg.solve(M.toarray(), AA2.toarray()))

    # Find combination of Dirichlet points:
    if False:
        # min_val = 1.0
        max_val = 0.0
        # min_combi = []
        max_combi = []
        is_updated = False
        it = 0
        # get boundary indices
        d = DirichletBC(V, Constant(0.0), "on_boundary")
        boundary_idx = numpy.sort(list(d.get_boundary_values().keys()))
        # boundary_idx = numpy.arange(V.dim())
        # print(boundary_idx)
        # pick some at random
        # idx = numpy.sort(numpy.random.choice(boundary_idx, size=3, replace=False))
        for idx in itertools.combinations(boundary_idx, 3):
            it += 1
            print()
            print(it)

            # Replace the rows corresponding to test functions living in one cell
            # (deliberately chosen as 0) by Dirichlet rows.
            AA3 = AA2.tolil()
            for k in idx:
                AA3[k] = 0
                AA3[k, k] = 1
            n = AA3.shape[0]
            AA3 = AA3.tocsr()

            ATA2 = numpy.dot(
                AA3.toarray().T, numpy.linalg.solve(M.toarray(), AA3.toarray())
            )
            vals = numpy.sort(numpy.linalg.eigvalsh(ATA2))
            if vals[0] < 0.0:
                continue

            # op = sparse.linalg.LinearOperator(
            #     (n, n),
            #     matvec=lambda x: _spsolve(AA3, M.dot(_spsolve(AA3.T.tocsr(), x)))
            #     )
            # vals, _ = scipy.sparse.linalg.eigsh(op, k=3, which='LM')
            # vals = numpy.sort(1/vals[::-1])
            # print(vals)

            print(idx)

            # if min_val > vals[0]:
            #     min_val = vals[0]
            #     min_combi = idx
            #     is_updated = True

            if max_val < vals[0]:
                max_val = vals[0]
                max_combi = idx
                is_updated = True

            if is_updated:
                # vals, _ = scipy.sparse.linalg.eigsh(op, k=10, which='LM')
                # vals = numpy.sort(1/vals[::-1])
                # print(vals)
                is_updated = False
                # print(min_val, min_combi)
                print(max_val, max_combi)
                # plt.plot(dofs_x[:, 0], dofs_x[:, 1], 'x')
                meshzoo.plot2d(mesh.coordinates(), mesh.cells())
                dofs_x = V.tabulate_dof_coordinates().reshape((-1, gdim))
                # plt.plot(dofs_x[min_combi, 0], dofs_x[min_combi, 1], 'or')
                plt.plot(dofs_x[max_combi, 0], dofs_x[max_combi, 1], "ob")
                plt.gca().set_aspect("equal")
                plt.title(f"smallest eigenvalue: {max_val}")
                plt.show()

            # # if True:
            # if abs(vals[0]) < 1.0e-8:
            #     gdim = mesh.geometry().dim()
            #     # plt.plot(dofs_x[:, 0], dofs_x[:, 1], 'x')
            #     X = mesh.coordinates()
            #     meshzoo.plot2d(mesh.coordinates(), mesh.cells())
            #     dofs_x = V.tabulate_dof_coordinates().reshape((-1, gdim))
            #     plt.plot(dofs_x[idx, 0], dofs_x[idx, 1], 'or')
            #     plt.gca().set_aspect('equal')
            #     plt.show()

        meshzoo.plot2d(mesh.coordinates(), mesh.cells())
        dofs_x = V.tabulate_dof_coordinates().reshape((-1, gdim))
        # plt.plot(dofs_x[min_combi, 0], dofs_x[min_combi, 1], 'or')
        plt.plot(dofs_x[max_combi, 0], dofs_x[max_combi, 1], "ob")
        plt.gca().set_aspect("equal")
        plt.title(f"final smallest eigenvalue: {max_val}")
        plt.show()
        exit(1)

    # Eigenvalues of the operators
    if True:
        # import betterspy
        # betterspy.show(sum(A), colormap="viridis")

        AA = _assemble_eigen(
            +dot(grad(u), grad(v)) * dx - dot(grad(u), n) * v * ds
        ).sparray()

        eigvals, eigvecs = scipy.sparse.linalg.eigs(AA, k=5, which="SM")

        assert numpy.all(numpy.abs(eigvals.imag) < 1.0e-12)
        eigvals = eigvals.real
        assert numpy.all(numpy.abs(eigvecs.imag) < 1.0e-12)
        eigvecs = eigvecs.real

        i = numpy.argsort(eigvals)
        print(eigvals[i])

        import meshio

        for k in range(3):
            meshio.write_points_cells(
                f"eigval{k}.vtk",
                points,
                {"triangle": cells},
                point_data={"ev": eigvecs[:, i][:, k]},
            )
        exit(1)

        # import betterspy
        # betterspy.show(AA, colormap="viridis")
        # print(numpy.sort(numpy.linalg.eigvals(AA.todense())))
        exit(1)

        Asum = sum(A).todense()
        AsumT_Minv_Asum = numpy.dot(Asum.T, numpy.linalg.solve(M.toarray(), Asum))

        # print(numpy.sort(numpy.linalg.eigvalsh(Asum)))
        print(numpy.sort(numpy.linalg.eigvalsh(AsumT_Minv_Asum)))
        exit(1)

        # eigvals, eigvecs = numpy.linalg.eigh(Asum)
        # i = numpy.argsort(eigvals)
        # print(eigvals[i])
        # exit(1)
        # print(eigvals[:20])
        # eigvals[eigvals < 1.0e-15] = 1.0e-15
        #
        # eigvals = numpy.sort(numpy.linalg.eigvalsh(sum(A).todense()))
        # print(eigvals[:20])
        # plt.semilogy(eigvals, ".", label="Asum")
        # plt.legend()
        # plt.grid()
        # plt.show()
        # exit(1)

        ATMinvAsum_eigs = numpy.sort(numpy.linalg.eigvalsh(ATMinvAsum))
        print(ATMinvAsum_eigs[:20])
        ATMinvAsum_eigs[ATMinvAsum_eigs < 0.0] = 1.0e-12
        # ATA2_eigs = numpy.sort(numpy.linalg.eigvalsh(ATA2))
        # print(ATA2_eigs[:20])
        plt.semilogy(ATMinvAsum_eigs, ".", label="ATMinvAsum")
        # plt.semilogy(ATA2_eigs, ".", label="ATA2")
        plt.legend()
        plt.grid()
        plt.show()
        # # Preconditioned eigenvalues
        # # IATA_eigs = numpy.sort(scipy.linalg.eigvalsh(ATMinvAsum, ATA2))
        # # plt.semilogy(IATA_eigs, ".", label="precond eigenvalues")
        # # plt.legend()
        # # plt.show()
        exit(1)

    # # Test with A only
    # numpy.random.seed(123)
    # b = numpy.random.rand(sum(a.shape[0] for a in A))
    # MTM = M.T.dot(M)
    # MTb = M.T.dot(b)
    # sol = _gmres(
    #     MTM,
    #     # TODO linear operator
    #     # lambda x: M.T.dot(M.dot(x)),
    #     MTb,
    #     M=prec
    #     )
    # plt.semilogy(sol.resnorms)
    # plt.show()
    # exit(1)

    n = AA2.shape[0]

    # define the operator
    def matvec(x):
        # M^{-1} can be computed in O(n) with CG + diagonal preconditioning
        # or algebraic multigrid.
        # return sum([a.T.dot(a.dot(x)) for a in A])
        return numpy.sum([a.T.dot(_spsolve(M, a.dot(x))) for a in A], axis=0)

    op = sparse.linalg.LinearOperator((n, n), matvec=matvec)

    # pick a random solution and a consistent rhs
    x = numpy.random.rand(n)
    b = op.dot(x)

    linear_system = krypy.linsys.LinearSystem(op, b)
    print("unpreconditioned solve...")
    t = time.time()
    out = krypy.linsys.Gmres(linear_system, tol=1.0e-12, explicit_residual=True)
    out.xk = out.xk.reshape(b.shape)
    print("done.")
    print("  res: {}".format(out.resnorms[-1]))
    print(
        "  unprec res: {}".format(
            numpy.linalg.norm(b - op.dot(out.xk)) / numpy.linalg.norm(b)
        )
    )
    # The error isn't useful here; only with the nullspace removed
    # print('  error: {}'.format(numpy.linalg.norm(out.xk - x)))
    print("  its: {}".format(len(out.resnorms)))
    print("  duration: {}s".format(time.time() - t))

    # preconditioned solver
    ml = pyamg.smoothed_aggregation_solver(AA2)
    # res = []
    # b = numpy.random.rand(AA2.shape[0])
    # x0 = numpy.zeros(AA2.shape[1])
    # x = ml.solve(b, x0, residuals=res, tol=1.0e-12)
    # print(res)
    # plt.semilogy(res)
    # plt.show()

    mlT = pyamg.smoothed_aggregation_solver(AA2.T.tocsr())
    # res = []
    # b = numpy.random.rand(AA2.shape[0])
    # x0 = numpy.zeros(AA2.shape[1])
    # x = mlT.solve(b, x0, residuals=res, tol=1.0e-12)

    # print(res)
    def prec_matvec(b):
        x0 = numpy.zeros(n)
        b1 = mlT.solve(b, x0, tol=1.0e-12)
        b2 = M.dot(b1)
        x = ml.solve(b2, x0, tol=1.0e-12)
        return x

    prec = LinearOperator((n, n), matvec=prec_matvec)

    # TODO assert this in a test
    # x = prec_matvec(b)
    # print(b - AA2.T.dot(AA2.dot(x)))

    linear_system = krypy.linsys.LinearSystem(op, b, Ml=prec)
    print()
    print("preconditioned solve...")
    t = time.time()
    try:
        out_prec = krypy.linsys.Gmres(
            linear_system, tol=1.0e-14, maxiter=1000, explicit_residual=True
        )
    except krypy.utils.ConvergenceError:
        print("prec not converged!")
        pass
    out_prec.xk = out_prec.xk.reshape(b.shape)
    print("done.")
    print("  res: {}".format(out_prec.resnorms[-1]))
    print(
        "  unprec res: {}".format(
            numpy.linalg.norm(b - op.dot(out_prec.xk)) / numpy.linalg.norm(b)
        )
    )
    print("  its: {}".format(len(out_prec.resnorms)))
    print("  duration: {}s".format(time.time() - t))

    plt.semilogy(out.resnorms, label="original")
    plt.semilogy(out_prec.resnorms, label="preconditioned")
    plt.legend()
    plt.show()

    return out.xk
Ejemplo n.º 10
0
        test = div(grad(psi))
        S_ = gamma * inner(ax, grad(grad(phi))) * test * dx(mx) \
            + stab1 * avg(hE)**(-1) * inner(jump(grad(phi), nE), jump(grad(psi), nE)) * dS(mx) \
            + gamma * inner(bx, grad(phi)) * test * dx(mx) \
            + gamma * c * phi * test * dx(mx)

        # This matrix also changes since we are testing the whole equation
        # with div(grad(psi)) instead of psi
        M_ = gamma * phi * test * dx(mx)

        bc_Vx = DirichletBC(Vx, g, 'on_boundary')
        S = assemble(S_)
        M = assemble(M_)

        # Prepare special treatment of deterministic part and time-derivative.
        xdofs = Vx.tabulate_dof_coordinates().flatten()
        ix = np.argsort(xdofs)

        # Since we're using the mesh in the deterministic direction
        # only for temporary purpose, the coordinates are fine here
        ydofs = Vy.tabulate_dof_coordinates().flatten()
        ydofs.sort()
        ydiff = np.diff(ydofs)

        assert np.all(ydiff > 0)
        # Create meshgrid X, Y of shape (ny+1, nx+1)
        X, Y = np.meshgrid(xdofs, ydofs)

        trange = np.linspace(T[1], T[0], nt + 1)
        dt = -np.diff(trange)
        assert np.all(dt > 0)
Ejemplo n.º 11
0
def run_simulation(
        filepath,
        topology_info: int = None,
        top_bc: int = None,
        bot_bc: int = None,
        left_bc: int = None,
        right_bc: int = None,
        geometry: dict = None,
        kappa=3,  #only if geometry is None
        show=True,
        save_solution=False):

    from dolfin import (Mesh, XDMFFile, MeshValueCollection, cpp,
                        FunctionSpace, TrialFunction, TestFunction,
                        DirichletBC, Constant, Measure, inner, nabla_grad,
                        Function, solve, plot, File)
    mesh = Mesh()
    with XDMFFile("%s_triangle.xdmf" % filepath.split('.')[0]) as infile:
        infile.read(mesh)  # read the complete mesh

    mvc_subdo = MeshValueCollection("size_t", mesh,
                                    mesh.geometric_dimension() - 1)
    with XDMFFile("%s_triangle.xdmf" % filepath.split('.')[0]) as infile:
        infile.read(mvc_subdo, "subdomains")  # read the diferent subdomians
    subdomains = cpp.mesh.MeshFunctionSizet(mesh, mvc_subdo)

    mvc = MeshValueCollection("size_t", mesh, mesh.geometric_dimension() - 2)
    with XDMFFile("%s_line.xdmf" % filepath.split('.')[0]) as infile:
        infile.read(mvc, "boundary_conditions")  #read the boundary conditions
    boundary = cpp.mesh.MeshFunctionSizet(mesh, mvc)

    # Define function space and basis functions
    V = FunctionSpace(mesh, "CG", 1)
    u = TrialFunction(V)
    v = TestFunction(V)
    # Boundary conditions
    bcs = []
    for bc_id in topology_info.keys():
        if bc_id[-2:] == "bc":
            if bot_bc is not None and bc_id[:3] == "bot":
                bcs.append(
                    DirichletBC(V, Constant(bot_bc), boundary,
                                topology_info[bc_id]))
            elif left_bc is not None and bc_id[:4] == "left":
                bcs.append(
                    DirichletBC(V, Constant(left_bc), boundary,
                                topology_info[bc_id]))
            elif top_bc is not None and bc_id[:3] == "top":
                bcs.append(
                    DirichletBC(V, Constant(top_bc), boundary,
                                topology_info[bc_id]))
            elif right_bc is not None and bc_id[:5] == "right":
                bcs.append(
                    DirichletBC(V, Constant(right_bc), boundary,
                                topology_info[bc_id]))
            else:
                print(bc_id + " Not assigned as boundary condition ")
            #    raise NotImplementedError

    # Define new measures associated with the interior domains and
    # exterior boundaries
    dx = Measure("dx", subdomain_data=subdomains)
    ds = Measure("ds", subdomain_data=boundary)

    f = Constant(0)
    g = Constant(0)
    if geometry is not None:  # run multipatch implementation (Multiple domains)
        a = []
        L = []
        for patch_id in geometry.keys():
            kappa = geometry[patch_id].get("kappa")
            a.append(
                inner(Constant(kappa) * nabla_grad(u), nabla_grad(v)) *
                dx(topology_info[patch_id]))
            L.append(f * v * dx(topology_info[patch_id]))
        a = sum(a)
        L = sum(L)
    else:
        a = inner(Constant(kappa) * nabla_grad(u), nabla_grad(v)) * dx
        L = f * v * dx

    ## Redefine u as a function in function space V for the solution
    u = Function(V)
    # Solve
    solve(a == L, u, bcs)
    u.rename('u', 'Temperature')
    # Save solution to file in VTK format
    print('  [+] Output to %s_solution.pvd' % filepath.split('.')[0])
    vtkfile = File('%s_solution.pvd' % filepath.split('.')[0])
    vtkfile << u

    if show:
        import matplotlib
        matplotlib.use("Qt5Agg")
        # Plot solution and gradient
        plot(u, title="Temperature")
        plt.gca().view_init(azim=-90, elev=90)
        plt.show()

    dofs = V.tabulate_dof_coordinates().reshape(
        V.dim(),
        mesh.geometry().dim())  #coordinates of nodes
    vals = u.vector().get_local()  #temperature at nodes

    if save_solution:
        from dolfin import HDF5File, MPI
        output_file = HDF5File(MPI.comm_world,
                               filepath.split('.')[0] + "_solution_field.h5",
                               "w")
        output_file.write(u, "solution")
        output_file.close()
    u.set_allow_extrapolation(True)
    return dofs, vals, mesh, u