def experiment01(): """ Compute the quantity of interest, it's expectation and variance """ # # FE Discretization # # Computational mesh mesh = Mesh1D(resolution=(64, )) # Element element = QuadFE(mesh.dim(), 'DQ0') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # Linear Functional mesh.mark_region('integrate', lambda x: x > 0.75, entity_type='cell', strict_containment=False) phi = Basis(dofhandler) assembler = Assembler(Form(1, test=phi, flag='integrate')) assembler.assemble() L = assembler.get_vector()
def test_constructor(self): # # Define mesh, element, and dofhandler # mesh = QuadMesh(box=[0, 20, 0, 20], resolution=(20, 20), periodic={0, 1}) dim = mesh.dim() element = QuadFE(dim, 'Q2') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() basis = Basis(dofhandler, 'u') alph = 2 kppa = 1 # Symmetric tensor gma T + bta* vv^T gma = 0.1 bta = 25 p = lambda x: 10/np.pi*(0.75*np.sin(np.pi*x[:,0]/10)+\ 0.25*np.sin(np.pi*x[:,1]/10)) f = Nodal(f=p, basis=basis) fx = f.differentiate((1, 0)) fy = f.differentiate((1, 1)) #plot.contour(f) x = np.linspace(0, 20, 12) X, Y = np.meshgrid(x, x) xy = np.array([X.ravel(), Y.ravel()]).T U = fx.eval(xy).reshape(X.shape) V = fy.eval(xy).reshape(X.shape) v1 = lambda x: -0.25 * np.cos(np.pi * x[:, 1] / 10) v2 = lambda x: 0.75 * np.cos(np.pi * x[:, 0] / 10) U = v1(xy).reshape(X.shape) V = v2(xy).reshape(X.shape) #plt.quiver(X,Y, U, V) #plt.show() h11 = Explicit(lambda x: gma + bta * v1(x) * v1(x), dim=2) h12 = Explicit(lambda x: bta * v1(x) * v2(x), dim=2) h22 = Explicit(lambda x: gma + bta * v2(x) * v2(x), dim=2) tau = (h11, h12, h22) #tau = (Constant(2), Constant(1), Constant(1)) # # Define default elliptic field # u = EllipticField(dofhandler, kappa=1, tau=tau, gamma=2) Q = u.precision() v = Nodal(data=u.sample(mode='precision', decomposition='chol'), basis=basis) plot = Plot(20) plot.contour(v)
def test_same_dofs(self): # # Construct nested mesh # mesh = QuadMesh() mesh.record(0) for dummy in range(2): mesh.cells.refine() # # Define dofhandler # element = QuadFE(mesh.dim(), 'Q1') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # # Define basis functions # phi0 = Basis(dofhandler, 'u', subforest_flag=0) phi0_x = Basis(dofhandler, 'ux', subforest_flag=0) phi1 = Basis(dofhandler, 'u') self.assertTrue(phi0.same_mesh(phi0_x)) self.assertFalse(phi0.same_mesh(phi1))
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 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 test03_dJdq(): """ Compute dJdq for a simple problem, check that it works """ # # Mesh # mesh = Mesh1D(resolution=(20, )) mesh.mark_region('left', lambda x: np.abs(x) < 1e-10) mesh.mark_region('right', lambda x: np.abs(x - 1) < 1e-10) # # Element # Q = QuadFE(mesh.dim(), 'Q3') dh = DofHandler(mesh, Q) dh.distribute_dofs() nx = dh.n_dofs() x = dh.get_dof_vertices() # # Basis # phi = Basis(dh, 'v') phi_x = Basis(dh, 'vx') # # Parameters # # Reference q q_ref = Nodal(data=np.zeros(nx), basis=phi) # Perturbation dq = Nodal(data=np.ones(nx), basis=phi) # # Sample Reference QoI # J, u_ref = sample_qoi(q_ref.data(), dh, return_state=True) u_ref = Nodal(data=u_ref, basis=phi) # # Compute dJdq # # Perturbation method Jp_per = dJdq_per(q_ref, dq, dh) # Sensitivity method Jp_sen = dJdq_sen(q_ref, u_ref, dq) # Adjoint method Jp_adj = dJdq_adj(q_ref, u_ref, dq) # Check that the answers are close to -1 assert np.allclose(Jp_per, -1) assert np.allclose(Jp_sen, -1) assert np.allclose(Jp_adj, -1)
def test_set(self): mesh = QuadMesh(resolution=(1, 1)) element = QuadFE(2, 'Q1') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() px = Basis(dofhandler, 'ux') p = Basis(dofhandler, 'ux') self.assertNotEqual(px, p)
def test_n_samples(self): # # Sampled Case # meshes = {1: Mesh1D(), 2: QuadMesh()} elements = {1: QuadFE(1, 'Q2'), 2: QuadFE(2, 'Q2')} # Use function to set data fns = { 1: { 1: lambda x: 2 * x[:, 0]**2, 2: lambda x, y: 2 * x[:, 0] + 2 * y[:, 0] }, 2: { 1: lambda x: x[:, 0]**2 + x[:, 1], 2: lambda x, y: x[:, 0] * y[:, 0] + x[:, 1] * y[:, 1] } } # n_samples = 2 parms = {1: {1: [{}, {}], 2: [{}, {}]}, 2: {1: [{}, {}], 2: [{}, {}]}} for dim in [1, 2]: mesh = meshes[dim] element = elements[dim] dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() basis = Basis(dofhandler) for n_variables in [1, 2]: fn = fns[dim][n_variables] parm = parms[dim][n_variables] # # Deterministic # f = Nodal(f=fn, mesh=mesh, basis=basis, element=element, dim=dim, n_variables=n_variables) self.assertEqual(f.n_samples(), 1) # # Sampled # f = Nodal(f=fn, parameters=parm, basis=basis, mesh=mesh, element=element, dim=dim, n_variables=n_variables) self.assertEqual(f.n_samples(), 2)
def test02a_sensitivity_gradient(): """ Test whether the sensitivity and adjoint calculations give the same gradient """ # Mesh mesh = Mesh1D(resolution=(100, )) mesh.mark_region('left', lambda x: np.abs(x) < 1e-10) mesh.mark_region('right', lambda x: np.abs(1 - x) < 1e-10) # Element Q = QuadFE(mesh.dim(), 'Q2') dh = DofHandler(mesh, Q) dh.distribute_dofs() n_dofs = dh.n_dofs() phi = Basis(dh, 'u') # Covariance cov = Covariance(dh, name='gaussian', parameters={'l': 0.05}) cov.compute_eig_decomp() lmd, V = cov.get_eig_decomp() d = len(lmd) # Coarse field (single sample) d0 = 2 z0 = np.random.randn(d0, 1) q0 = sample_q0(V, lmd, d0, z0) q0_fn = Nodal(data=q0, basis=phi) # State J0, u0 = sample_qoi(q0, dh, return_state=True) u0_fn = Nodal(data=u0, basis=phi) # Compute gradient using sensitivity dJs = np.zeros(n_dofs) for i in range(n_dofs): # Define perturbation dq = np.zeros(n_dofs) dq[i] = 1 dq_fn = Nodal(data=dq, basis=phi) # Compute gradient using sensitivity dJs[i] = dJdq_sen(q0_fn, u0_fn, dq_fn) dJs_fn = Nodal(data=dJs, basis=phi) plot = Plot() plot.line(dJs_fn) # Compute gradient using adjoint method dJa = dJdq_adj(q0_fn, u0_fn) dJa_fn = Nodal(data=dJa, basis=phi) print(dJa) plot.line(dJa_fn)
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 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 test_timings(self): """ """ comment = Verbose() mesh = QuadMesh() element = QuadFE(2,'Q1') dofhandler = DofHandler(mesh, element) for dummy in range(7): mesh.cells.refine() comment.tic() dofhandler.distribute_dofs() comment.toc() print(dofhandler.n_dofs())
def sampling_error(): """ Test the sampling error by comparing the accuracy of the quantities of interest q1 = E[|y|] and q2 = E[y(0.5)] """ c = Verbose() mesh = Mesh1D(resolution=(1026,)) mesh.mark_region('left', lambda x:np.abs(x)<1e-10) mesh.mark_region('right', lambda x:np.abs(x-1)<1e-10) element = QuadFE(1,'Q1') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() dofhandler.set_dof_vertices() phi = Basis(dofhandler,'u') phi_x = Basis(dofhandler,'ux') ns_ref = 10000 z = get_points(n_samples=ns_ref) q = set_diffusion(dofhandler,z) problems = [[Form(q, test=phi_x, trial=phi_x), Form(1, test=phi)], [Form(1, test=phi, trial=phi)]] c.tic('assembling') assembler = Assembler(problems, mesh) assembler.assemble() c.toc() A = assembler.af[0]['bilinear'].get_matrix() b = assembler.af[0]['linear'].get_matrix() M = assembler.af[0]['bilinear'].get_matrix() system = LS(phi) system.add_dirichlet_constraint('left') system.add_dirichlet_constraint('right') c.tic('solving') for n in range(ns_ref): system.set_matrix(A[n]) system.set_rhs(b.copy()) system.solve_system() c.toc()
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 test_n_dofs(self): """ Check that the total number of dofs is correct NOTE: A mesh with multiple levels has dofs on coarser levels that may not appear in leaves """ etypes = ['DQ0', 'DQ1', 'DQ2', 'DQ3', 'Q1', 'Q2', 'Q3'] # # Single cell # n_dofs = dict.fromkeys([0,1]) n_dofs[0] = {'DQ0': 1, 'DQ1': 2, 'DQ2': 3, 'DQ3': 4, 'Q1': 2, 'Q2': 3, 'Q3': 4} n_dofs[1] = {'DQ0': 1, 'DQ1': 4, 'DQ2': 9, 'DQ3': 16, 'Q1': 4, 'Q2': 9, 'Q3':16} for dim in range(2): if dim==0: mesh = Mesh1D() elif dim==1: mesh = QuadMesh() for etype in etypes: element = QuadFE(dim+1, etype) dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() self.assertEqual(n_dofs[dim][etype], dofhandler.n_dofs()) # # Mesh with multiple cells # n_dofs = dict.fromkeys([0,1]) n_dofs[0] = {'DQ0': 2, 'DQ1': 4, 'DQ2': 6, 'DQ3': 8, 'Q1': 3, 'Q2': 5, 'Q3': 7} n_dofs[1] = {'DQ0': 4, 'DQ1': 16, 'DQ2': 36, 'DQ3': 64, 'Q1': 9, 'Q2': 25, 'Q3': 49} for dim in range(2): if dim==0: mesh = Mesh1D(resolution=(2,)) elif dim==1: mesh = QuadMesh(resolution=(2,2)) for etype in etypes: element = QuadFE(dim+1, etype) dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() self.assertEqual(n_dofs[dim][etype], dofhandler.n_dofs())
def test02_variance(): """ Compute the variance of J(q) for different mesh refinement levels and compare with MC estimates. """ l_max = 8 for i_res in np.arange(2, l_max): # Computational mesh mesh = Mesh1D(resolution=(2**i_res, )) # Element element = QuadFE(mesh.dim(), 'DQ0') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # Linear Functional mesh.mark_region('integrate', lambda x: x >= 0.75, entity_type='cell', strict_containment=False) phi = Basis(dofhandler) assembler = Assembler(Form(4, test=phi, flag='integrate')) assembler.assemble() L = assembler.get_vector() # Define Gaussian random field C = Covariance(dofhandler, name='gaussian', parameters={'l': 0.05}) C.compute_eig_decomp() eta = GaussianField(dofhandler.n_dofs(), K=C) eta.update_support() n_samples = 100000 J_paths = L.dot(eta.sample(n_samples=n_samples)) var_mc = np.var(J_paths) lmd, V = C.get_eig_decomp() LV = L.dot(V) var_an = LV.dot(np.diag(lmd).dot(LV.transpose())) print(var_mc, var_an)
def test_distribute_dofs(self): show_plots = False if show_plots: plot = Plot() # # Define QuadMesh with hanging node # mesh = QuadMesh(resolution=(1,1), periodic={0,1}) mesh.cells.refine() mesh.cells.get_child(0).get_child(0).mark(flag=0) mesh.cells.refine(refinement_flag=0) etypes = ['DQ0','DQ1', 'DQ2', 'DQ3', 'Q1', 'Q2', 'Q3'] for etype in etypes: # Define new element element = QuadFE(2,etype) # Distribute dofs dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() plot.mesh(mesh, dofhandler=dofhandler, dofs=True)
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 test_constructor(self): # # Errors # # Nothing specified self.assertRaises(Exception, Nodal) # Nominal case mesh = QuadMesh() element = QuadFE(2, 'Q1') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() basis = Basis(dofhandler) data = np.arange(0, 4) f = Nodal(data=data, basis=basis, mesh=mesh, element=element) self.assertEqual(f.dim(), 2) self.assertTrue(np.allclose(f.data().ravel(), data)) # Now change the data -> Error false_data = np.arange(0, 6) self.assertRaises( Exception, Nodal, **{ 'data': false_data, 'mesh': mesh, 'element': element }) # Now omit mesh or element kwargs = {'data': data, 'mesh': mesh} self.assertRaises(Exception, Nodal, **kwargs) kwargs = {'data': data, 'element': element} self.assertRaises(Exception, Nodal, **kwargs)
def test_get_region_dofs(self): """ Test the function for returning the dofs associated with a region. """ # # 2D # mesh = QuadMesh() for etype in ['Q1','Q2','Q3']: element = QuadFE(2, etype) dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # # Mark half-edges # bnd_right = lambda x,dummy: np.abs(x-1)<1e-9 mesh.mark_region('right', bnd_right, \ entity_type='half_edge', \ on_boundary=True) # Check that mesh.mark_region is doing the right thing. cell = mesh.cells.get_child(0) marked_edge = False for he in cell.get_half_edges(): if he.is_marked('right'): # # All vertices should be on the boundary # marked_edge = True for v in he.get_vertices(): x,y = v.coordinates() self.assertTrue(bnd_right(x,y)) else: # # Not all vertices on should be on the boundary # on_right = True for v in he.get_vertices(): x,y = v.coordinates() if not bnd_right(x,y): on_right = False self.assertFalse(on_right) # # Some half-edge should be marked # self.assertTrue(marked_edge) # # Check that we get the right number of dofs # n_dofs = {True: {'Q1': 0, 'Q2': 1, 'Q3': 2}, False: {'Q1': 2, 'Q2': 3, 'Q3': 4}} for interior in [True, False]: dofs = dofhandler.get_region_dofs(entity_type='half_edge', \ entity_flag='right', \ interior=interior, \ on_boundary=True) # # Check that we get the right number of dofs # self.assertEqual(len(dofs), n_dofs[interior][etype])
def test_set_hanging_nodes(self): """ Check that functions in the finite element space can be interpolated by linear combinations of shape functions at supporting nodes. TODO: Move this test to tests for system """ # # Define QuadMesh with hanging node # mesh = QuadMesh(resolution=(1,1)) mesh.cells.refine() mesh.cells.get_child(0).get_child(0).mark(flag=0) mesh.cells.refine(refinement_flag=0) c_00 = mesh.cells.get_child(0).get_child(0) # # Define test functions to interpolate # test_functions = {'Q1': lambda x,y: x + y, \ 'Q2': lambda x,y: x**2 + y**2,\ 'Q3': lambda x,y: x**3*y + y**2*x**2} etypes = ['Q1', 'Q2', 'Q3'] plot = Plot() for etype in etypes: #print(etype) # Define new element element = QuadFE(2,etype) # Distribute dofs and set vertices dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() dofhandler.set_dof_vertices() # Determine hanging nodes dofhandler.set_hanging_nodes() hanging_nodes = dofhandler.get_hanging_nodes() for dof, support in hanging_nodes.items(): # Get hanging node vertex x_hgnd = dofhandler.get_dof_vertices(dof) # Extract support indices and weights js, ws = support # Extract dofs_glb = dofhandler.get_cell_dofs(c_00) #print(dof, js) # Local dof numbers for supporting nodes dofs_loc_supp = [i for i in range(element.n_dofs()) if dofs_glb[i] in js] #x_dofs = c_00.reference_map(element.reference_nodes()) #phi_supp = element.shape(x_hgnd, cell=c_00, local_dofs=dofs_loc_supp) #print(phi_supp, js) # Evaluate test function at hanging node #f_hgnd = test_functions[etype](x_hgnd[0],x_hgnd[1]) #print('Weighted sum of support function', np.dot(phi_supp,ws)) #print(f_hgnd - np.dot(phi_supp, ws)) #phi_hgnd = element.shape(x_dofs, cell=c_00, local_dofs=dofs_loc_hgnd) #print(phi_supp) #print(phi_hgnd) #plot.mesh(mesh, dofhandler=dofhandler, dofs=True) # Evaluate c_01 = mesh.cells.get_child(0).get_child(1) c_022 = mesh.cells.get_child(0).get_child(2).get_child(2) #print(dofhandler.get_global_dofs(c_022)) x_ref = element.reference_nodes() #print(dofhandler.get_global_dofs(c_01)) #print(dofhandler.get_hanging_nodes()) x = c_01.reference_map(x_ref)
# Define new mesh # mesh = QuadMesh(resolution=resolution) errors[resolution] = {} for eps in [1, 1e-3, 1e-6]: errors[resolution][eps] = {} for etype in ['Q1', 'Q2']: # # Define element # element = QuadFE(2, etype) dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # # Define Basis Functions # u = Basis(dofhandler, 'u') ux = Basis(dofhandler, 'ux') uy = Basis(dofhandler, 'uy') # # Define weak form # a_diff_x = Form(eps, trial=ux, test=ux) a_diff_y = Form(eps, trial=uy, test=uy) a_adv_x = Form(vx, trial=ux, test=u) a_adv_y = Form(vy, trial=uy, test=u) b = Form(f, test=u)
xx_min, xx_max = 0, 0.7 # region on which to condition f_int_region = lambda x: x >= x_min and x <= x_max f_cnd_region = lambda x: x >= xx_min and x <= xx_max mesh.mark_region('integration', f_int_region, entity_type='cell') mesh.mark_region('condition', f_cnd_region, entity_type='cell') # # Finite Elements # # Piecewise Constant Q0 = QuadFE(mesh.dim(), 'DQ0') dQ0 = DofHandler(mesh, Q0) dQ0.distribute_dofs() phi_0 = Basis(dQ0) # Piecewise Linear Q1 = QuadFE(mesh.dim(), 'Q1') dQ1 = DofHandler(mesh, Q1) dQ1.distribute_dofs() phi_1 = Basis(dQ1) # ----------------------------------------------------------------------------- # Stochastic Approximation # ----------------------------------------------------------------------------- # # Random Field # # Covariance kernel
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 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 test_eval_projection(self): """ Test validity of the local projection-based kernel. Choose u, v in V k(x,y) in VxV (symmetric/non-symm) cell01, cell02 Compare v^T*Kloc*u ?= Icell01 Icell02 k(x,y)u(y)dy dx """ # # 1D # # Mesh mesh = Mesh1D(resolution=(3, )) # Finite element space etype = 'Q1' element = QuadFE(1, etype) # Dofhandler dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # Basis functions phi = Basis(dofhandler, 'u') # Symmetric kernel function kfns = { 'symmetric': lambda x, y: x * y, 'non_symmetric': lambda x, y: x - y } vals = { 'symmetric': (1 / 2 * 1 / 9 - 1 / 3 * 1 / 27) * (1 / 3 - 1 / 3 * 8 / 27), 'non_symmetric': (1 / 18 - 1 / 3 * 1 / 27) * (1 / 2 - 2 / 9) + (1 / 18 - 1 / 3) * (1 / 3 - 1 / 3 * 8 / 27) } for ktype in ['symmetric', 'non_symmetric']: # Get kernel function kfn = kfns[ktype] # Define integral kernel kernel = Kernel(Explicit(kfn, dim=1, n_variables=2)) # Define Bilinear Form form = IPForm(kernel, trial=phi, test=phi) # # Compute inputs required for evaluating form_loc # # Assembler assembler = Assembler(form, mesh) # Cells ci = mesh.cells.get_child(0) cj = mesh.cells.get_child(2) # Shape function info on cells ci_sinfo = assembler.shape_info(ci) cj_sinfo = assembler.shape_info(cj) # Gauss nodes and weights on cell xi_g, wi_g, phii, dofsi = assembler.shape_eval(ci) xj_g, wj_g, phij, dofsj = assembler.shape_eval(cj) # # Evaluate form # form_loc = form.eval((ci,cj), (xi_g,xj_g), \ (wi_g,wj_g), (phii,phij), (dofsi,dofsj)) # # Define functions # u = Nodal(f=lambda x: x, basis=phi) v = Nodal(f=lambda x: 1 - x, basis=phi) # # Get local node values # # Degrees of freedom ci_dofs = phi.dofs(ci) cj_dofs = phi.dofs(cj) uj = u.data()[np.array(cj_dofs)] vi = v.data()[np.array(ci_dofs)] if ktype == 'symmetric': # Local form by hand c10 = 1 / 54 c11 = 1 / 27 c20 = 3 / 2 - 1 - 3 / 2 * 4 / 9 + 8 / 27 c21 = 4 / 27 fl = np.array([[c10 * c20, c10 * c21], [c11 * c20, c11 * c21]]) # Compare computed and explicit local forms self.assertTrue(np.allclose(fl, form_loc)) # Evaluate Ici Icj k(x,y) y dy (1-x)dx fa = np.dot(vi.T, form_loc.dot(uj)) fe = vals[ktype] self.assertAlmostEqual(fa, fe)
x_max = 2 mesh = Mesh1D(box=[x_min, x_max], resolution=(256, )) # Mark Dirichlet Vertices mesh.mark_region('left', lambda x: np.abs(x) < 1e-9) mesh.mark_region('right', lambda x: np.abs(x - 2) < 1e-9) # # Finite element spaces # Q1 = QuadFE(mesh.dim(), 'Q1') # Dofhandler for state dh = DofHandler(mesh, Q1) dh.distribute_dofs() m = dh.n_dofs() dh.set_dof_vertices() x = dh.get_dof_vertices() # Basis functions phi = Basis(dh, 'v') phi_x = Basis(dh, 'vx') state = LS(phi) state.add_dirichlet_constraint('left', 1) state.add_dirichlet_constraint('right', 0) state.set_constraint_relation() adjoint = LS(phi) adjoint.add_dirichlet_constraint('left', 0)
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()))