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_is_balanced(self): mesh_1 = QuadMesh(resolution=(2,2)) mesh_2 = QuadMesh(resolution=(2,2), periodic={1}) mesh_3 = QuadMesh(resolution=(2,2), periodic={0,1}) count = 0 for mesh in [mesh_1, mesh_2, mesh_3]: # Initial Meshes should be balanced self.assertTrue(mesh.is_balanced()) # Refine mesh and label it mesh.cells.get_child(0).mark(1) mesh.cells.refine(refinement_flag=1, new_label='b1') # Check if refined mesh is balanced mesh.is_balanced(subforest_flag='b1') # Now refine again - unbalanced mesh.cells.get_child(0).get_child(0).mark(1) mesh.cells.refine(refinement_flag=1, subforest_flag='b1', new_label='ub1') # New mesh should not be balanced if count in [0]: self.assertTrue(mesh.is_balanced()) self.assertTrue(mesh.is_balanced(subforest_flag='ub1')) else: self.assertFalse(mesh.is_balanced(subforest_flag='ub1')) self.assertFalse(mesh.is_balanced()) # Old mesh should still be balanced self.assertTrue(mesh.is_balanced(subforest_flag='b1')) count += 1
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_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_get_boundary_segments(self): """ Test """ # # Define Mesh # mesh = QuadMesh(resolution=(2,2)) mesh.record('mesh_1') mesh.cells.get_child(2).mark('1') mesh.cells.refine(refinement_flag='1') # # # for segment in mesh.get_boundary_segments(subforest_flag=None): for he in segment: pass
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 test_mark_region(self): """ This is a method in Mesh2D, but """ # # Define Mesh # mesh = QuadMesh(resolution=(2,2)) mesh.cells.get_child(2).mark('1') mesh.cells.refine(refinement_flag='1') # # Mark left boundary vertices # f_left = lambda x,dummy: np.abs(x)<1e-9 mesh.mark_region('left', f_left, on_boundary=True) # # Check that left boundary vertices are the only # count = 0 for segment in mesh.get_boundary_segments(): for he in segment: # Half-edge should not be marked self.assertFalse(he.is_marked('left')) # Cell should not be marked self.assertFalse(he.cell().is_marked('left')) for v in he.get_vertices(): if f_left(*v.coordinates()): # # Left boundary vertices should be marked # self.assertTrue(v.is_marked('left')) count += 1 else: # # No other boundary vertices should be marked # self.assertFalse(v.is_marked('left')) self.assertEqual(count, 8)
def test_get_region(self): # # Define Mesh # mesh = QuadMesh(resolution=(2,2)) mesh.cells.get_child(2).mark('1') mesh.cells.refine(refinement_flag='1') # # Mark left boundary vertices # f_left = lambda x,dummy: np.abs(x)<1e-9 mesh.mark_region('left', f_left, on_boundary=True) for v,cell in mesh.get_region('left', entity_type='vertex', return_cells=True, on_boundary=True): self.assertTrue(v.is_marked('left'))
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 test_balance(self): mesh_1 = QuadMesh(resolution=(2,2)) mesh_2 = QuadMesh(resolution=(2,2), periodic={1}) mesh_3 = QuadMesh(resolution=(2,2), periodic={0,1}) plot = Plot() for mesh in [mesh_1, mesh_2, mesh_3]: # Refine mesh and label it mesh.cells.get_child(0).mark(1) mesh.cells.refine(refinement_flag=1, new_label='b1') # Check if refined mesh is balanced mesh.is_balanced(subforest_flag='b1') # Now refine again - unbalanced mesh.cells.get_child(0).get_child(0).mark(1) mesh.cells.refine(refinement_flag=1, subforest_flag='b1', new_label='ub1') #plot.mesh(mesh, mesh_flag='ub1') mesh.balance(subforest_flag='ub1')
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 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 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 test_get_local_dofs(self): """ Extract local dofs from a corner vertex, halfEdge or cell """ local_dofs = {1: {'DQ0': [[0], [], [0]], 'DQ1': [[0,1], [1], []], 'DQ2': [[0,1,2], [1], [2]], 'DQ3': [[0,1,2,3], [1], [2,3]] }, 2: {'DQ0': [[0], [], [], [0]], 'DQ1': [[0,1,2,3], [1], [], []], 'DQ2': [[0,1,2,3,4,5,6,7,8], [1], [6], [8]], 'DQ3': [[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], [1], [8,9], [12,13,14,15]] } } etypes = ['DQ' + i for i in '0123'] for dim in range(1,3): if dim==1: mesh = Mesh1D(box=[2,4], resolution=(1,)) cell = mesh.cells.get_child(0) vertex = cell.get_vertex(1) entities = [None, vertex, cell] elif dim==2: mesh = QuadMesh(box = [0,2,0,2], resolution=(2,2)) cell = mesh.cells.get_child(1) vertex = cell.get_vertex(1) half_edge = cell.get_half_edge(2) entities = [None, vertex, half_edge, cell] for etype in etypes: element = QuadFE(dim, etype) dofhandler = DofHandler(mesh, element) for i_entity in range(len(entities)): entity = entities[i_entity] dofs = dofhandler.get_cell_dofs(cell, entity=entity, doftype='local', interior=True) self.assertEqual(local_dofs[dim][etype][i_entity], dofs)
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_bin_points(self): # Construct mesh mesh = QuadMesh(resolution=(2,2)) mesh.record(1) mesh.cells.get_child(0).mark('refine') mesh.cells.refine(refinement_flag='refine') # # Bin random points using the coarsest mesh # x = np.random.rand(5,2) bins = mesh.bin_points(x,subforest_flag=1) for cell, dummy in bins: self.assertEqual(cell.get_depth(),0) # # x # x = np.array([[0.125,0.125]]) bins = mesh.bin_points(x, subforest_flag=1) self.assertEqual(len(bins),1) for cell, dummy in bins: # Cell should be on level 0 self.assertEqual(cell.get_depth(),0) # Bin over all cells bins = mesh.bin_points(x) self.assertEqual(len(bins),1) for cell, dummy in bins: # Cell should now be on level 1 self.assertEqual(cell.get_depth(),1) # # Out of bounds x # x = np.array([[-1,-1]]) self.assertRaises(Exception, mesh.bin_points, *(x,))
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)
def test_share_dofs_with_children(self): # # 1D Test # mesh = Mesh1D(resolution=(1,)) mesh.cells.refine() for etype in ['DQ0','DQ1', 'DQ2', 'DQ3', 'Q1', 'Q2', 'Q3']: # New DofHandler element = QuadFE(1, etype) dh = DofHandler(mesh, element) # Fill in parent dofs and share with children cell = mesh.cells.get_child(0) dh.fill_dofs(cell) dh.share_dofs_with_children(cell) # Expected dofs for children left_child_dofs = {'DQ0': [None], 'DQ1': [0, None], 'DQ2': [0, 2, None], 'DQ3': [0, None, None, 2], 'Q1': [0, None], 'Q2': [0, 2, None], 'Q3': [0, None, None, 2]} right_child_dofs = {'DQ0': [None], 'DQ1': [None, 1], 'DQ2': [None, 1, None], 'DQ3': [None, 1, 3, None], 'Q1':[None, 1], 'Q2': [2, 1, None], 'Q3': [None, 1, 3, None]} left_child = cell.get_child(0) right_child = cell.get_child(1) # # Check whether shared dofs are as expected. # self.assertEqual(dh.get_cell_dofs(left_child), left_child_dofs[etype]) self.assertEqual(dh.get_cell_dofs(right_child), right_child_dofs[etype]) # # 2D Test # mesh = QuadMesh(resolution=(1,1)) mesh.cells.refine() for etype in ['DQ0','DQ1', 'DQ2', 'DQ3', 'Q1', 'Q2', 'Q3']: # New dofhandler element = QuadFE(2, etype) dh = DofHandler(mesh, element) # Fill in parent dofs and share with children cell = mesh.cells.get_child(0) dh.fill_dofs(cell) dh.share_dofs_with_children(cell) # Expected dofs for children child_dofs = {0: {'DQ0': [None], 'DQ1': [0, None, None, None], 'DQ2': [0, 4, 8, 7, None, None, None, None, None], 'DQ3': [0, None, None, None, None, 4, None, None, None, None, 11, None, None, None, None, 12], 'Q1': [0, None, None, None], 'Q2': [0, 4, 8, 7, None, None, None, None, None], 'Q3': [0, None, None, None, None, 4, None, None, None, None, 11, None, None, None, None, 12]}, 1: {'DQ0': [None], 'DQ1': [None, 1, None, None], 'DQ2': [None, 1, 5, None, None, None, None, None, None], 'DQ3': [None, 1, None, None, 5, None, None, 6, None, None, None, None, None, None, 13, None], 'Q1': [None, 1, None, None], 'Q2': [4, 1, 5, 8, None, None, None, None, None], 'Q3': [None, 1, None, None, 5, None, None, 6, None, None, None, None, None, None, 13, None]}, 2: {'DQ0': [None], 'DQ1': [None, None, 2, None], 'DQ2': [None, None, 2, 6, None, None, None, None, None], 'DQ3': [None, None, 2, None, None, None, 7, None, None, 8, None, None, 15, None, None, None], 'Q1': [None, None, 2, None], 'Q2': [8, 5, 2, 6, None, None, None, None, None], 'Q3': [None, None, 2, None, None, None, 7, None, None, 8, None, None, 15, None, None, None]}, 3: {'DQ0': [None], 'DQ1': [None, None, None, 3], 'DQ2': [None, None, None, 3, None, None, None, None, None], 'DQ3': [None, None, None, 3, None, None, None, None, 9, None, None, 10, None, 14, None, None], 'Q1': [None, None, None, 3], 'Q2': [7, 8, 6, 3, None, None, None, None, None], 'Q3': [None, None, None, 3, None, None, None, None, 9, None, None, 10, None, 14, None, None]}} for i in range(4): child = cell.get_child(i) # # Check whether shared dofs are as expected # self.assertEqual(dh.get_cell_dofs(child), child_dofs[i][etype])
# Forcing function ffn = lambda x: 2*eps*np.sin(x[:,0])*np.sin(x[:,1]) + \ x[:,0]*np.cos(x[:,0])*np.sin(x[:,1]) + \ x[:,1]*np.sin(x[:,0])*np.cos(x[:,1]) f = Explicit(ffn, dim=2) # Velocity function vx = Explicit(lambda x: x[:, 0], dim=2) vy = Explicit(lambda x: x[:, 1], dim=2) errors = {} for resolution in [(5, 5), (10, 10), (20, 20), (40, 40)]: # # 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
def test_eval_x(self): # # Evaluate Nodal function at a given set of x-values # # Meshes and elements meshes = {1: Mesh1D(resolution=(2, )), 2: QuadMesh(resolution=(2, 1))} 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: [{}, {}]}} n_points = 1 for dim in [1, 2]: mesh = meshes[dim] element = elements[dim] dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() #dofhandler.get_region_dofs() basis = Basis(dofhandler) # # Define random points in domain # if dim == 1: x_min, x_max = mesh.bounding_box() x = x_min + 0.5 * (x_max - x_min) * np.random.rand(n_points) x = x[:, np.newaxis] y = x_min + (x_max - x_min) * np.random.rand(n_points) y = y[:, np.newaxis] elif dim == 2: x_min, x_max, y_min, y_max = mesh.bounding_box() x = np.zeros((n_points, 2)) x[:, 0] = x_min + (x_max - x_min) * np.random.rand(n_points) x[:, 1] = y_min + (y_max - y_min) * np.random.rand(n_points) y = np.zeros((n_points, 2)) y[:, 0] = x_min + (x_max - x_min) * np.random.rand(n_points) y[:, 1] = y_min + (y_max - y_min) * np.random.rand(n_points) for n_variables in [1, 2]: fn = fns[dim][n_variables] parm = parms[dim][n_variables] # # Deterministic # f = Nodal(f=fn, basis=basis, mesh=mesh, element=element, dim=dim, n_variables=n_variables) if n_variables == 1: xx = x fe = fn(x) elif n_variables == 2: xx = (x, y) fe = fn(*xx) fx = f.eval(x=xx) self.assertTrue(np.allclose(fx, fe)) # # 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) fx = f.eval(x=xx) self.assertTrue(np.allclose(fx[:, 0], fe)) self.assertTrue(np.allclose(fx[:, 1], fe))
from fem import DofHandler from fem import QuadFE from fem import Basis from function import Explicit from mesh import Mesh1D from mesh import QuadMesh from mesh import Vertex from mesh import HalfEdge from solver import LinearSystem as LS from plot import Plot import numpy as np # ============================================================================= # Computational mesh # ============================================================================= mesh = QuadMesh(box=[-0.5, 0.5, -0.5, 0.5], resolution=(20, 20)) # Mark slit region slit = HalfEdge(Vertex((0, 0)), Vertex((0, -0.5))) sf = lambda x, y: slit.contains_points(np.array([x, y]))[0] mesh.mark_region('slit', sf, entity_type='half_edge') # Mark perimeter tol = 1e-9 pf = lambda x,y: np.abs(x+0.5)<tol or np.abs(x-0.5)<tol or \ np.abs(y+0.5)<tol or np.abs(y-0.5)<tol mesh.mark_region('perimeter', pf, entity_type='half_edge') # Get rid of neighbors of half-edges on slit for he in mesh.half_edges.get_leaves('slit'): if he.unit_normal()[0] < 0:
def test_subsample_deterministic(self): """ When evaluating a deterministic function while specifying a subsample, n_subsample copies of the function output should be returned. """ # # Deterministic functions # # Functions fns = { 1: { 1: lambda x: x[:, 0]**2, 2: lambda x, y: x[:, 0] + y[:, 0] }, 2: { 1: lambda x: x[:, 0]**2 + x[:, 1]**2, 2: lambda x, y: x[:, 0] * y[:, 0] + x[:, 1] * y[:, 1] } } # Singletons x = {1: {1: 2, 2: (3, 4)}, 2: {1: (1, 2), 2: ((1, 2), (3, 4))}} xv = { 1: { 1: [(2, ), (2, )], 2: ([(3, ), (3, )], [(4, ), (4, )]) }, 2: { 1: [(1, 2), (1, 2)], 2: ([(1, 2), (1, 2)], [(3, 4), (3, 4)]) } } vals = {1: {1: 4, 2: 7}, 2: {1: 5, 2: 11}} subsample = np.array([2, 3], dtype=np.int) for dim in [1, 2]: # # Iterate over dimension # # DofHandler if dim == 1: mesh = Mesh1D(box=[0, 5], resolution=(1, )) elif dim == 2: mesh = QuadMesh(box=[0, 5, 0, 5]) element = QuadFE(dim, 'Q2') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() basis = Basis(dofhandler) for n_variables in [1, 2]: # # Iterate over number of variables # # # Explicit # f = fns[dim][n_variables] # Explicit fe = Explicit(f, n_variables=n_variables, dim=dim, \ subsample=subsample) # Nodal fn = Nodal(f, n_variables=n_variables, basis=basis, dim=dim, \ dofhandler=dofhandler, subsample=subsample) # Constant fc = Constant(1, n_variables=n_variables, \ subsample=subsample) # Singleton input xn = x[dim][n_variables] # Explicit self.assertEqual(fe.eval(xn).shape[1], len(subsample)) self.assertEqual(fe.eval(xn)[0, 0], vals[dim][n_variables]) self.assertEqual(fe.eval(xn)[0, 1], vals[dim][n_variables]) # Nodal self.assertEqual(fn.eval(xn).shape[1], len(subsample)) self.assertAlmostEqual( fn.eval(xn)[0, 0], vals[dim][n_variables]) self.assertAlmostEqual( fn.eval(xn)[0, 1], vals[dim][n_variables]) # Constant self.assertEqual(fc.eval(xn).shape[1], len(subsample)) self.assertAlmostEqual(fc.eval(xn)[0, 0], 1) self.assertAlmostEqual(fc.eval(xn)[0, 1], 1) # Vector input xn = xv[dim][n_variables] n_points = 2 # Explicit self.assertEqual(fe.eval(xn).shape, (2, 2)) for i in range(fe.n_subsample()): for j in range(n_points): self.assertEqual( fe.eval(xn)[i][j], vals[dim][n_variables]) # Nodal self.assertEqual(fn.eval(xn).shape, (2, 2)) for i in range(fe.n_subsample()): for j in range(n_points): self.assertAlmostEqual( fn.eval(xn)[i][j], vals[dim][n_variables]) # Constant self.assertEqual(fc.eval(xn).shape, (2, 2)) for i in range(fe.n_subsample()): for j in range(n_points): self.assertEqual(fc.eval(xn)[i][j], 1)
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()))
from diagnostics import Verbose # Built-in modules import numpy as np import scipy.linalg as la import matplotlib.pyplot as plt """ Investigate local error estimates on the resolution of a random field """ plot = Plot() # # Computational mesh # mesh = QuadMesh(resolution=(4, 4)) # Mark boundary bnd_fn = lambda x, y: abs(x) < 1e-6 or abs(1 - x) < 1e-6 or abs( y) < 1e-6 or abs(1 - y) < 1e-6 mesh.mark_region('bnd', bnd_fn, entity_type='half_edge', on_boundary=True) # Mark averaging region dmn_fn = lambda x, y: x >= 0.75 and x <= 1 and y >= 0.75 and y <= 1 mesh.mark_region('dmn', dmn_fn, entity_type='cell', strict_containment=True, on_boundary=False) #cells = mesh.get_region(flag='dmn', entity_type='cell', on_boundary=False, subforest_flag=None) plot.mesh(mesh, regions=[('bnd', 'edge'), ('dmn', 'cell')])
def test_derivative(self): """ Compute the derivatives of a Nodal Map """ # Define meshes for each dimension meshes = {1: Mesh1D(resolution=(2, )), 2: QuadMesh(resolution=(2, 2))} # Define elements for each dimension elements = {1: QuadFE(1, 'Q2'), 2: QuadFE(2, 'Q2')} # Use function to set data fns = {1: lambda x: 2 * x[:, 0]**2, 2: lambda x: x[:, 0]**2 + x[:, 1]} derivatives = {1: [(1, 0), (2, 0)], 2: [(1, 0), (1, 1), (2, 0, 0)]} dfdx_exact = { 1: [lambda x: 4 * x[:, 0][:, None], lambda x: 4 * np.ones(x.shape)], 2: [ lambda x: 2 * x[:, 0][:, None], lambda x: np.ones(x.shape), lambda x: 2 * np.ones(x.shape) ] } # n_samples = 2 parms = {1: [{}, {}], 2: [{}, {}]} for dim in [1, 2]: mesh = meshes[dim] # Random points in domain n_points = 5 if dim == 1: x_min, x_max = mesh.bounding_box() x = x_min + 0.5 * (x_max - x_min) * np.random.rand(n_points) x = x[:, np.newaxis] elif dim == 2: x_min, x_max, y_min, y_max = mesh.bounding_box() x = np.zeros((n_points, 2)) x[:, 0] = x_min + (x_max - x_min) * np.random.rand(n_points) x[:, 1] = y_min + (y_max - y_min) * np.random.rand(n_points) element = elements[dim] fn = fns[dim] dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() basis = Basis(dofhandler) # # Deterministic # f = Nodal(f=fn, basis=basis, mesh=mesh, element=element, dim=dim, n_variables=1) count = 0 for derivative in derivatives[dim]: # Evaluate the derivative dfdx = f.differentiate(derivative) self.assertTrue( np.allclose(dfdx.eval(x=x), dfdx_exact[dim][count](x))) count += 1 # # Sampled # parm = parms[dim] f = Nodal(f=fn, parameters=parm, basis=basis, mesh=mesh, element=element, dim=dim) count = 0 for derivative in derivatives[dim]: # Evaluate the derivative dfdx = f.differentiate(derivative) self.assertTrue( np.allclose( dfdx.eval(x=x)[:, 0], dfdx_exact[dim][count](x)[:, 0])) self.assertTrue( np.allclose( dfdx.eval(x=x)[:, 1], dfdx_exact[dim][count](x)[:, 0])) count += 1
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])
from fem import QuadFE from fem import DofHandler from fem import Form from fem import Basis from fem import Kernel from fem import GaussRule from fem import Assembler from fem import Function from plot import Plot from scipy import sparse as sp import numpy as np # # Define Mesh # mesh = QuadMesh(resolution=(2,1)) mesh.cells.get_child(1).mark('1') mesh.cells.refine(refinement_flag='1') # # Define element # Q1 = QuadFE(2,'Q1') # # Basis Functions # u = Basis(Q1, 'u') ux = Basis(Q1, 'ux') uy = Basis(Q1, 'uy')
Created on Mon Apr 4 16:17:45 2022 @author: hans-werner """ from mesh import QuadMesh from fem import DofHandler, Basis, QuadFE from function import Nodal from gmrf import GaussianField, SPDMatrix, Covariance from plot import Plot from assembler import Assembler, Form, Kernel import numpy as np # Computational mesh mesh = QuadMesh(resolution=(50, 50)) # Mark Dirichlet boundary regions out_fn = lambda x, y: abs(x - 1) < 1e-8 and 0.8 <= y and y <= 1 mesh.mark_region('out', out_fn, entity_type='half_edge', on_boundary=True) in_fn = lambda x, y: abs(x) < 1e-8 and 0 <= y and y <= 0.2 mesh.mark_region('in', in_fn, entity_type='half_edge', on_boundary=True) x_min, x_max = 0.7, 0.8 y_min, y_max = 0.4, 0.5 reg_fn = lambda x, y: x >= x_min and x <= x_max and y >= y_min and y <= y_max mesh.mark_region('reg', reg_fn, entity_type='cell') # Elements Q1 = QuadFE(mesh.dim(), 'Q1')
def test_eval_phi(self): """ Check that the shapes are correct """ # # Mesh # mesh = QuadMesh() dim = mesh.dim() # # element information # element = QuadFE(dim, 'Q2') dofhandler = DofHandler(mesh, element) dofhandler.distribute_dofs() # Basis basis = Basis(dofhandler) # Define phi n_points = 5 phi = np.random.rand(n_points, 2) dofs = [0, 1] # # Deterministic Data # n_dofs = dofhandler.n_dofs() data = np.random.rand(n_dofs) # Define deterministic function f = Nodal(data=data, basis=basis) # Evaluate and check dimensions fx = f.eval(phi=phi, dofs=dofs) self.assertEqual(fx.shape, (n_points, 1)) # # Sampled Data # n_samples = 4 data = np.random.rand(n_dofs, n_samples) # Define stochastic function f = Nodal(data=data, basis=basis, dofhandler=dofhandler) # Evaluate and check dimensions fx = f.eval(phi=phi, dofs=dofs) self.assertEqual(fx.shape, (n_points, n_samples)) # # Bivariate deterministic # data = np.random.rand(n_dofs, n_dofs, 1) # Define deterministic function f = Nodal(data=data, basis=basis, dofhandler=dofhandler, n_variables=2) fx = f.eval(phi=(phi, phi), dofs=(dofs, dofs)) self.assertEqual(fx.shape, (n_points, 1)) # # Bivariate sampled # data = np.random.rand(n_dofs, n_dofs, n_samples) # Define stochastic function f = Nodal(data=data, basis=basis, dofhandler=dofhandler, n_variables=2) fx = f.eval(phi=(phi, phi), dofs=(dofs, dofs)) self.assertEqual(fx.shape, (n_points, n_samples)) # # Trivariate deterministic # data = np.random.rand(n_dofs, n_dofs, n_dofs, 1) f = Nodal(data=data, basis=basis, dofhandler=dofhandler, n_variables=3)