예제 #1
0
    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)
예제 #2
0
    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))