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