Beispiel #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]
              })
Beispiel #2
0
    def __init__(self, edges, coord_sys, tabs):
        self.edges = edges
        self.nodes = dict.fromkeys(["y", "z"])
        for var in self.nodes.keys():
            self.nodes[var] = (self.edges[var][1:] + self.edges[var][:-1]) / 2
        self.npts = len(self.edges["y"]) * len(self.edges["z"])
        self.coord_sys = coord_sys

        # create mesh
        self.fem_mesh = skfem.MeshTri.init_tensor(self.edges["y"],
                                                  self.edges["z"])

        # get coordinates (returns a vector size 2*(Ny*Nz))
        self.coordinates = self.fem_mesh.p

        # create elements and basis
        self.element = skfem.ElementTriP1()
        self.basis = skfem.InteriorBasis(self.fem_mesh, self.element)
        self.facet_basis = skfem.FacetBasis(self.fem_mesh, self.element)

        # get degrees of freedom and facets which correspond to tabs, and
        # create facet basis for sub regions
        self.negative_tab_dofs = self.basis.get_dofs(
            lambda x: self.on_boundary(x[0], x[1], tabs["negative"])).all()
        self.positive_tab_dofs = self.basis.get_dofs(
            lambda x: self.on_boundary(x[0], x[1], tabs["positive"])).all()
        self.negative_tab_facets = self.fem_mesh.facets_satisfying(
            lambda x: self.on_boundary(x[0], x[1], tabs["negative"]))
        self.positive_tab_facets = self.fem_mesh.facets_satisfying(
            lambda x: self.on_boundary(x[0], x[1], tabs["positive"]))
        self.negative_tab_basis = skfem.FacetBasis(
            self.fem_mesh, self.element, facets=self.negative_tab_facets)
        self.positive_tab_basis = skfem.FacetBasis(
            self.fem_mesh, self.element, facets=self.positive_tab_facets)
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
Beispiel #4
0
height = 0.41

geom = Geometry()
cylinder = geom.add_circle([0.2, 0.2, 0.0], radius, lcar=radius / 2)
channel = geom.add_rectangle(
    0.0, 2.2, 0.0, height, 0, holes=[cylinder], lcar=radius / 2
)
geom.add_physical(channel.surface, "domain")
geom.add_physical(channel.lines[1], "outlet")
geom.add_physical(channel.lines[3], "inlet")

mesh = from_meshio(generate_mesh(geom, dim=2))

element = {"u": skfem.ElementVectorH1(skfem.ElementTriP2()), "p": skfem.ElementTriP1()}
basis = {
    **{v: skfem.InteriorBasis(mesh, e, intorder=4) for v, e in element.items()},
    "inlet": skfem.FacetBasis(mesh, element["u"], facets=mesh.boundaries["inlet"]),
}
M = skfem.asm(vector_mass, basis["u"])
L = {"u": skfem.asm(vector_laplace, basis["u"]), "p": skfem.asm(laplace, basis["p"])}
B = -skfem.asm(divergence, basis["u"], basis["p"])
P = B.T + skfem.asm(
    port_pressure,
    *(
        skfem.FacetBasis(mesh, element[v], intorder=3, facets=mesh.boundaries["outlet"])
        for v in ["p", "u"]
    ),
)

t_final = 5.0
dt = 0.001
Beispiel #5
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

    ml = pyamg.smoothed_aggregation_solver(
        mesh = from_file(Path("cylinder.json"))
    except Exception as e:
        from cylinder_dmsh import CylinderDmsh

        print("Couldn't find cylinder.json; generating in dmsh.")
        mesher = CylinderDmsh()
        mesh = mesher.mesh
        mesher.save()

element = {
    "u": skfem.ElementVectorH1(skfem.ElementTriP2()),
    "p": skfem.ElementTriP1()
}
basis = {
    **{
        v: skfem.InteriorBasis(mesh, e, intorder=4)
        for v, e in element.items()
    },
    "inlet": skfem.FacetBasis(mesh,
                              element["u"],
                              facets=mesh.boundaries["inlet"]),
}
pressure_probe = probe(basis["p"], np.array([(0.15, 0.2), (0.25, 0.2)]).T)

M = skfem.asm(vector_mass, basis["u"])
L = {
    "u": skfem.asm(vector_laplace, basis["u"]),
    "p": skfem.asm(laplace, basis["p"])
}
B = -skfem.asm(divergence, basis["u"], basis["p"])
P = B.T + skfem.asm(