Ejemplo n.º 1
0
def save_nullspaces():
    # points, cells = meshzoo.rectangle_tri((0.0, 0.0), (1.0, 1.0), 20)
    points, cells = meshzoo.disk(6, 20)

    @fem.BilinearForm
    def flux(u, v, w):
        return dot(w.n, u.grad) * v

    mesh = fem.MeshTri(points.T, cells.T)
    basis = fem.InteriorBasis(mesh, fem.ElementTriP1())
    facet_basis = fem.FacetBasis(basis.mesh, basis.elem)

    lap = fem.asm(laplace, basis)
    boundary_terms = fem.asm(flux, facet_basis)

    A_dense = (lap - boundary_terms).toarray()

    # the right null space are the affine-linear functions
    rns = scipy.linalg.null_space(A_dense).T
    mesh.save("nullspace-right.vtk",
              point_data={
                  "k0": rns[0],
                  "k1": rns[1],
                  "k2": rns[2]
              })

    # the left null space is a bit weird; something around the boundaries
    lns = scipy.linalg.null_space(A_dense.T).T
    mesh.save("nullspace-left.vtk",
              point_data={
                  "k0": lns[0],
                  "k1": lns[1],
                  "k2": lns[2]
              })
Ejemplo n.º 2
0
def _fit_skfem(x0,
               y0,
               points,
               cells,
               lmbda: float,
               degree: int = 1,
               solver: str = "lsqr"):
    import skfem
    from skfem.helpers import dot
    from skfem.models.poisson import laplace

    assert degree == 1

    if cells.shape[1] == 2:
        mesh = skfem.MeshLine(np.ascontiguousarray(points.T),
                              np.ascontiguousarray(cells.T))
        element = skfem.ElementLineP1()
    elif cells.shape[1] == 3:
        mesh = skfem.MeshTri(np.ascontiguousarray(points.T),
                             np.ascontiguousarray(cells.T))
        element = skfem.ElementTriP1()
    else:
        assert cells.shape[1] == 4
        mesh = skfem.MeshQuad(np.ascontiguousarray(points.T),
                              np.ascontiguousarray(cells.T))
        element = skfem.ElementQuad1()

    @skfem.BilinearForm
    def mass(u, v, _):
        return u * v

    @skfem.BilinearForm
    def flux(u, v, w):
        return dot(w.n, u.grad) * v

    basis = skfem.CellBasis(mesh, element)
    facet_basis = skfem.FacetBasis(basis.mesh, basis.elem)

    lap = skfem.asm(laplace, basis)
    boundary_terms = skfem.asm(flux, facet_basis)

    A = lap - boundary_terms
    A *= lmbda

    # get the evaluation matrix
    E = basis.probes(x0.T)

    # mass matrix
    M = skfem.asm(mass, basis)

    x = _solve(A, M, E, y0, solver)
    return basis, x
Ejemplo n.º 3
0
def setup(n):
    x0 = rng.random((n, 2)) - 0.5
    # y0 = np.ones(n)
    # y0 = x0[:, 0]
    # y0 = x0[:, 0]**2
    # y0 = np.cos(np.pi*x0.T[0])
    # y0 = np.cos(np.pi*x0.T[0]) * np.cos(np.pi*x0.T[1])
    y0 = np.cos(np.pi * np.sqrt(x0.T[0]**2 + x0.T[1]**2))

    points, cells = meshzoo.rectangle_tri((-1.0, -1.0), (1.0, 1.0), n)

    mesh = skfem.MeshTri(points.T.copy(), cells.T.copy())
    element = skfem.ElementTriP1()

    @skfem.BilinearForm
    def mass(u, v, _):
        return u * v

    @skfem.BilinearForm
    def flux(u, v, w):
        return dot(w.n, u.grad) * v

    basis = skfem.InteriorBasis(mesh, element)
    facet_basis = skfem.FacetBasis(basis.mesh, basis.elem)

    lap = skfem.asm(laplace, basis)
    boundary_terms = skfem.asm(flux, facet_basis)

    A = lap - boundary_terms
    # A *= lmbda

    # get the evaluation matrix
    E = basis.probes(x0.T)

    # mass matrix
    M = skfem.asm(mass, basis)

    # x = _solve(A, M, E, y0, solver)

    # # Neumann preconditioner
    # An = _assemble_eigen(dot(grad(u), grad(v)) * dx).sparray()

    # # Dirichlet preconditioner
    # Ad = _assemble_eigen(dot(grad(u), grad(v)) * dx)
    # bc = DirichletBC(V, 0.0, "on_boundary")
    # bc.apply(Ad)
    # # Ad = Ad.sparray()

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

    # ml = pyamg.smoothed_aggregation_solver(A, coarse_solver="jacobi", max_coarse=100)
    # mln = pyamg.smoothed_aggregation_solver(An, coarse_solver="jacobi", max_coarse=100)
    # mld = pyamg.smoothed_aggregation_solver(Ad, coarse_solver="jacobi", max_coarse=100)
    # mlq = pyamg.smoothed_aggregation_solver(Aq, coarse_solver="jacobi", max_coarse=100)

    ml = pyamg.smoothed_aggregation_solver(A,
                                           coarse_solver="jacobi",
                                           symmetry="nonsymmetric",
                                           max_coarse=100)
    # mlT = pyamg.smoothed_aggregation_solver(
    #     A.T, coarse_solver="jacobi", symmetry="nonsymmetric", max_coarse=100
    # )

    P = ml.aspreconditioner()
    # PT = mlT.aspreconditioner()

    # construct transpose -- dense, super expensive!
    I = np.eye(P.shape[0])
    PT = (P @ I).T
    PT = scipy.sparse.csr_matrix(PT)

    # # make sure it's really the transpose
    # x = rng.random(A.shape[1])
    # y = rng.random(A.shape[1])
    # print(np.dot(x, P @ y))
    # print(np.dot(PT @ x, y))

    def matvec(x):
        return P @ x

    def rmatvec(y):
        return PT @ y

    precs = [
        scipy.sparse.linalg.LinearOperator(A.shape,
                                           matvec=matvec,
                                           rmatvec=rmatvec)
        # not working well:
        # (ml.aspreconditioner(), mlT.aspreconditioner())
    ]

    return A, E, M, precs, y0
Ejemplo n.º 4
0
rng = np.random.default_rng(0)

tol = 1.0e-8

for n in range(5, 41, 5):
    # points, cells = meshzoo.rectangle_tri((0.0, 0.0), (1.0, 1.0), n)
    points, cells = meshzoo.disk(6, n)
    print(f"{n = }, {len(points) = }")

    @fem.BilinearForm
    def flux(u, v, w):
        return dot(w.n, u.grad) * v

    # copy to avoid warnings; better would be to get the transposed arrays from meshzoo
    # directly
    mesh = fem.MeshTri(points.T.copy(), cells.T.copy())
    basis = fem.InteriorBasis(mesh, fem.ElementTriP1())
    facet_basis = fem.FacetBasis(basis.mesh, basis.elem)

    lap = fem.asm(laplace, basis)
    boundary_terms = fem.asm(flux, facet_basis)

    A = lap - boundary_terms

    b = rng.random(A.shape[1])
    # make the system consistent by removing A's left nullspace components from the
    # right-hand side
    lns = scipy.linalg.null_space(A.T.toarray()).T
    for n in lns:
        b -= np.dot(b, n) / np.dot(n, n) * n
Ejemplo n.º 5
0
from meshio.xdmf import TimeSeriesWriter


@skfem.BilinearForm
def vector_mass(u, v, w):
    return sum(v * u)


@skfem.BilinearForm
def port_pressure(u, v, w):
    return sum(v * (u * w.n))


p_inlet = 8.0

mesh = skfem.MeshTri()
mesh.refine(3)

boundary = {
    "inlet": mesh.facets_satisfying(lambda x: x[0] == 0),
    "outlet": mesh.facets_satisfying(lambda x: x[0] == 1),
    "wall":
    mesh.facets_satisfying(lambda x: np.logical_or(x[1] == 0, x[1] == 1)),
}
boundary["ports"] = np.concatenate([boundary["inlet"], boundary["outlet"]])

element = {
    "u": skfem.ElementVectorH1(skfem.ElementTriP2()),
    "p": skfem.ElementTriP1()
}
basis = {