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 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))