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 test_edge_integrals(self): """ Test computing """ mesh = QuadMesh(resolution=(1, 1)) Q = QuadFE(2, 'Q1') dQ = DofHandler(mesh, Q) dQ.distribute_dofs() phi = Basis(dQ, 'u') f = Nodal(data=np.ones((phi.n_dofs(), 1)), basis=phi) kernel = Kernel(f) form = Form(kernel, dmu='ds') assembler = Assembler(form, mesh) cell = mesh.cells.get_leaves()[0] shape_info = assembler.shape_info(cell) xg, wg, phi, dofs = assembler.shape_eval(cell)
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))
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_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 sample_qoi(q, dofhandler, return_state=False): """ Compute the Quantity of Interest J(u) = -exp(q(1))*u'(1), where u solves -d/dx ( exp(q)* du/dx) = 1 u(0) = 0, u(1) = 1 for a sample of q's. Inputs: q: Nodal, (n_dofs, n_samples) function representing the log porosity dofhandler: DofHandler """ # Basis phi = Basis(dofhandler, 'v') phi_x = Basis(dofhandler, 'vx') n_dofs = phi.n_dofs() # Define problem expq_fn = Nodal(data=np.exp(q), basis=phi) problem = [[Form(expq_fn, test=phi_x, trial=phi_x), Form(1, test=phi)], [Form(expq_fn, test=phi_x, dmu='dv', flag='right')]] # Define assembler assembler = Assembler(problem, dofhandler.mesh) # Incorporate Dirichlet conditions assembler.add_dirichlet('left', 0) assembler.add_dirichlet('right', 1) n_samples = expq_fn.n_subsample() # Assemble system assembler.assemble() if return_state: U = np.empty((n_dofs, n_samples)) J = np.zeros(n_samples) for i in range(n_samples): # Solve system u = assembler.solve(i_problem=0, i_matrix=i, i_vector=0) # Compute quantity of interest J[i] = -u.dot(assembler.get_vector(1, i)) if return_state: U[:, i] = u if return_state: return J, U else: return J
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')
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))