示例#1
0
def get_poisson_steps_scikitfem(points, cells, tol):
    from skfem import (
        MeshTri,
        MeshTet,
        InteriorBasis,
        ElementTriP1,
        ElementTetP1,
        asm,
        condense,
    )
    from skfem.models.poisson import laplace, unit_load
    import krypy

    if cells.shape[1] == 3:
        mesh = MeshTri(points.T, cells.T)
        e = ElementTriP1()
    else:
        assert cells.shape[1] == 4
        mesh = MeshTet(points.T, cells.T)
        e = ElementTetP1()

    basis = InteriorBasis(mesh, e)

    # assemble
    A = asm(laplace, basis)
    b = asm(unit_load, basis)

    A, b = condense(A, b, I=mesh.interior_nodes(), expand=False)
    _, info = krypy.cg(A, b, tol=tol)

    return info.iter
示例#2
0
    def runTest(self):
        @LinearForm
        def load(v, w):
            x = w.x
            return (np.sin(np.pi * x[0]) * np.sin(np.pi * x[1]) *
                    (2.0 * np.pi**2) * v)

        m = self.mesh
        Nitrs = 9
        L2s = np.zeros(Nitrs)
        H1s = np.zeros(Nitrs)

        for itr in range(Nitrs):
            ib = self.create_basis(m, itr + 2)

            A = asm(laplace, ib)
            b = asm(load, ib)

            D = ib.find_dofs()

            x = solve(*condense(A, b, D=D))

            # calculate error
            L2s[itr], H1s[itr] = self.compute_error(m, ib, x)

        self.assertLess(H1s[-1], 1e-10)
        self.assertLess(L2s[-1], 1e-11)
    def s(arr: spmatrix, b: np.ndarray) -> LinearSolver:
        ml = ruge_stuben_solver(
            skfem.condense(arr, D=dirichlet[v], expand=False))

        def f(_: LinearOperator, b: np.ndarray) -> np.ndarray:
            return ml.solve(b)

        return f
示例#4
0
def test_point_source(etype):

    mesh = MeshLine1().refined()
    basis = CellBasis(mesh, etype())
    source = np.array([0.7])
    u = solve(*condense(asm(laplace, basis), basis.point_source(source), D=basis.get_dofs()))
    exact = np.stack([(1 - source) * mesh.p, (1 - mesh.p) * source]).min(0)
    assert_almost_equal(u[basis.nodal_dofs], exact)
示例#5
0
    def runTest(self):
        m = self.init_mesh()
        basis = InteriorBasis(m, self.element_type())

        A = laplace.assemble(basis)
        b = unit_load.assemble(basis)
        x = solve(*condense(A, b, D=basis.get_dofs()))

        self.assertAlmostEqual(np.max(x), self.maxval, places=3)
示例#6
0
    def runTest(self):
        path = Path(__file__).parents[1] / 'docs' / 'examples' / 'meshes'
        m = self.mesh_type.load(path / self.filename)
        basis = InteriorBasis(m, self.element_type())

        A = laplace.assemble(basis)
        b = unit_load.assemble(basis)
        x = solve(*condense(A, b, D=basis.get_dofs()))

        self.assertAlmostEqual(np.max(x), 0.06261690318912218, places=3)
示例#7
0
    def runTest(self):
        """Solve Stokes problem, try splitting and other small things."""

        m = MeshTri().refined()
        m = m.refined(3).with_boundaries({
            'up': lambda x: x[1] == 1.,
            'rest': lambda x: x[1] != 1.,
        })

        e = ElementVectorH1(ElementTriP2()) * ElementTriP1()

        basis = CellBasis(m, e)

        @BilinearForm
        def bilinf(u, p, v, q, w):
            from skfem.helpers import grad, ddot, div
            return (ddot(grad(u), grad(v)) - div(u) * q - div(v) * p
                    - 1e-2 * p * q)

        S = asm(bilinf, basis)

        D = basis.find_dofs(skip=['u^2'])
        x = basis.zeros()
        x[D['up'].all('u^1^1')] = .1

        x = solve(*condense(S, x=x, D=D))

        (u, u_basis), (p, p_basis) = basis.split(x)

        self.assertEqual(len(u), m.p.shape[1] * 2 + m.facets.shape[1] * 2)
        self.assertEqual(len(p), m.p.shape[1])

        self.assertTrue(np.sum(p - x[basis.nodal_dofs[2]]) < 1e-8)

        U, P = basis.interpolate(x)
        self.assertTrue(isinstance(U.value, np.ndarray))
        self.assertTrue(isinstance(P.value, np.ndarray))
        self.assertTrue(P.shape[0] == m.nelements)

        self.assertTrue((basis.doflocs[:, D['up'].all()][1] == 1.).all())

        # test blocks splitting of forms while at it
        C1 = asm(bilinf.block(1, 1), CellBasis(m, ElementTriP1()))
        C2 = S[basis.nodal_dofs[-1]].T[basis.nodal_dofs[-1]].T
        self.assertTrue(abs((C1 - C2).min()) < 1e-10)
        self.assertTrue(abs((C1 - C2).max()) < 1e-10)

        # test splitting ElementVector
        (ux, uxbasis), (uy, uybasis) = u_basis.split(u)
        assert_allclose(ux[uxbasis.nodal_dofs[0]], u[u_basis.nodal_dofs[0]])
        assert_allclose(ux[uxbasis.facet_dofs[0]], u[u_basis.facet_dofs[0]])
        assert_allclose(uy[uybasis.nodal_dofs[0]], u[u_basis.nodal_dofs[1]])
        assert_allclose(uy[uybasis.facet_dofs[0]], u[u_basis.facet_dofs[1]])
示例#8
0
    def runTest(self):
        """Solve Stokes problem, try splitting and other small things."""

        m = MeshTri()
        m.refine()
        m.define_boundary('centreline',
                          lambda x: x[0] == .5,
                          boundaries_only=False)
        m.refine(3)

        e = ElementVectorH1(ElementTriP2()) * ElementTriP1()

        m.define_boundary('up', lambda x: x[1] == 1.)
        m.define_boundary('rest', lambda x: x[1] != 1.)

        basis = InteriorBasis(m, e)
        self.assertEqual(
            basis.get_dofs(m.boundaries['centreline']).all().size,
            (2 + 1) * (2**(1 + 3) + 1) + 2 * 2**(1 + 3))
        self.assertEqual(basis.find_dofs()['centreline'].all().size,
                         (2 + 1) * (2**(1 + 3) + 1) + 2 * 2**(1 + 3))

        @BilinearForm
        def bilinf(u, p, v, q, w):
            from skfem.helpers import grad, ddot, div
            return (ddot(grad(u), grad(v)) - div(u) * q - div(v) * p -
                    1e-2 * p * q)

        S = asm(bilinf, basis)

        D = basis.find_dofs(skip=['u^2'])
        x = basis.zeros()
        x[D['up'].all('u^1^1')] = .1

        x = solve(*condense(S, basis.zeros(), x=x, D=D))

        (u, u_basis), (p, p_basis) = basis.split(x)

        self.assertEqual(len(u), m.p.shape[1] * 2 + m.facets.shape[1] * 2)
        self.assertEqual(len(p), m.p.shape[1])

        self.assertTrue(np.sum(p - x[basis.nodal_dofs[2]]) < 1e-8)

        U, P = basis.interpolate(x)
        self.assertTrue(isinstance(U.value, np.ndarray))
        self.assertTrue(isinstance(P.value, np.ndarray))

        self.assertTrue((basis.doflocs[:, D['up'].all()][1] == 1.).all())
示例#9
0
    def runTest(self):
        m = MeshLine(np.linspace(0., 1.)).refined(2)
        ib = InteriorBasis(m, self.e)
        fb = FacetBasis(m, self.e)

        @LinearForm
        def boundary_flux(v, w):
            return v * (w.x[0] == 1.)

        L = asm(laplace, ib)
        b = asm(boundary_flux, fb)
        D = m.nodes_satisfying(lambda x: x == 0.0)
        I = ib.complement_dofs(D)  # noqa E741
        u = solve(*condense(L, b, I=I))  # noqa E741

        np.testing.assert_array_almost_equal(u[ib.nodal_dofs[0]], m.p[0], -10)
示例#10
0
    def runTest(self):

        m = self.mesh().refined(3)

        ib = InteriorBasis(m, self.elem())

        A = asm(laplace, ib)

        D = ib.get_dofs().all()
        I = ib.complement_dofs(D)

        for X in self.funs:
            x = self.set_bc(X, ib)
            Xh = x.copy()
            x = solve(*condense(A, x=x, I=I))
            self.assertLessEqual(np.sum(x - Xh), 1e-10)
示例#11
0
    def runTest(self):
        @LinearForm
        def load(v, w):
            x = w.x
            if x.shape[0] == 1:
                return (np.sin(np.pi * x[0]) * (np.pi**2) * v)
            elif x.shape[0] == 2:
                return (np.sin(np.pi * x[0]) * np.sin(np.pi * x[1]) *
                        (2.0 * np.pi**2) * v)
            elif x.shape[0] == 3:
                return (np.sin(np.pi * x[0]) * np.sin(np.pi * x[1]) *
                        np.sin(np.pi * x[2]) * (3.0 * np.pi**2) * v)
            else:
                raise Exception("The dimension not supported")

        m = self.mesh
        Nitrs = 3
        L2s = np.zeros(Nitrs)
        H1s = np.zeros(Nitrs)
        hs = np.zeros(Nitrs)

        for itr in range(Nitrs):
            if itr > 0:
                m = self.do_refined(m, itr)
            ib = self.create_basis(m)

            A = asm(laplace, ib)
            b = asm(load, ib)

            D = self.get_bc_nodes(ib)
            x = solve(*condense(A, b, D=D))

            # calculate error
            L2s[itr], H1s[itr] = self.compute_error(m, ib, x)
            hs[itr] = m.param()

        rateL2 = np.polyfit(np.log(hs), np.log(L2s), 1)[0]
        rateH1 = np.polyfit(np.log(hs), np.log(H1s), 1)[0]

        self.assertLess(np.abs(rateL2 - self.rateL2),
                        self.eps,
                        msg='observed L2 rate: {}'.format(rateL2))
        self.assertLess(np.abs(rateH1 - self.rateH1),
                        self.eps,
                        msg='observed H1 rate: {}'.format(rateH1))
        self.assertLess(H1s[-1], 0.3)
        self.assertLess(L2s[-1], 0.008)
示例#12
0
    def runTest(self):
        m = self.case[0]()
        m.refine(self.prerefs)

        hs = []
        L2s = []

        for itr in range(3):
            e = self.case[1]()
            ib = InteriorBasis(m, e)

            @BilinearForm
            def bilinf(u, v, w):
                return ddot(dd(u), dd(v))

            @LinearForm
            def linf(v, w):
                return 1. * v

            K = asm(bilinf, ib)
            f = asm(linf, ib)

            x = solve(*condense(K, f, D=ib.get_dofs().all()))

            X = ib.interpolate(x)

            def exact(x):
                return (x ** 2 - 2. * x ** 3 + x ** 4) / 24.

            @Functional
            def error(w):
                return (w.w - exact(w.x)) ** 2

            L2 = np.sqrt(error.assemble(ib, w=X))

            L2s.append(L2)
            hs.append(m.param())
            m.refine()

        hs = np.array(hs)
        L2s = np.array(L2s)
        pfit = np.polyfit(np.log10(hs), np.log10(L2s), 1)
        self.assertGreater(pfit[0], self.limits[0])
        self.assertLess(pfit[0], self.limits[1])
        self.assertLess(L2s[-1], self.abs_limit)
示例#13
0
    def runTest(self):
        m = MeshLine(np.linspace(0., 1.))
        m.refine(2)
        e = ElementLineP1()
        ib = InteriorBasis(m, e)
        fb = FacetBasis(m, e)

        @linear_form
        def boundary_flux(v, dv, w):
            return -v * (w.x[0] == 1.)

        L = asm(laplace, ib)
        b = asm(boundary_flux, fb)
        D = m.nodes_satisfying(lambda x: x == 0.0)
        I = ib.complement_dofs(D)  # noqa E741
        u = solve(*condense(L, b, I=I))  # noqa E741

        self.assertTrue(np.sum(np.abs(u + m.p[0, :])) < 1e-10)
示例#14
0
    def runTest(self):
        m = MeshLine(np.linspace(0., 1.)).refined(2)
        ib = InteriorBasis(m, self.e)
        m.define_boundary('left', lambda x: x[0] == 0.0)
        m.define_boundary('right', lambda x: x[0] == 1.0)
        fb = FacetBasis(m, self.e, facets=m.boundaries['right'])

        @LinearForm
        def boundary_flux(v, w):
            return -w.x[0] * v

        L = asm(laplace, ib)
        b = asm(boundary_flux, fb)
        D = ib.find_dofs()['left'].all()
        I = ib.complement_dofs(D)  # noqa E741
        u = solve(*condense(L, b, I=I))  # noqa E741

        np.testing.assert_array_almost_equal(u[ib.nodal_dofs[0]], -m.p[0], -10)
示例#15
0
def test_periodic_mesh_assembly(m, mdgtype, etype, check1, check2):
    def _sort(ix):
        # sort index arrays so that ix[0] matches
        return ix[np.argsort(np.sum(m.p, axis=0)[ix])]

    mp = mdgtype.periodic(m, _sort(m.nodes_satisfying(check1)),
                          _sort(m.nodes_satisfying(check2)))
    basis = Basis(mp, etype())
    A = laplace.assemble(basis)

    f = unit_load.assemble(basis)
    D = basis.get_dofs()
    x = solve(*condense(A, f, D=D))

    if m.dim() == 2:
        assert_almost_equal(x.max(), 0.125)
    else:
        assert_almost_equal(x.max(), 0.07389930610869411, decimal=3)
    assert not np.isnan(x).any()
示例#16
0
    def runTest(self):
        @bilinear_form
        def dudv(u, du, v, dv, w):
            return sum(du * dv)

        m = self.mesh()
        m.refine(4)

        ib = InteriorBasis(m, self.elem())

        A = asm(dudv, ib)

        D = ib.get_dofs().all()
        I = ib.complement_dofs(D)

        for X in self.funs:
            x = self.set_bc(X, ib)
            Xh = x.copy()
            x = solve(*condense(A, 0 * x, x=x, I=I))
            self.assertLessEqual(np.sum(x - Xh), 1e-10)
示例#17
0
def laplace(m, **params):
    """Solve the Laplace equation using the FEM.

    Parameters
    ----------
    m
        A Mesh object.

    """
    e = ElementTriP1()
    basis = CellBasis(m, e)
    A = laplacian.assemble(basis)
    b = unit_load.assemble(basis)
    u = solve(*condense(A, b, I=m.interior_nodes()))

    # evaluate the error estimators
    fbasis = [InteriorFacetBasis(m, e, side=i) for i in [0, 1]]
    w = {"u" + str(i + 1): fbasis[i].interpolate(u) for i in [0, 1]}

    @Functional
    def interior_residual(w):
        h = w.h
        return h**2

    eta_K = interior_residual.elemental(basis)

    @Functional
    def edge_jump(w):
        h = w.h
        n = w.n
        dw1 = grad(w["u1"])
        dw2 = grad(w["u2"])
        return h * ((dw1[0] - dw2[0]) * n[0] + (dw1[1] - dw2[1]) * n[1])**2

    eta_E = edge_jump.elemental(fbasis[0], **w)

    tmp = np.zeros(m.facets.shape[1])
    np.add.at(tmp, fbasis[0].find, eta_E)
    eta_E = np.sum(0.5 * tmp[m.t2f], axis=0)

    return eta_E + eta_K
示例#18
0
    def runTest(self):
        """Solve Stokes problem, try splitting and other small things."""

        m = MeshTri().refined()
        m = m.refined(3).with_boundaries({
            'up': lambda x: x[1] == 1.,
            'rest': lambda x: x[1] != 1.,
        })

        e = ElementVectorH1(ElementTriP2()) * ElementTriP1()

        basis = CellBasis(m, e)

        @BilinearForm
        def bilinf(u, p, v, q, w):
            from skfem.helpers import grad, ddot, div
            return (ddot(grad(u), grad(v)) - div(u) * q - div(v) * p
                    - 1e-2 * p * q)

        S = asm(bilinf, basis)

        D = basis.find_dofs(skip=['u^2'])
        x = basis.zeros()
        x[D['up'].all('u^1^1')] = .1

        x = solve(*condense(S, x=x, D=D))

        (u, u_basis), (p, p_basis) = basis.split(x)

        self.assertEqual(len(u), m.p.shape[1] * 2 + m.facets.shape[1] * 2)
        self.assertEqual(len(p), m.p.shape[1])

        self.assertTrue(np.sum(p - x[basis.nodal_dofs[2]]) < 1e-8)

        U, P = basis.interpolate(x)
        self.assertTrue(isinstance(U.value, np.ndarray))
        self.assertTrue(isinstance(P.value, np.ndarray))

        self.assertTrue((basis.doflocs[:, D['up'].all()][1] == 1.).all())
gamma = 0.4 * delta**2
beta = 1.25
lambda_ = beta
g = gamma

mesh = MeshTet.init_tensor(np.linspace(0, L, 10 + 1), np.linspace(0, W, 3 + 1),
                           np.linspace(0, W, 3 + 1))

basis = InteriorBasis(mesh, ElementVectorH1(ElementTetP1()))

clamped = basis.get_dofs(lambda x: x[0] == 0.0).all()
free = basis.complement_dofs(clamped)

K = asm(linear_elasticity(lambda_, mu), basis)


@LinearForm
def load(v, w):
    return -rho * g * v.value[2]


f = asm(load, basis)

u = solve(*condense(K, f, I=free))

deformed = MeshTet(mesh.p + u[basis.nodal_dofs], mesh.t)
deformed.save("deformed.xdmf")

u_magnitude = np.linalg.norm(u.reshape((-1, 3)), axis=1)
print("min/max u:", min(u_magnitude), max(u_magnitude))
with TimeSeriesWriter(Path(__file__).with_suffix(".xdmf")) as writer:

    writer.write_points_cells(embed(mesh.p.T), {"triangle": mesh.t.T})

    t = 0.0
    while t < t_final:
        t += dt

        # Step 1: momentum prediction

        uv = skfem.solve(
            *skfem.condense(
                K_lhs,
                K_rhs @ uv_ - P @ (2 * p_ - p__) - skfem.asm(
                    acceleration, basis["u"], wind=basis["u"].interpolate(u)),
                uv0,
                D=dirichlet["u"],
            ),
            solver=solvers[0],
        )

        # Step 2: pressure correction

        dp = skfem.solve(*skfem.condense(L["p"], (B / dt) @ uv,
                                         D=dirichlet["p"]),
                         solver=solvers[1])

        # Step 3: velocity correction

        p = p_ + dp
示例#21
0
    def runTest(self):
        m = self.case[0]().refined(self.prerefs)

        hs = []
        L2s = []

        for itr in range(3):
            e = self.case[1]()
            ib = InteriorBasis(m, e)

            t = 1.
            E = 1.
            nu = 0.3
            D = E * t ** 3 / (12. * (1. - nu ** 2))

            @BilinearForm
            def bilinf(u, v, w):

                def C(T):
                    trT = T[0, 0] + T[1, 1]
                    return E / (1. + nu) * \
                        np.array([[T[0, 0] + nu / (1. - nu) * trT, T[0, 1]],
                                  [T[1, 0], T[1, 1] + nu / (1. - nu) * trT]])

                return t ** 3 / 12.0 * ddot(C(dd(u)), dd(v))

            def load(x):
                return np.sin(np.pi * x[0]) * np.sin(np.pi * x[1])

            @LinearForm
            def linf(v, w):
                return load(w.x) * v

            K = asm(bilinf, ib)
            f = asm(linf, ib)

            # TODO fix boundary conditions
            # u_x should be zero on top/bottom
            # u_y should be zero on left/right
            x = solve(*condense(K, f, D=ib.get_dofs().all('u')))

            X = ib.interpolate(x)

            def exact(x):
                return 1. / (4. * D * np.pi ** 4) * load(x)

            @Functional
            def error(w):
                return (w.w - exact(w.x)) ** 2

            L2 = np.sqrt(error.assemble(ib, w=X))

            L2s.append(L2)
            hs.append(m.param())
            m = m.refined()

        hs = np.array(hs)
        L2s = np.array(L2s)
        pfit = np.polyfit(np.log10(hs), np.log10(L2s), 1)
        self.assertGreater(pfit[0], self.limits[0])
        self.assertLess(pfit[0], self.limits[1])
        self.assertLess(L2s[-1], self.abs_limit)
示例#22
0
uv0 = np.zeros(basis["u"].N)
inlet_dofs = basis["u"].get_dofs(mesh.boundaries["inlet"]).all("u^1")
inlet_y_lim = [p.x[1] for p in channel.lines[3].points[::-1]]
monic = np.polynomial.polynomial.Polynomial.fromroots(inlet_y_lim)
uv0[inlet_dofs] = -6 * monic(basis["u"].doflocs[1, inlet_dofs]) / inlet_y_lim[1] ** 2


def embed(xy: np.ndarray) -> np.ndarray:
    return np.pad(xy, ((0, 0), (0, 1)), "constant")


solvers = [
    pyamgcl.solver(
        pyamgcl.amg(
            skfem.condense(K_lhs, D=dirichlet["u"], expand=False),
            {"coarsening.type": "aggregation", "relax.type": "ilu0"},
        ),
        {"type": "cg"},
    ),
    pyamgcl.solver(
        pyamgcl.amg(skfem.condense(L["p"], D=dirichlet["p"], expand=False)),
        {"type": "cg"},
    ),
    pyamgcl.solver(
        pyamgcl.amg(
            skfem.condense(M / dt, D=dirichlet["u"], expand=False),
            {"relax.type": "gauss_seidel"},
        ),
        {"type": "cg"},
    ),
示例#23
0
t = 0

with TimeSeriesWriter("channel.xdmf") as writer:

    writer.write_points_cells(mesh.p.T, {"triangle": mesh.t.T})

    while t < t_final:

        t += dt

        # Step 1: Momentum prediction (Ern & Guermond 2002, eq. 7.40, p. 274)

        uv = skfem.solve(*skfem.condense(
            K,
            (M / dt) @ uv_ - P @ (2 * p_ - p__),
            np.zeros_like(uv_),
            D=dirichlet["u"],
        ))

        # Step 2: Projection (Ern & Guermond 2002, eq. 7.41, p. 274)

        dp = np.zeros(basis["p"].N)
        dp[inlet_pressure_dofs] = p_inlet - p_[inlet_pressure_dofs]

        dp = skfem.solve(*skfem.condense(L["p"], B @ uv, dp, D=dirichlet["p"]))

        # Step 3: Recover pressure and velocity (E. & G. 2002, p. 274)

        p = p_ + dp
        print(min(p), "<= p <= ", max(p))