def test_subdomain_facet_assembly(): def subdomain(x): return np.logical_and( np.logical_and(x[0] > .25, x[0] < .75), np.logical_and(x[1] > .25, x[1] < .75), ) m, e = MeshTri().refined(4), ElementTriP2() cbasis = CellBasis(m, e) cbasis_p0 = cbasis.with_element(ElementTriP0()) sfbasis = FacetBasis(m, e, facets=m.facets_around(subdomain, flip=True)) sfbasis_p0 = sfbasis.with_element(ElementTriP0()) sigma = cbasis_p0.zeros() + 1 @BilinearForm def laplace(u, v, w): return dot(w.sigma * grad(u), grad(v)) A = laplace.assemble(cbasis, sigma=cbasis_p0.interpolate(sigma)) u0 = cbasis.zeros() u0[cbasis.get_dofs(elements=subdomain)] = 1 u0_dofs = cbasis.get_dofs() + cbasis.get_dofs(elements=subdomain) A, b = enforce(A, D=u0_dofs, x=u0) u = solve(A, b) @Functional def measure_current(w): return dot(w.n, w.sigma * grad(w.u)) meas = measure_current.assemble(sfbasis, sigma=sfbasis_p0.interpolate(sigma), u=sfbasis.interpolate(u)) assert_almost_equal(meas, 9.751915526759191)
def test_periodic_loading(m, mdgtype, e): 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(lambda x: x[0] == 0)), _sort(m.nodes_satisfying(lambda x: x[0] == 1))) basis = Basis(mp, e) A = laplace.assemble(basis) M = mass.assemble(basis) @LinearForm def linf(v, w): return np.sin(2. * np.pi * w.x[0]) * v f = linf.assemble(basis) x = solve(A + 1e-6 * M, f) def uexact(x): return (1. / (2. * np.pi)**2) * np.sin(2. * np.pi * x[0]) @Functional def func(w): uexact = (1. / (2. * np.pi)**2) * np.sin(2. * np.pi * w.x[0]) return (uexact - w['u'])**2 assert_almost_equal(func.assemble(basis, u=x), 0, decimal=5)
def test_solving_inhomogeneous_laplace(mesh_elem, impose): """Adapted from example 14.""" mesh, elem = mesh_elem m = mesh().refined(4) basis = Basis(m, elem) boundary_basis = FacetBasis(m, elem) boundary_dofs = boundary_basis.get_dofs().flatten() def dirichlet(x): """return a harmonic function""" return ((x[0] + 1.j * x[1])**2).real u = basis.zeros() A = laplace.assemble(basis) u[boundary_dofs] = projection(dirichlet, boundary_basis, I=boundary_dofs) u = solve(*impose(A, x=u, D=boundary_dofs)) @Functional def gradu(w): gradu = w['sol'].grad return dot(gradu, gradu) np.testing.assert_almost_equal(gradu.assemble(basis, sol=basis.interpolate(u)), 8 / 3, decimal=9)
def runTest(self): m = self.mesh().refined(4) basis = InteriorBasis(m, self.elem) boundary_basis = FacetBasis(m, self.elem) boundary_dofs = boundary_basis.get_dofs().flatten() def dirichlet(x): """return a harmonic function""" return ((x[0] + 1.j * x[1])**2).real u = basis.zeros() A = laplace.assemble(basis) u[boundary_dofs] = projection(dirichlet, boundary_basis, I=boundary_dofs) u = solve(*enforce(A, x=u, D=boundary_dofs)) @Functional def gradu(w): gradu = w['sol'].grad return dot(gradu, gradu) self.assertAlmostEqual( gradu.assemble(basis, sol=basis.interpolate(u)), 8 / 3, delta=1e-10, )
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 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)
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)
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)
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]])
def initOnes(self, basis): @bilinear_form def mass(u, du, ddu, v, dv, ddv, w): return u * v @linear_form def ones(v, dv, ddv, w): return 1.0 * v M = asm(mass, basis) f = asm(ones, basis) return solve(M, f)
def initOnes(self, basis): @BilinearForm def mass(u, v, w): return u * v @LinearForm def ones(v, w): return 1. * v M = asm(mass, basis) f = asm(ones, basis) return solve(M, f)
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())
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)
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) - v * (w.x[0] == 0) L = asm(laplace, ib) M = asm(mass, ib) b = asm(boundary_flux, fb) u = solve(L + 1e-6 * M, b) np.testing.assert_array_almost_equal(u[ib.nodal_dofs[0]], m.p[0] - .5, -4)
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)
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)
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) - v * (w.x[0] == 0) L = asm(laplace, ib) M = asm(mass, ib) b = asm(boundary_flux, fb) u = solve(L + 1e-6 * M, b) self.assertTrue(np.sum(np.abs(u - m.p[0, :] + 0.5)) < 1e-4)
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)
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)
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)
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()
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)
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
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))
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))
def runTest(self): dudv = laplace @BilinearForm def uv(u, v, w): return u * v def F(x, y, z): return 2 * x**2 + 2 * y**2 - 6 * x * y * z @LinearForm def fv(v, w): return F(*w.x) * v def G(x, y, z): eps = 1e-6 def circa(a, b): return (a - b < eps) * (a - b > -eps) return (circa(x, 1) * (3 - 3 * y**2 + 2 * y * z**3) + circa(x, 0) * (-y * z**3) + circa(y, 1) * (1 + x - 3 * x**2 + 2 * x * z**3) + circa(y, 0) * (1 + x - x * z**3) + circa(z, 1) * (1 + x + 4 * x * y - x**2 * y**2) + circa(z, 0) * (1 + x - x**2 * y**2)) @LinearForm def gv(v, w): return G(*w.x) * v hs = np.array([]) H1err = np.array([]) L2err = np.array([]) for itr in range(0, 3): m = self.case[0]().refined(self.preref + itr) ib = Basis(m, self.case[1]()) fb = FacetBasis(m, self.case[1]()) A = asm(dudv, ib) f = asm(fv, ib) B = asm(uv, fb) g = asm(gv, fb) u = solve(A + B, f + g) L2, H1 = self.compute_error(m, ib, u) hs = np.append(hs, m.param()) L2err = np.append(L2err, L2) H1err = np.append(H1err, H1) pfit = np.polyfit(np.log10(hs), np.log10(np.sqrt(L2err**2 + H1err**2)), 1) self.assertGreater(pfit[0], self.limits[0]) self.assertLess(pfit[0], self.limits[1]) self.assertLess(H1err[-1], 0.08) self.assertLess(L2err[-1], 0.005)
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)
def runTest(self): @BilinearForm def bilinf_A(sigma, tau, w): from skfem.models.helpers import dot return dot(sigma, tau) @BilinearForm def bilinf_B(sigma, v, w): return sigma.df * v @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) Hdivs = np.zeros(Nitrs) hs = np.zeros(Nitrs) for itr in range(Nitrs): ib1, ib2 = self.create_basis(m) A = asm(bilinf_A, ib1) B = asm(bilinf_B, ib1, ib2) b = np.concatenate((np.zeros(A.shape[0]), -asm(load, ib2))) from scipy.sparse import bmat K = bmat([[A, B.T], [B, None]]).tocsr() x = solve(K, b) # calculate error sigma, u = np.split(x, [A.shape[0]]) L2s[itr] = self.compute_L2(m, ib2, u) Hdivs[itr] = self.compute_Hdiv(m, ib1, sigma) hs[itr] = m.param() m.refine() rateL2 = np.polyfit(np.log(hs), np.log(L2s), 1)[0] rateHdiv = np.polyfit(np.log(hs), np.log(Hdivs), 1)[0] self.assertLess(np.abs(rateL2 - self.rateL2), self.eps, msg='observed L2 rate: {}'.format(rateL2)) self.assertLess(np.abs(rateHdiv - self.rateHdiv), self.eps, msg='observed Hdiv rate: {}'.format(rateHdiv)) self.assertLess(Hdivs[-1], self.Hdivbound) self.assertLess(L2s[-1], self.L2bound)
with TimeSeriesWriter(Path(__file__).with_suffix(".xdmf").name) 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