def test_phi(self): for etype in ['DQ0', 'Q1', 'Q2', 'Q3']: element = QuadFE(2, etype) n_dofs = element.n_dofs() I = np.eye(n_dofs) x = element.reference_nodes() for n in range(n_dofs): self.assertTrue(np.allclose(element.phi(n,x),I[:,n]),\ 'Shape function evaluation incorrect')
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_shape(self): """ Test shape functions """ test_functions = {'Q1': (lambda x,y: (x+1)*(y-1), lambda x,y: y-1, \ lambda x,y: x+1), 'Q2': (lambda x,y: x**2 -1, lambda x,y: 2*x, \ lambda x,y: 0*x), 'Q3': (lambda x,y: x**3 - y**3, lambda x,y: 3*x**2, \ lambda x,y: -3*y**2)} # # Over reference cell # cell_integrals = { 'Q1': [-0.75, -0.5, 1.5], 'Q2': [-2 / 3., 1.0, 0.0], 'Q3': [0., 1.0, -1.0] } derivatives = [(0, ), (1, 0), (1, 1)] for etype in ['Q1', 'Q2', 'Q3']: element = QuadFE(2, etype) n_dofs = element.n_dofs() x_ref = element.reference_nodes() # # Sanity check # I = np.eye(n_dofs) self.assertTrue(np.allclose(element.shape(x_ref),I),\ 'Shape functions incorrect at reference nodes.') y = np.random.rand(5, 2) rule2d = GaussRule(9, element=element) weights = rule2d.weights() x_gauss = rule2d.nodes() f_nodes = test_functions[etype][0](x_ref[:, 0], x_ref[:, 1]) for i in range(3): phi = element.shape(y, derivatives=derivatives[i]) f = test_functions[etype][i] # # Interpolation # fvals = f(y[:, 0], y[:, 1]) self.assertTrue(np.allclose(np.dot(phi,f_nodes),fvals),\ 'Shape function interpolation failed.') # # Integration # phi = element.shape(x_gauss, derivatives=derivatives[i]) self.assertAlmostEqual(np.dot(weights,np.dot(phi,f_nodes)),\ cell_integrals[etype][i],places=8,\ msg='Incorrect integral.') # On Physical cell # # Non-rectangular quadcell # test_functions['Q1'] = (lambda x, y: (x + 1) + (y - 1), lambda x, y: np.ones(x.shape), lambda x, y: np.ones(y.shape)) # Vertices v0 = Vertex((0, 0)) v1 = Vertex((0.5, 0.5)) v2 = Vertex((0, 2)) v3 = Vertex((-0.5, 0.5)) # half_edges h01 = HalfEdge(v0, v1) h12 = HalfEdge(v1, v2) h23 = HalfEdge(v2, v3) h30 = HalfEdge(v3, v0) # quadcell cell = QuadCell([h01, h12, h23, h30]) for etype in ['Q1', 'Q2', 'Q3']: element = QuadFE(2, etype) n_dofs = element.n_dofs() x_ref = element.reference_nodes() x, mg = cell.reference_map(x_ref, jac_p2r=True, hess_p2r=True) # # Sanity check # I = np.eye(n_dofs) shape = element.shape(x_ref, cell, jac_p2r=mg['jac_p2r'], hess_p2r=mg['hess_p2r']) self.assertTrue(np.allclose(shape,I),\ 'Shape functions incorrect at reference nodes.') # Random points in the reference domain y_ref = np.random.rand(5, 2) y, mg = cell.reference_map(y_ref, jac_p2r=True, hess_p2r=True) self.assertTrue(all(cell.contains_points(y)),\ 'Cell should contain all mapped points') f_nodes = test_functions[etype][0](x[:, 0], x[:, 1]) for i in range(3): phi = element.shape(y_ref, cell=cell, derivatives=derivatives[i], jac_p2r=mg['jac_p2r'], hess_p2r=mg['hess_p2r']) f = test_functions[etype][i] # # Interpolation # fvals = f(y[:, 0], y[:, 1]) self.assertTrue(np.allclose(np.dot(phi,f_nodes),fvals),\ 'Shape function interpolation failed.')