def test_assemble_iiform(self): mesh = Mesh1D(resolution=(1, )) Q1 = QuadFE(1, 'DQ1') dofhandler = DofHandler(mesh, Q1) dofhandler.distribute_dofs() phi = Basis(dofhandler, 'u') k = Explicit(lambda x, y: x * y, n_variables=2, dim=1) kernel = Kernel(k) form = IIForm(kernel, test=phi, trial=phi) assembler = Assembler(form, mesh) assembler.assemble() Ku = Nodal(lambda x: 1 / 3 * x, basis=phi) #af = assembler.af[0]['bilinear'] M = assembler.get_matrix().toarray() u = Nodal(lambda x: x, basis=phi) u_vec = u.data() self.assertTrue(np.allclose(M.dot(u_vec), Ku.data()))
def test_assemble_ipform(self): # ===================================================================== # Test 7: Assemble Kernel # ===================================================================== mesh = Mesh1D(resolution=(10, )) Q1 = QuadFE(1, 'DQ1') dofhandler = DofHandler(mesh, Q1) dofhandler.distribute_dofs() phi = Basis(dofhandler, 'u') k = Explicit(lambda x, y: x * y, n_variables=2, dim=1) kernel = Kernel(k) form = IPForm(kernel, test=phi, trial=phi) assembler = Assembler(form, mesh) assembler.assemble() #af = assembler.af[0]['bilinear'] M = assembler.get_matrix().toarray() u = Nodal(lambda x: x, basis=phi) v = Nodal(lambda x: 1 - x, basis=phi) u_vec = u.data() v_vec = v.data() I = v_vec.T.dot(M.dot(u_vec)) self.assertAlmostEqual(I[0, 0], 1 / 18)
def test02_1d_dirichlet_higher_order(self): mesh = Mesh1D() for etype in ['Q2', 'Q3']: element = QuadFE(1, etype) dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # Basis functions ux = Basis(dofhandler, 'ux') u = Basis(dofhandler, 'u') # Exact solution ue = Nodal(f=lambda x: x * (1 - x), basis=u) # Define coefficient functions one = Constant(1) two = Constant(2) # Define forms a = Form(kernel=Kernel(one), trial=ux, test=ux) L = Form(kernel=Kernel(two), test=u) problem = [a, L] # Assemble problem assembler = Assembler(problem, mesh) assembler.assemble() A = assembler.get_matrix() b = assembler.get_vector() # Set up linear system system = LinearSystem(u, A=A, b=b) # Boundary functions bnd_left = lambda x: np.abs(x) < 1e-9 bnd_right = lambda x: np.abs(1 - x) < 1e-9 # Mark mesh mesh.mark_region('left', bnd_left, entity_type='vertex') mesh.mark_region('right', bnd_right, entity_type='vertex') # Add Dirichlet constraints to system system.add_dirichlet_constraint('left', 0) system.add_dirichlet_constraint('right', 0) # Solve system system.solve_system() system.resolve_constraints() # Compare solution with the exact solution ua = system.get_solution(as_function=True) self.assertTrue(np.allclose(ua.data(), ue.data()))
def test01_solve_2d(self): """ Solve a simple 2D problem with no hanging nodes """ mesh = QuadMesh(resolution=(5, 5)) # Mark dirichlet boundaries mesh.mark_region('left', lambda x, dummy: np.abs(x) < 1e-9, entity_type='half_edge') mesh.mark_region('right', lambda x, dummy: np.abs(x - 1) < 1e-9, entity_type='half_edge') Q1 = QuadFE(mesh.dim(), 'Q1') dQ1 = DofHandler(mesh, Q1) dQ1.distribute_dofs() phi = Basis(dQ1, 'u') phi_x = Basis(dQ1, 'ux') phi_y = Basis(dQ1, 'uy') problem = [ Form(1, test=phi_x, trial=phi_x), Form(1, test=phi_y, trial=phi_y), Form(0, test=phi) ] assembler = Assembler(problem, mesh) assembler.add_dirichlet('left', dir_fn=0) assembler.add_dirichlet('right', dir_fn=1) assembler.assemble() # Get matrix dirichlet correction and right hand side A = assembler.get_matrix().toarray() x0 = assembler.assembled_bnd() b = assembler.get_vector() ua = np.zeros((phi.n_dofs(), 1)) int_dofs = assembler.get_dofs('interior') ua[int_dofs, 0] = np.linalg.solve(A, b - x0) dir_bc = assembler.get_dirichlet() dir_vals = np.array([dir_bc[dof] for dof in dir_bc]) dir_dofs = [dof for dof in dir_bc] ua[dir_dofs] = dir_vals ue_fn = Nodal(f=lambda x: x[:, 0], basis=phi) ue = ue_fn.data() self.assertTrue(np.allclose(ue, ua)) self.assertTrue(np.allclose(x0 + A.dot(ua[int_dofs, 0]), b))
def test01_solve_1d(self): """ Test solving 1D systems """ mesh = Mesh1D(resolution=(20, )) mesh.mark_region('left', lambda x: np.abs(x) < 1e-9) mesh.mark_region('right', lambda x: np.abs(x - 1) < 1e-9) Q1 = QuadFE(1, 'Q1') dQ1 = DofHandler(mesh, Q1) dQ1.distribute_dofs() phi = Basis(dQ1, 'u') phi_x = Basis(dQ1, 'ux') problem = [Form(1, test=phi_x, trial=phi_x), Form(0, test=phi)] assembler = Assembler(problem, mesh) assembler.add_dirichlet('left', dir_fn=0) assembler.add_dirichlet('right', dir_fn=1) assembler.assemble() # Get matrix dirichlet correction and right hand side A = assembler.get_matrix().toarray() x0 = assembler.assembled_bnd() b = assembler.get_vector() ua = np.zeros((phi.n_dofs(), 1)) int_dofs = assembler.get_dofs('interior') ua[int_dofs, 0] = np.linalg.solve(A, b - x0) dir_bc = assembler.get_dirichlet() dir_vals = np.array([dir_bc[dof] for dof in dir_bc]) dir_dofs = [dof for dof in dir_bc] ua[dir_dofs] = dir_vals ue_fn = Nodal(f=lambda x: x[:, 0], basis=phi) ue = ue_fn.data() self.assertTrue(np.allclose(ue, ua)) self.assertTrue(np.allclose(x0 + A.dot(ua[int_dofs, 0]), b))
def test08_1d_sampled_rhs(self): # # Mesh # mesh = Mesh1D(resolution=(1, )) mesh.mark_region('left', lambda x: np.abs(x) < 1e-9, on_boundary=True) mesh.mark_region('right', lambda x: np.abs(1 - x) < 1e-9, on_boundary=True) # # Elements # Q3 = QuadFE(1, 'Q3') dofhandler = DofHandler(mesh, Q3) dofhandler.distribute_dofs() # # Basis # v = Basis(dofhandler, 'u') vx = Basis(dofhandler, 'ux') # # Define sampled right hand side and exact solution # xv = dofhandler.get_dof_vertices() n_points = dofhandler.n_dofs() n_samples = 6 a = np.arange(n_samples) f = lambda x, a: a * x u = lambda x, a: a / 6 * (x - x**3) + x fdata = np.zeros((n_points, n_samples)) udata = np.zeros((n_points, n_samples)) for i in range(n_samples): fdata[:, i] = f(xv, a[i]).ravel() udata[:, i] = u(xv, a[i]).ravel() # Define sampled function fn = Nodal(data=fdata, basis=v) ue = Nodal(data=udata, basis=v) # # Forms # one = Constant(1) a = Form(Kernel(one), test=vx, trial=vx) L = Form(Kernel(fn), test=v) problem = [a, L] # # Assembler # assembler = Assembler(problem, mesh) assembler.assemble() A = assembler.get_matrix() b = assembler.get_vector() # # Linear System # system = LinearSystem(v, A=A, b=b) # Set constraints system.add_dirichlet_constraint('left', 0) system.add_dirichlet_constraint('right', 1) #system.set_constraint_relation() #system.incorporate_constraints() # Solve and resolve constraints system.solve_system() #system.resolve_constraints() # Extract finite element solution ua = system.get_solution(as_function=True) # Check that the solution is close print(ue.data()[:, [0]]) print(ua.data()) self.assertTrue(np.allclose(ue.data()[:, [0]], ua.data()))
def test05_2d_dirichlet(self): """ Two dimensional Dirichlet problem with hanging nodes """ # # Define mesh # mesh = QuadMesh(resolution=(1, 2)) mesh.cells.get_child(1).mark(1) mesh.cells.refine(refinement_flag=1) mesh.cells.refine() # # Mark left and right boundaries # bm_left = lambda x, dummy: np.abs(x) < 1e-9 bm_right = lambda x, dummy: np.abs(1 - x) < 1e-9 mesh.mark_region('left', bm_left, entity_type='half_edge') mesh.mark_region('right', bm_right, entity_type='half_edge') for etype in ['Q1', 'Q2', 'Q3']: # # Element # element = QuadFE(2, etype) dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # # Basis # u = Basis(dofhandler, 'u') ux = Basis(dofhandler, 'ux') uy = Basis(dofhandler, 'uy') # # Construct forms # ue = Nodal(f=lambda x: x[:, 0], basis=u) ax = Form(kernel=Kernel(Constant(1)), trial=ux, test=ux) ay = Form(kernel=Kernel(Constant(1)), trial=uy, test=uy) L = Form(kernel=Kernel(Constant(0)), test=u) problem = [ax, ay, L] # # Assemble # assembler = Assembler(problem, mesh) assembler.assemble() # # Get system matrices # A = assembler.get_matrix() b = assembler.get_vector() # # Linear System # system = LinearSystem(u, A=A, b=b) # # Constraints # # Add dirichlet conditions system.add_dirichlet_constraint('left', ue) system.add_dirichlet_constraint('right', ue) # # Solve # system.solve_system() #system.resolve_constraints() # # Check solution # ua = system.get_solution(as_function=True) self.assertTrue(np.allclose(ua.data(), ue.data()))
def test01_1d_dirichlet_linear(self): """ Solve one dimensional boundary value problem with dirichlet conditions on left and right """ # # Define mesh # mesh = Mesh1D(resolution=(10, )) for etype in ['Q1', 'Q2', 'Q3']: element = QuadFE(1, etype) dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() phi = Basis(dofhandler) # # Exact solution # ue = Nodal(f=lambda x: x, basis=phi) # # Define Basis functions # u = Basis(dofhandler, 'u') ux = Basis(dofhandler, 'ux') # # Define bilinear form # one = Constant(1) zero = Constant(0) a = Form(kernel=Kernel(one), trial=ux, test=ux) L = Form(kernel=Kernel(zero), test=u) problem = [a, L] # # Assemble # assembler = Assembler(problem, mesh) assembler.assemble() # # Form linear system # A = assembler.get_matrix() b = assembler.get_vector() system = LinearSystem(u, A=A, b=b) # # Dirichlet conditions # # Boundary functions bm_left = lambda x: np.abs(x) < 1e-9 bm_rght = lambda x: np.abs(x - 1) < 1e-9 # Mark boundary regions mesh.mark_region('left', bm_left, on_boundary=True) mesh.mark_region('right', bm_rght, on_boundary=True) # Add Dirichlet constraints system.add_dirichlet_constraint('left', ue) system.add_dirichlet_constraint('right', ue) # # Solve system # #system.solve_system() system.solve_system() # # Get solution # #ua = system.get_solution(as_function=True) uaa = system.get_solution(as_function=True) #uaa = uaa.data().ravel() # Compare with exact solution #self.assertTrue(np.allclose(ua.data(), ue.data())) self.assertTrue(np.allclose(uaa.data(), ue.data()))
def test04_1d_periodic(self): # # Dirichlet Problem on a Periodic Mesh # # Define mesh, element mesh = Mesh1D(resolution=(100, ), periodic=True) element = QuadFE(1, 'Q3') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # Basis functions u = Basis(dofhandler, 'u') ux = Basis(dofhandler, 'ux') # Exact solution ue = Nodal(f=lambda x: np.sin(2 * np.pi * x), basis=u) # # Mark dirichlet regions # bnd_left = lambda x: np.abs(x) < 1e-9 mesh.mark_region('left', bnd_left, entity_type='vertex') # # Set up forms # # Bilinear form a = Form(kernel=Kernel(Constant(1)), trial=ux, test=ux) # Linear form f = Explicit(lambda x: 4 * np.pi**2 * np.sin(2 * np.pi * x), dim=1) L = Form(kernel=Kernel(f), test=u) # # Assemble # problem = [a, L] assembler = Assembler(problem, mesh) assembler.assemble() A = assembler.get_matrix() b = assembler.get_vector() # # Linear System # system = LinearSystem(u, A=A, b=b) # Add dirichlet constraint system.add_dirichlet_constraint('left', 0, on_boundary=False) # Assemble constraints #system.set_constraint_relation() #system.incorporate_constraints() system.solve_system() #system.resolve_constraints() # Compare with interpolant of exact solution ua = system.get_solution(as_function=True) #plot = Plot(2) #plot.line(ua) #plot.line(ue) self.assertTrue(np.allclose(ua.data(), ue.data()))
def test_ft(): plot = Plot() vb = Verbose() # ============================================================================= # Parameters # ============================================================================= # # Flow # # permeability field phi = Constant(1) # porosity D = Constant(0.0252) # dispersivity K = Constant(1) # permeability # ============================================================================= # Mesh and Elements # ============================================================================= # Mesh mesh = QuadMesh(resolution=(30, 30)) # Mark left and right regions mesh.mark_region('left', lambda x, y: np.abs(x) < 1e-9, entity_type='half_edge') mesh.mark_region('right', lambda x, y: np.abs(x - 1) < 1e-9, entity_type='half_edge') # Elements p_element = QuadFE(2, 'Q1') # element for pressure c_element = QuadFE(2, 'Q1') # element for concentration # Dofhandlers p_dofhandler = DofHandler(mesh, p_element) c_dofhandler = DofHandler(mesh, c_element) p_dofhandler.distribute_dofs() c_dofhandler.distribute_dofs() # Basis functions p_ux = Basis(p_dofhandler, 'ux') p_uy = Basis(p_dofhandler, 'uy') p_u = Basis(p_dofhandler, 'u') p_inflow = lambda x, y: np.ones(shape=x.shape) p_outflow = lambda x, y: np.zeros(shape=x.shape) c_inflow = lambda x, y: np.zeros(shape=x.shape) # ============================================================================= # Solve the steady state flow equations # ============================================================================= vb.comment('Solving flow equations') # Define problem flow_problem = [ Form(1, test=p_ux, trial=p_ux), Form(1, test=p_uy, trial=p_uy), Form(0, test=p_u) ] # Assemble vb.tic('assembly') assembler = Assembler(flow_problem) assembler.add_dirichlet('left', 1) assembler.add_dirichlet('right', 0) assembler.assemble() vb.toc() # Solve linear system vb.tic('solve') A = assembler.get_matrix().tocsr() b = assembler.get_vector() x0 = assembler.assembled_bnd() # Interior nodes pa = np.zeros((p_u.n_dofs(), 1)) int_dofs = assembler.get_dofs('interior') pa[int_dofs, 0] = spla.spsolve(A, b - x0) # Resolve Dirichlet conditions dir_dofs, dir_vals = assembler.get_dirichlet(asdict=False) pa[dir_dofs] = dir_vals vb.toc() # Pressure function pfn = Nodal(data=pa, basis=p_u) px = pfn.differentiate((1, 0)) py = pfn.differentiate((1, 1)) #plot.contour(px) #plt.show() # ============================================================================= # Transport Equations # ============================================================================= # Specify initial condition c0 = Constant(1) dt = 1e-1 T = 6 N = int(np.ceil(T / dt)) c = Basis(c_dofhandler, 'c') cx = Basis(c_dofhandler, 'cx') cy = Basis(c_dofhandler, 'cy') print('assembling transport equations') k_phi = Kernel(f=phi) k_advx = Kernel(f=[K, px], F=lambda K, px: -K * px) k_advy = Kernel(f=[K, py], F=lambda K, py: -K * py) tht = 1 m = [Form(kernel=k_phi, test=c, trial=c)] s = [ Form(kernel=k_advx, test=c, trial=cx), Form(kernel=k_advy, test=c, trial=cy), Form(kernel=Kernel(D), test=cx, trial=cx), Form(kernel=Kernel(D), test=cy, trial=cy) ] problems = [m, s] assembler = Assembler(problems) assembler.add_dirichlet('left', 0, i_problem=0) assembler.add_dirichlet('left', 0, i_problem=1) assembler.assemble() x0 = assembler.assembled_bnd() # Interior nodes int_dofs = assembler.get_dofs('interior') # Dirichlet conditions dir_dofs, dir_vals = assembler.get_dirichlet(asdict=False) # System matrices M = assembler.get_matrix(i_problem=0) S = assembler.get_matrix(i_problem=1) # Initialize c0 and cp c0 = np.ones((c.n_dofs(), 1)) cp = np.zeros((c.n_dofs(), 1)) c_fn = Nodal(data=c0, basis=c) # # Compute solution # print('time stepping') for i in range(N): # Build system A = M + tht * dt * S b = M.dot(c0[int_dofs]) - (1 - tht) * dt * S.dot(c0[int_dofs]) # Solve linear system cp[int_dofs, 0] = spla.spsolve(A, b) # Add Dirichlet conditions cp[dir_dofs] = dir_vals # Record current iterate c_fn.add_samples(data=cp) # Update c0 c0 = cp.copy() #plot.contour(c_fn, n_sample=i) # # Quantity of interest # def F(c, px, py, entity=None): """ Compute c(x,y,t)*(grad p * n) """ n = entity.unit_normal() return c * (px * n[0] + py * n[1]) px.set_subsample(i=np.arange(41)) py.set_subsample(i=np.arange(41)) #kernel = Kernel(f=[c_fn,px,py], F=F) kernel = Kernel(c_fn) #print(kernel.n_subsample()) form = Form(kernel, flag='right', dmu='ds') assembler = Assembler(form, mesh=mesh) assembler.assemble() QQ = assembler.assembled_forms()[0].aggregate_data()['array'] Q = np.array([assembler.get_scalar(i_sample=i) for i in np.arange(N + 1)]) t = np.linspace(0, T, N + 1) plt.plot(t, Q) plt.show() print(Q)
def test03_solve_2d(self): """ Test problem with Neumann conditions """ # # Define Mesh # mesh = QuadMesh(resolution=(2, 1)) mesh.cells.get_child(1).mark(1) mesh.cells.refine(refinement_flag=1) # Mark left and right boundaries bm_left = lambda x, dummy: np.abs(x) < 1e-9 bm_right = lambda x, dummy: np.abs(1 - x) < 1e-9 mesh.mark_region('left', bm_left, entity_type='half_edge') mesh.mark_region('right', bm_right, entity_type='half_edge') for etype in ['Q1', 'Q2', 'Q3']: # # Define element and basis type # element = QuadFE(2, etype) dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() u = Basis(dofhandler, 'u') ux = Basis(dofhandler, 'ux') uy = Basis(dofhandler, 'uy') # # Exact solution # ue = Nodal(f=lambda x: x[:, 0], basis=u) # # Set up forms # one = Constant(1) ax = Form(kernel=Kernel(one), trial=ux, test=ux) ay = Form(kernel=Kernel(one), trial=uy, test=uy) L = Form(kernel=Kernel(Constant(0)), test=u) Ln = Form(kernel=Kernel(one), test=u, dmu='ds', flag='right') problem = [ax, ay, L, Ln] assembler = Assembler(problem, mesh) assembler.add_dirichlet('left', dir_fn=0) assembler.add_hanging_nodes() assembler.assemble() # # Automatic solve # ya = assembler.solve() self.assertTrue(np.allclose(ue.data()[:, 0], ya)) # # Explicit solve # # System Matrices A = assembler.get_matrix().toarray() b = assembler.get_vector() x0 = assembler.assembled_bnd() # Solve linear system xa = np.zeros(u.n_dofs()) int_dofs = assembler.get_dofs('interior') xa[int_dofs] = np.linalg.solve(A, b - x0) # Resolve Dirichlet conditions dir_dofs, dir_vals = assembler.get_dirichlet(asdict=False) xa[dir_dofs] = dir_vals[:, 0] # Resolve hanging nodes C = assembler.hanging_node_matrix() xa += C.dot(xa) self.assertTrue(np.allclose(ue.data()[:, 0], xa))
def test02_solve_2d(self): """ Solve 2D problem with hanging nodes """ # Mesh mesh = QuadMesh(resolution=(2, 2)) mesh.cells.get_leaves()[0].mark(0) mesh.cells.refine(refinement_flag=0) mesh.mark_region('left', lambda x, y: abs(x) < 1e-9, entity_type='half_edge') mesh.mark_region('right', lambda x, y: abs(x - 1) < 1e-9, entity_type='half_edge') # Element Q1 = QuadFE(2, 'Q1') dofhandler = DofHandler(mesh, Q1) dofhandler.distribute_dofs() dofhandler.set_hanging_nodes() # Basis functions phi = Basis(dofhandler, 'u') phi_x = Basis(dofhandler, 'ux') phi_y = Basis(dofhandler, 'uy') # # Define problem # problem = [ Form(1, trial=phi_x, test=phi_x), Form(1, trial=phi_y, test=phi_y), Form(0, test=phi) ] ue = Nodal(f=lambda x: x[:, 0], basis=phi) xe = ue.data().ravel() # # Assemble without Dirichlet and without Hanging Nodes # assembler = Assembler(problem, mesh) assembler.add_dirichlet('left', dir_fn=0) assembler.add_dirichlet('right', dir_fn=1) assembler.add_hanging_nodes() assembler.assemble() # Get dofs for different regions int_dofs = assembler.get_dofs('interior') # Get matrix and vector A = assembler.get_matrix().toarray() b = assembler.get_vector() x0 = assembler.assembled_bnd() # Solve linear system xa = np.zeros(phi.n_dofs()) xa[int_dofs] = np.linalg.solve(A, b - x0) # Resolve Dirichlet conditions dir_dofs, dir_vals = assembler.get_dirichlet(asdict=False) xa[dir_dofs] = dir_vals[:, 0] # Resolve hanging nodes C = assembler.hanging_node_matrix() xa += C.dot(xa) self.assertTrue(np.allclose(xa, xe))
def test_integrals_2d(self): """ Test Assembly of some 2D systems """ mesh = QuadMesh(box=[1, 2, 1, 2], resolution=(2, 2)) mesh.cells.get_leaves()[0].mark(0) mesh.cells.refine(refinement_flag=0) # Kernel kernel = Kernel(Explicit(f=lambda x: x[:, 0] * x[:, 1], dim=2)) problem = Form(kernel) assembler = Assembler(problem, mesh=mesh) assembler.assemble() self.assertAlmostEqual(assembler.get_scalar(), 9 / 4) # # Linear forms (x,x) and (x,x') over [1,2]^2 = 7/3, 3/2 # # Elements Q1 = QuadFE(mesh.dim(), 'Q1') Q2 = QuadFE(mesh.dim(), 'Q2') Q3 = QuadFE(mesh.dim(), 'Q3') # Dofhandlers dQ1 = DofHandler(mesh, Q1) dQ2 = DofHandler(mesh, Q2) dQ3 = DofHandler(mesh, Q3) # Distribute dofs [d.distribute_dofs() for d in [dQ1, dQ2, dQ3]] for dQ in [dQ1, dQ2, dQ3]: # Basis phi = Basis(dQ, 'u') phi_x = Basis(dQ, 'ux') # Kernel function xfn = Nodal(f=lambda x: x[:, 0], basis=phi) yfn = Nodal(f=lambda x: x[:, 1], basis=phi) # Kernel kernel = Kernel(xfn) # Form problem = [[Form(kernel, test=phi)], [Form(kernel, test=phi_x)]] # Assembly assembler = Assembler(problem, mesh) assembler.assemble() # Check b^Tx = (x,y) b0 = assembler.get_vector(0) self.assertAlmostEqual(np.sum(b0 * yfn.data()[:, 0]), 9 / 4) b1 = assembler.get_vector(1) self.assertAlmostEqual(np.sum(b1 * xfn.data()[:, 0]), 3 / 2) self.assertAlmostEqual(np.sum(b1 * yfn.data()[:, 0]), 0) # # Bilinear forms # # Compute (1,x,y) = 9/4, or (xy, 1, 1) = 9/4 for dQ in [dQ1, dQ2, dQ3]: # Basis phi = Basis(dQ, 'u') phi_x = Basis(dQ, 'ux') phi_y = Basis(dQ, 'uy') # Kernel function xyfn = Explicit(f=lambda x: x[:, 0] * x[:, 1], dim=2) xfn = Nodal(f=lambda x: x[:, 0], basis=phi) yfn = Nodal(f=lambda x: x[:, 1], basis=phi) # Form problems = [[Form(1, test=phi, trial=phi)], [Form(Kernel(xfn), test=phi, trial=phi_x)], [Form(Kernel(xyfn), test=phi_y, trial=phi_x)]] # Assemble assembler = Assembler(problems, mesh) assembler.assemble() x = xfn.data()[:, 0] y = yfn.data()[:, 0] for i_problem in range(3): A = assembler.get_matrix(i_problem) self.assertAlmostEqual(y.T.dot(A.dot(x)), 9 / 4)
def test09_1d_inverse(self): """ Compute the inverse of a matrix and apply it to a vector/matrix. """ # # Mesh # mesh = Mesh1D(resolution=(1, )) mesh.mark_region('left', lambda x: np.abs(x) < 1e-9, on_boundary=True) mesh.mark_region('right', lambda x: np.abs(1 - x) < 1e-9, on_boundary=True) # # Elements # Q3 = QuadFE(1, 'Q3') dofhandler = DofHandler(mesh, Q3) dofhandler.distribute_dofs() # # Basis # u = Basis(dofhandler, 'u') ux = Basis(dofhandler, 'ux') # # Define sampled right hand side and exact solution # xv = dofhandler.get_dof_vertices() n_points = dofhandler.n_dofs() n_samples = 6 a = np.arange(n_samples) ffn = lambda x, a: a * x ufn = lambda x, a: a / 6 * (x - x**3) + x fdata = np.zeros((n_points, n_samples)) udata = np.zeros((n_points, n_samples)) for i in range(n_samples): fdata[:, i] = ffn(xv, a[i]).ravel() udata[:, i] = ufn(xv, a[i]).ravel() # Define sampled function fn = Nodal(data=fdata, basis=u) ue = Nodal(data=udata, basis=u) # # Forms # one = Constant(1) a = Form(Kernel(one), test=ux, trial=ux) L = Form(Kernel(fn), test=u) problem = [[a], [L]] # # Assembler # assembler = Assembler(problem, mesh) assembler.assemble() A = assembler.get_matrix() b = assembler.get_vector(i_problem=1) # # Linear System # system = LinearSystem(u, A=A) # Set constraints system.add_dirichlet_constraint('left', 0) system.add_dirichlet_constraint('right', 1) system.solve_system(b) # Extract finite element solution ua = system.get_solution(as_function=True) system2 = LinearSystem(u, A=A, b=b) # Set constraints system2.add_dirichlet_constraint('left', 0) system2.add_dirichlet_constraint('right', 1) system2.solve_system() u2 = system2.get_solution(as_function=True) # Check that the solution is close self.assertTrue(np.allclose(ue.data()[:, 0], ua.data()[:, 0])) self.assertTrue(np.allclose(ue.data()[:, [0]], u2.data()))
def test01_finite_elements(): """ Test accuracy of the finite element approximation """ # # Construct reference solution # plot = Plot(quickview=False) # Mesh mesh = Mesh1D(resolution=(2**11, )) mesh.mark_region('left', lambda x: np.abs(x) < 1e-10) mesh.mark_region('right', lambda x: np.abs(x - 1) < 1e-10) # Element Q1 = QuadFE(mesh.dim(), 'Q1') dQ1 = DofHandler(mesh, Q1) dQ1.distribute_dofs() # Basis phi = Basis(dQ1, 'v') phi_x = Basis(dQ1, 'vx') # # Covariance # cov = Covariance(dQ1, name='gaussian', parameters={'l': 0.05}) cov.compute_eig_decomp() lmd, V = cov.get_eig_decomp() d = len(lmd) # # Sample and plot full dimensional parameter and solution # n_samples = 1 z = np.random.randn(d, n_samples) q_ref = sample_q0(V, lmd, d, z) print(q_ref.shape) # Define finite element function q_ref_fn = Nodal(data=q_ref, basis=phi) problem = [[Form(q_ref_fn, test=phi_x, trial=phi_x), Form(1, test=phi)], [Form(q_ref_fn, test=phi_x, dmu='dv', flag='right')]] # Define assembler assembler = Assembler(problem) # Incorporate Dirichlet conditions assembler.add_dirichlet('left', 0) assembler.add_dirichlet('right', 1) # Assemble system assembler.assemble() # Solve system u_ref = assembler.solve() # Compute quantity of interest J_ref = u_ref.dot(assembler.get_vector(1)) # Plot fig = plt.figure(figsize=(6, 4)) ax = fig.add_subplot(111) u_ref_fn = Nodal(basis=phi, data=u_ref) ax = plot.line(u_ref_fn, axis=ax) n_levels = 10 J = np.zeros(n_levels) for l in range(10): comment.comment('level: %d' % (l)) # # Mesh # mesh = Mesh1D(resolution=(2**l, )) mesh.mark_region('left', lambda x: np.abs(x) < 1e-10) mesh.mark_region('right', lambda x: np.abs(x - 1) < 1e-10) # # Element # Q1 = QuadFE(mesh.dim(), 'Q1') dQ1 = DofHandler(mesh, Q1) dQ1.distribute_dofs() # # Basis # phi = Basis(dQ1, 'v') phi_x = Basis(dQ1, 'vx') # Define problem problem = [[ Form(q_ref_fn, test=phi_x, trial=phi_x), Form(1, test=phi) ], [Form(q_ref_fn, test=phi_x, dmu='dv', flag='right')]] assembler = Assembler(problem) # Incorporate Dirichlet conditions assembler.add_dirichlet('left', 0) assembler.add_dirichlet('right', 1) assembler.assemble() A = assembler.get_matrix() print('A shape', A.shape) u = assembler.solve() J[l] = u.dot(assembler.get_vector(1)) print(u.shape) print(phi.n_dofs()) ufn = Nodal(basis=phi, data=u) ax = plot.line(ufn, axis=ax) plt.show() # # Plots # # Formatting plt.rc('text', usetex=True) # Figure sizes fs2 = (3, 2) fs1 = (4, 3) print(J_ref) print(J) # # Plot truncation error for mean and variance of J # fig = plt.figure(figsize=fs2) ax = fig.add_subplot(111) err = np.array([np.abs(J[i] - J_ref) for i in range(n_levels)]) h = np.array([2**(-l) for l in range(n_levels)]) plt.loglog(h, err, '.-') ax.set_xlabel(r'$h$') ax.set_ylabel(r'$|J-J^h|$') plt.tight_layout() fig.savefig('fig/ex02_gauss_fem_error.eps')
vx = Explicit(f=lambda x: -x[:, 1], dim=2) vy = Explicit(f=lambda x: x[:, 0], dim=2) uB = Explicit(f=lambda x: np.cos(2 * np.pi * (x[:, 1] + 0.25)), dim=2) problem = [ Form(epsilon, trial=ux, test=ux), Form(epsilon, trial=uy, test=uy), Form(vx, trial=ux, test=u), Form(vy, trial=uy, test=u), Form(0, test=u) ] print('assembling', end=' ') assembler = Assembler(problem, mesh) assembler.assemble() print('done') print('solving', end=' ') A = assembler.get_matrix() b = np.zeros(u.n_dofs()) system = LS(u, A=A, b=b) system.add_dirichlet_constraint('B', uB) system.add_dirichlet_constraint('perimeter', 0) system.solve_system() ua = system.get_solution() print('done') plot = Plot() plot.wire(ua)
def test_integrals_1d(self): """ Test system assembly """ # # Constant form # # Mesh mesh = Mesh1D(box=[1, 2], resolution=(1, )) # Kernel kernel = Kernel(Explicit(f=lambda x: x[:, 0], dim=1)) problem = Form(kernel) assembler = Assembler(problem, mesh=mesh) assembler.assemble() self.assertAlmostEqual(assembler.get_scalar(), 3 / 2) # # Linear forms (x,x) and (x,x') over [1,2] = 7/3, 3/2 # # Elements Q1 = QuadFE(mesh.dim(), 'Q1') Q2 = QuadFE(mesh.dim(), 'Q2') Q3 = QuadFE(mesh.dim(), 'Q3') # Dofhandlers dQ1 = DofHandler(mesh, Q1) dQ2 = DofHandler(mesh, Q2) dQ3 = DofHandler(mesh, Q3) # Distribute dofs [d.distribute_dofs() for d in [dQ1, dQ2, dQ3]] for dQ in [dQ1, dQ2, dQ3]: # Basis phi = Basis(dQ, 'u') phi_x = Basis(dQ, 'ux') # Kernel function xfn = Nodal(f=lambda x: x[:, 0], basis=phi) # Kernel kernel = Kernel(xfn) # Form problem = [[Form(kernel, test=phi)], [Form(kernel, test=phi_x)]] # Assembly assembler = Assembler(problem, mesh) assembler.assemble() # Check b^Tx = (x,x) b0 = assembler.get_vector(0) self.assertAlmostEqual(np.sum(b0 * xfn.data()[:, 0]), 7 / 3) b1 = assembler.get_vector(1) self.assertAlmostEqual(np.sum(b1 * xfn.data()[:, 0]), 3 / 2) # # Bilinear forms # # Compute (1,x,x) = 7/3, or (x^2, 1, 1) = 7/3 for dQ in [dQ1, dQ2, dQ3]: # Basis phi = Basis(dQ, 'u') phi_x = Basis(dQ, 'ux') # Kernel function x2fn = Explicit(f=lambda x: x[:, 0]**2, dim=1) xfn = Nodal(f=lambda x: x[:, 0], basis=phi) # Form problems = [[Form(1, test=phi, trial=phi)], [Form(Kernel(xfn), test=phi, trial=phi_x)], [Form(Kernel(x2fn), test=phi_x, trial=phi_x)]] # Assemble assembler = Assembler(problems, mesh) assembler.assemble() x = xfn.data()[:, 0] for i_problem in range(3): A = assembler.get_matrix(i_problem) self.assertAlmostEqual(x.T.dot(A.dot(x)), 7 / 3) # ====================================================================== # Test 1: Assemble simple bilinear form (u,v) on Mesh1D # ====================================================================== # Mesh mesh = Mesh1D(resolution=(1, )) Q1 = QuadFE(mesh.dim(), 'Q1') Q2 = QuadFE(mesh.dim(), 'Q2') Q3 = QuadFE(mesh.dim(), 'Q3') # Test and trial functions dhQ1 = DofHandler(mesh, QuadFE(1, 'Q1')) dhQ1.distribute_dofs() u = Basis(dhQ1, 'u') v = Basis(dhQ1, 'v') # Form form = Form(trial=u, test=v) # Define system system = Assembler(form, mesh) # Get local information cell = mesh.cells.get_child(0) si = system.shape_info(cell) # Compute local Gauss nodes xg, wg, phi, dofs = system.shape_eval(cell) self.assertTrue(cell in xg) self.assertTrue(cell in wg) # Compute local shape functions self.assertTrue(cell in phi) self.assertTrue(u in phi[cell]) self.assertTrue(v in phi[cell]) self.assertTrue(u in dofs[cell]) # Assemble system system.assemble() # Extract system bilinear form A = system.get_matrix() # Use bilinear form to integrate x^2 over [0,1] f = Nodal(lambda x: x, basis=u) fv = f.data()[:, 0] self.assertAlmostEqual(np.sum(fv * A.dot(fv)), 1 / 3) # ====================================================================== # Test 3: Constant form (x^2,.,.) over 1D mesh # ====================================================================== # Mesh mesh = Mesh1D(resolution=(10, )) # Nodal kernel function Q2 = QuadFE(1, 'Q2') dhQ2 = DofHandler(mesh, Q2) dhQ2.distribute_dofs() phiQ2 = Basis(dhQ2) f = Nodal(lambda x: x**2, basis=phiQ2) kernel = Kernel(f=f) # Form form = Form(kernel=kernel) # Generate and assemble the system system = Assembler(form, mesh) system.assemble() # Check self.assertAlmostEqual(system.get_scalar(), 1 / 3) # ===================================================================== # Test 4: Periodic Mesh # ===================================================================== # # TODO: NO checks yet # mesh = Mesh1D(resolution=(2, ), periodic=True) # Q1 = QuadFE(1, 'Q1') dhQ1 = DofHandler(mesh, Q1) dhQ1.distribute_dofs() u = Basis(dhQ1, 'u') form = Form(trial=u, test=u) system = Assembler(form, mesh) system.assemble() # ===================================================================== # Test 5: Assemble simple sampled form # ====================================================================== mesh = Mesh1D(resolution=(3, )) Q1 = QuadFE(1, 'Q1') dofhandler = DofHandler(mesh, Q1) dofhandler.distribute_dofs() phi = Basis(dofhandler) xv = dofhandler.get_dof_vertices() n_points = dofhandler.n_dofs() n_samples = 6 a = np.arange(n_samples) f = lambda x, a: a * x fdata = np.zeros((n_points, n_samples)) for i in range(n_samples): fdata[:, i] = f(xv, a[i]).ravel() # Define sampled function fn = Nodal(data=fdata, basis=phi) kernel = Kernel(fn) # # Integrate I[0,1] ax^2 dx by using the linear form (ax,x) # v = Basis(dofhandler, 'v') form = Form(kernel=kernel, test=v) system = Assembler(form, mesh) system.assemble() one = np.ones(n_points) for i in range(n_samples): b = system.get_vector(i_sample=i) self.assertAlmostEqual(one.dot(b), 0.5 * a[i]) # # Integrate I[0,1] ax^4 dx using bilinear form (ax, x^2, x) # Q2 = QuadFE(1, 'Q2') dhQ2 = DofHandler(mesh, Q2) dhQ2.distribute_dofs() u = Basis(dhQ2, 'u') # Define form form = Form(kernel=kernel, test=v, trial=u) # Define and assemble system system = Assembler(form, mesh) system.assemble() # Express x^2 in terms of trial function basis dhQ2.distribute_dofs() xvQ2 = dhQ2.get_dof_vertices() xv_squared = xvQ2**2 for i in range(n_samples): # # Iterate over samples # # Form sparse matrix A = system.get_matrix(i_sample=i) # Evaluate the integral I = np.sum(xv * A.dot(xv_squared)) # Compare with expected result self.assertAlmostEqual(I, 0.2 * a[i]) # ===================================================================== # Test 6: Working with submeshes # ===================================================================== mesh = Mesh1D(resolution=(2, ))