Example #1
0
    def test_bin_points(self):
        #
        # Cell vertices
        #
        v1 = Vertex((0, 0))
        v2 = Vertex((1, 0))
        v3 = Vertex((1, 1))
        v4 = Vertex((0, 1))

        # Cell HalfEdges
        h12 = HalfEdge(v1, v2)
        h23 = HalfEdge(v2, v3)
        h34 = HalfEdge(v3, v4)
        h41 = HalfEdge(v4, v1)

        # Cell
        cell = QuadCell([h12, h23, h34, h41])

        # Split cell twice
        cell.split()
        cell.get_child(1).split()

        #
        # Error: point not in cell
        #
        x = np.array([[-1, -1]])
        self.assertRaises(Exception, cell.bin_points, *(x, ))

        #
        # Corner points
        #
        x = convert_to_array([v1, v2, v3, v4])
        bins = cell.bin_points(x)

        # There should be four bins
        self.assertEqual(len(bins), 4)

        # No binning cells should have children
        for c, dummy in bins:
            self.assertFalse(c.has_children())

        #
        # Center point
        #
        x = np.array([[0.5, 0.5]])
        bins = cell.bin_points(x)
        self.assertEqual(len(bins), 1)

        #
        # Mark
        #
        sf = '1'
        for child in cell.get_children():
            child.mark(sf)

        x = np.array([[0.75, 0.25]])
        bins = cell.bin_points(x, subforest_flag=sf)
        for c, dummy in bins:
            self.assertTrue(c.is_marked(sf))
            self.assertFalse(c.has_children(flag=sf))
Example #2
0
 def test_subcell_position(self):
     # Define HalfEdge 
     v1, v2 = Vertex((1,1)), Vertex((2,3))
     he_ref = HalfEdge(v1,v2)
     
     # Define Bad HalfEdge
     he_bad = HalfEdge(Vertex((1.5,1.3)), Vertex((2,3)))
     
     # Assert Error 
     self.assertRaises(Exception, he_ref.subcell_position, he_bad)
  
     # Define Good HalfEdge
     V = convert_to_array([v1,v2])
     
     # Specify points along Half-Edge 
     t_min, t_max = 0.3, 0.5
     W_base = Vertex(tuple(V[0] + t_min*(V[1]-V[0])))
     W_head = Vertex(tuple(V[0] + t_max*(V[1]-V[0])))
     
     he_good = HalfEdge(W_base, W_head)
     pos, width = he_ref.subcell_position(he_good)
     
     # Check whether computed value matches reference
     self.assertAlmostEqual(pos, t_min)
     self.assertAlmostEqual(width, t_max-t_min)
Example #3
0
    def test_line_integral(self):
        # Define quadrature rule
        rule = GaussRule(2, shape='interval')
        w = rule.weights()
        x_ref = rule.nodes()

        # function f to be integrated over edge e
        f = lambda x, y: x**2 * y
        e = HalfEdge(Vertex((0, 0)), Vertex((1, 1)))

        # Map rule to physical entity
        x_phys, mg = e.reference_map(x_ref, jac_r2p=True)
        jacobian = mg['jac_r2p']

        x_phys = convert_to_array(x_phys, dim=2)
        fvec = f(x_phys[:, 0], x_phys[:, 1])

        jac = np.linalg.norm(jacobian[0])
        self.assertAlmostEqual(np.dot(fvec,w)*jac,np.sqrt(2)/4,places=10,\
                               msg='Failed to integrate x^2y.')
        self.assertAlmostEqual(np.sum(w)*jac, np.sqrt(2), places=10,\
                               msg='Failed to integrate 1.')
Example #4
0
    def test_reference_map(self):
        # New interval
        I = Interval(Vertex(2), Vertex(5))

        # New point
        x = np.array([0, 1, 0.5])

        # Map point to physical interval
        y, mg = I.reference_map(x, jac_r2p=True, hess_r2p=True)

        # Verify
        jac = mg['jac_r2p']
        hess = mg['hess_r2p']

        self.assertTrue(type(y) is np.ndarray)

        self.assertTrue(
            np.allclose(y, convert_to_array([(2, ), (5, ), (3.5, )], dim=1)))
        self.assertTrue(type(jac) is list)
        self.assertEqual(jac, [3, 3, 3])
        self.assertTrue(type(hess) is list)
        self.assertEqual(hess, [0, 0, 0])

        # Map back to reference domain
        xx, mg = I.reference_map(y,
                                 jac_p2r=True,
                                 hess_p2r=True,
                                 mapsto='reference')
        ijac = mg['jac_p2r']
        ihess = mg['hess_p2r']

        # Verify
        for i in range(3):
            self.assertEqual(xx[i], x[i])
            self.assertEqual(ijac[i], 1 / jac[i])
            self.assertEqual(ihess[i], hess[i])
Example #5
0
    def test_reference_map(self):
        v_sw = Vertex((0, 0))
        v_se = Vertex((3, 1))
        v_ne = Vertex((2, 3))
        v_nw = Vertex((-1, 1))

        h12 = HalfEdge(v_sw, v_se)
        h23 = HalfEdge(v_se, v_ne)
        h34 = HalfEdge(v_ne, v_nw)
        h41 = HalfEdge(v_nw, v_sw)
        cell = QuadCell([h12, h23, h34, h41])

        #
        # Map corner vertices of reference cell to physical vertices
        #
        y_refs = np.array([[0, 0], [1, 0], [1, 1], [0, 1]])
        x = list(convert_to_array(cell.get_vertices()))
        x_phys = cell.reference_map(list(y_refs))

        self.assertTrue(np.allclose(np.array(x),x_phys),\
                        'Mapped vertices should coincide '+\
                        'with physical cell vertices.')

        #
        # Jacobian: Area of cell by integration
        #
        rule_2d = GaussRule(order=4, shape='quadrilateral')
        r = rule_2d.nodes()
        wg = rule_2d.weights()
        dummy, mg = cell.reference_map(list(r), jac_r2p=True)
        jac = mg['jac_r2p']
        area = 0
        for i in range(4):
            j = jac[i]
            w = wg[i]
            area += np.abs(np.linalg.det(j)) * w
        self.assertAlmostEqual(cell.area(), area, 7,\
                               'Area computed via numerical quadrature '+\
                               'not close to actual area')
        #
        # Try different formats
        #
        # Array
        x = np.array(x)
        x_ref = cell.reference_map(x, mapsto='reference')
        self.assertTrue(np.allclose(y_refs, np.array(x_ref)),\
                        'Map array to reference: incorrect output.')
        # Single point
        x = x[0, :]
        x_ref = cell.reference_map(x, mapsto='reference')
        self.assertTrue(np.allclose(x, x_ref))

        #
        # Map corner vertices to reference points
        #
        x = convert_to_array(cell.get_vertices())
        y = cell.reference_map(x, mapsto='reference')
        self.assertTrue(np.allclose(y, y_refs), \
                        'Corner vertices should map '+\
                        'onto (0,0),(1,0),(1,1),(0,1).')

        #
        # Map random points in [0,1]^2 onto cell and back again
        #
        # Generate random points
        t = np.random.rand(5)
        s = np.random.rand(5)
        x = np.array([s, t]).T

        # Map to physical cell
        x_phy = cell.reference_map(x)

        # Check whether points are contained in cell
        in_cell = cell.contains_points(x_phy)
        self.assertTrue(all(in_cell), \
                        'All points mapped from [0,1]^2 '+\
                        'should be contained in the cell.')

        # Map back to reference cell
        x_ref = cell.reference_map(x_phy, mapsto='reference')
        self.assertTrue(np.allclose(np.array(x_ref), np.array(x)),\
                        'Points mapped to physical cell and back should '+\
                        'be unchanged.')

        #
        # Compute the hessian and compare with finite difference approximation
        #
        h = 1e-8
        x = np.array([[0.5, 0.5], [0.5 + h, 0.5], [0.5 - h, 0.5],
                      [0.5, 0.5 + h], [0.5, 0.5 - h]])

        x_ref, mg = cell.reference_map(x,
                                       mapsto='reference',
                                       hess_p2r=True,
                                       jac_p2r=True)
        J = mg['jac_p2r']
        H = mg['hess_p2r']

        # sxx
        sxx_fd = (J[1][0, 0] - J[2][0, 0]) / (2 * h)
        sxx = H[0][0, 0, 0]
        self.assertAlmostEqual(sxx_fd, sxx, 7, \
                               'Hessian calculation not close to '+\
                               'finite difference approximation')

        # syx
        syx_fd = (J[1][0, 1] - J[2][0, 1]) / (2 * h)
        sxy = H[0][0, 1, 0]
        syx = H[0][1, 0, 0]
        self.assertAlmostEqual(sxy, syx, 7, 'Mixed derivatives not equal.')
        self.assertAlmostEqual(syx_fd, sxy, 7, \
                               'Hessian calculation not close to '+\
                               'finite difference approximation')

        # syy
        syy_fd = (J[3][0, 1] - J[4][0, 1]) / (2 * h)
        syy = H[0][1, 1, 0]
        self.assertAlmostEqual(syy_fd, syy, 7, \
                               'Hessian calculation not close to '+\
                               'finite difference approximation')

        # txx
        txx_fd = (J[1][1, 0] - J[2][1, 0]) / (2 * h)
        txx = H[0][0, 0, 1]
        self.assertAlmostEqual(txx_fd, txx, 7, \
                               'Hessian calculation not close to '+\
                               'finite difference approximation')

        # txy
        txy_fd = (J[3][1, 0] - J[4][1, 0]) / (2 * h)
        txy = H[0][0, 1, 1]
        tyx = H[0][1, 0, 1]
        self.assertAlmostEqual(txy, tyx, 7, 'Mixed derivatives not equal.')
        self.assertAlmostEqual(txy_fd, txy, 7, \
                               'Hessian calculation not close to '+\
                               'finite difference approximation')

        # tyy
        tyy_fd = (J[3][1, 1] - J[4][1, 1]) / (2 * h)
        tyy = H[0][1, 1, 1]
        self.assertAlmostEqual(tyy_fd, tyy, 7, \
                               'Hessian calculation not close to '+\
                               'finite difference approximation')
Example #6
0
    def test_reference_quadcell(self):
        """
        Test Constructor
        
        TODO:
        
            - test 1D: 
            - test all reference cells (?)
        """
        # =====================================================================
        # Reference Interval/Cell
        # =====================================================================
        #
        #  1D
        #
        #
        # Check if reference interval contain the correct vertices
        #
        etypes = ['DQ0', 'DQ1', 'DQ2', 'DQ3', 'Q1', 'Q2', 'Q3']
        dv = dict.fromkeys(etypes)
        dv['DQ0'] = {0: [0.5], 1: {0: [0.25], 1: [0.75]}}
        dv['DQ1'] = {0: [0, 1], 1: {0: [0, 0.5], 1: [0.5, 1]}}
        dv['DQ2'] = {0: [0, 1, 0.5], 1: {0: [0, 0.5, 0.25], 1: [0.5, 1, 0.75]}}
        dv['DQ3'] = {
            0: [0, 1, 1 / 3, 2 / 3],
            1: {
                0: [0, 0.5, 1 / 6, 1 / 3],
                1: [0.5, 1, 2 / 3, 5 / 6]
            }
        }
        dv['Q1'] = {0: [0, 1], 1: {0: [0, 0.5], 1: [0.5, 1]}}
        dv['Q2'] = {0: [0, 1, 0.5], 1: {0: [0, 0.5, 0.25], 1: [0.5, 1, 0.75]}}
        dv['Q3'] = {
            0: [0, 1, 1 / 3, 2 / 3],
            1: {
                0: [0, 0.5, 1 / 6, 1 / 3],
                1: [0.5, 1, 2 / 3, 5 / 6]
            }
        }
        for etype in etypes:
            element = QuadFE(1, etype)
            cell = element.reference_cell()
            for level in range(2):
                if level == 0:
                    v = convert_to_array(cell.get_dof_vertices(level))
                    self.assertTrue(
                        np.allclose(np.array(dv[etype][level]), v[:, 0]))
                elif level == 1:
                    for child in range(2):
                        v = convert_to_array(
                            cell.get_dof_vertices(level, child))
                        self.assertTrue(
                            np.allclose(np.array(dv[etype][level][child]),
                                        v[:, 0]))
        #
        # Check if the vertices on the fine level are correctly linked with those on the coarse level
        #
        # TODO:

        #
        # Test Positions
        #
        for etype in ['DQ0', 'DQ1', 'DQ2', 'DQ3', 'Q1', 'Q2', 'Q3']:
            element = QuadFE(2, etype)
            cell = element.reference_cell()
            if etype == 'Q1' or etype == 'DQ1':
                # Level 1, child 0, vertex 0 = Level 0, vertex 0
                vertex = cell.get_dof_vertices(1, 0, 0)
                self.assertEqual(vertex.get_pos(1, 0), vertex.get_pos(0))

                # Level 1, child 2, vertex 2 = Level 0, vertex 1
                vertex = cell.get_dof_vertices(1, 2, 2)
                self.assertEqual(vertex.get_pos(1, 2), vertex.get_pos(0))

                # Level 1, child 2, vertex 0 has no inherited vertex
                vertex = cell.get_dof_vertices(1, 2, 0)
                self.assertIsNone(vertex.get_pos(0))

            elif etype == 'Q2':
                # All children share middle vertex
                for i in range(4):
                    vertex = cell.get_dof_vertices(1, i, (i + 2) % 4)
                    self.assertEqual(vertex.get_pos(0), 8)
            elif etype == 'DQ2':
                # Only first child shares middle vertex
                for i in range(4):
                    vertex = cell.get_dof_vertices(1, i, (i + 2) % 4)
                    if i == 0:
                        self.assertEqual(vertex.get_pos(0), 8)
                    else:
                        self.assertIsNone(vertex.get_pos(0))

                # Level 1, child 1, vertex 0 has no inherited vertex
                vertex = cell.get_dof_vertices(1, 1, 0)
                self.assertIsNone(vertex.get_pos(0))

                # Level 1, child 1, vertex 5 has no inherited vertex
                vertex = cell.get_dof_vertices(1, 1, 5)
                self.assertIsNone(vertex.get_pos(0))
            elif etype == 'Q3' or etype == 'DQ3':
                # Level 1, child 2, vertex 2 = Level 0, vertex 2
                vertex = cell.get_dof_vertices(1, 2, 2)
                self.assertEqual(vertex.get_pos(1, 2), vertex.get_pos(0))

                # Level 1, child 2, vertex 6 = Level 0, vertex 7
                vertex = cell.get_dof_vertices(1, 2, 6)
                self.assertEqual(vertex.get_pos(0), 7)

                # Level 1, child 2, vertex 12 = Level 0, vertex 15
                vertex = cell.get_dof_vertices(1, 2, 12)
                self.assertEqual(vertex.get_pos(0), 15)
Example #7
0
    def test_shape_eval(self):
        """
        Routine evaluates all shape functions on given cell
        """
        #
        # Diamond-shaped region
        #

        # Vertices
        A = Vertex((0, -1))
        B = Vertex((1, 0))
        C = Vertex((0, 1))
        D = Vertex((-1, 0))

        # Half-edges
        AB = HalfEdge(A, B)
        BC = HalfEdge(B, C)
        CD = HalfEdge(C, D)
        DA = HalfEdge(D, A)

        # Cell
        cell = QuadCell([AB, BC, CD, DA])

        # 1D Quadrature Rule
        rule = GaussRule(4, shape='interval')
        xx = rule.nodes()
        ww = rule.weights()

        #
        # Map rule to physical domain (CD)
        #
        xg, mg = CD.reference_map(xx, jac_r2p=True)
        xg = convert_to_array(xg)

        # Modify weights
        jac = mg['jac_r2p']
        wg = ww * np.array(np.linalg.norm(jac[0]))

        # Check length of edge is sqrt(2)
        self.assertTrue(np.allclose(np.sum(wg), np.sqrt(2)))

        # Check Int x^2 y on CD
        f = lambda x, y: x**2 * y
        fx = f(xg[:, 0], xg[:, 1])

        self.assertTrue(np.allclose(np.sum(fx * wg), np.sqrt(2) * (1 / 12)))

        #
        # Use shape functions to evaluate line integral
        #

        #
        # Map 1D rule onto reference cell
        #
        Q = QuadFE(2, 'Q1')
        rcell = Q.reference_cell()

        # Determine equivalent Half-edge on reference element
        i_he = cell.get_half_edges().index(CD)
        ref_he = rcell.get_half_edge(i_he)

        # Get 2D reference nodes
        b, h = convert_to_array(ref_he.get_vertices())
        x_ref = np.array([b[i] + xx * (h[i] - b[i]) for i in range(2)]).T

        # Map 2D reference point to phyisical cell
        xxg, mg = cell.reference_map(x_ref,
                                     jac_r2p=False,
                                     jac_p2r=True,
                                     hess_p2r=True)

        self.assertTrue(np.allclose(xxg, xg))

        # Evaluate the shape functions
        phi = Q.shape(x_ref, cell, [(0, ), (1, 0), (1, 1)], mg['jac_p2r'])

        # x = phi1 - phi3
        self.assertTrue(np.allclose(phi[0][:, 1] - phi[0][:, 3], xg[:, 0]))

        # y = -phi0 + phi2
        self.assertTrue(np.allclose(-phi[0][:, 0] + phi[0][:, 2], xg[:, 1]))

        # g(x,y) = x - y = phi*[1,1,-1-1]
        c = np.array([1, 1, -1, -1])
        g = phi[0].dot(c)

        # Int_CD x-y ds
        self.assertTrue(np.allclose(np.sum(wg * g), -np.sqrt(2)))

        # Integrals involving phi_x, phi_y
        gx = phi[1].dot(c)
        gy = phi[2].dot(c)

        n = CD.unit_normal()

        self.assertTrue(np.allclose(np.sum(wg * (gx * n[0] + gy * n[1])), -2))
Example #8
0
 def add_dirichlet_constraint(self, bnd_marker, dirichlet_function=0, 
                              on_boundary=True):
     """
     Modify an assembled bilinear/linear pair to account for Dirichlet 
     boundary conditions. The system matrix is modified "in place", 
     i.e. 
 
         a11 a12 a13 a14   u1     b1
         a21 a22 a23 a24   u2  =  b2 
         a31 a32 a33 a34   u3     b3
         a41 a42 a43 a44   u4     b4
         
     Suppose Dirichlet conditions u2=g2 and u4=g4 are prescribed. 
     The system is converted to
     
         a11  0  a13  0   u1     b1 - a12*g2 - a14*g4
          0   1   0   0   u2  =  0   
         a31  0  a33  0   u3     b3 - a32*g2 - a34*g4
          0   0   0   1   u4     0 
     
     The solution [u1,u3]^T of this system is then enlarged with the 
     dirichlet boundary values g2 and g4 by invoking 'resolve_constraints' 
     
 
     Inputs:
     
         bnd_marker: str/int flag to identify boundary
         
         dirichlet_function: Function, defining the Dirichlet boundary 
             conditions.
         
         on_boundary: bool, True if function values are prescribed on
             boundary.
         
         
     Notes:
     
     To maintain the dimensions of the matrix, the trial and test function 
     spaces must be the same, i.e. it must be a Galerkin approximation. 
     
     Specifying the Dirichlet conditions this way is necessary if there
     are hanging nodes, since a Dirichlet node may be a supporting node for
     one of the hanging nodes.  
             
             
     Inputs:
     
         bnd_marker: flag, used to mark the Dirichlet boundary
                     
         dirichlet_fn: Function, specifying the function values on the  
             Dirichlet boundary. 
     
         
     Outputs:
     
         None 
         
         
     Modified Attributes:
     
         __A: modify Dirichlet rows and colums (shrink)
         
         __b: modify right hand side (shrink)
         
         dirichlet: add dictionary,  {mask: np.ndarray, vals: np.ndarray}
     """
     #
     # Get Dofs Associated with Dirichlet boundary
     #
     subforest_flag = self.get_basis().subforest_flag()
     dh = self.get_dofhandler()
     
     if dh.mesh.dim()==1:
         #
         # One dimensional mesh
         # 
         dirichlet_dofs = dh.get_region_dofs(entity_type='vertex', \
                                             entity_flag=bnd_marker,\
                                             interior=False, \
                                             on_boundary=on_boundary,\
                                             subforest_flag=subforest_flag)
     elif dh.mesh.dim()==2:
         #
         # Two dimensional mesh
         #
         dirichlet_dofs = dh.get_region_dofs(entity_type='half_edge', 
                                             entity_flag=bnd_marker, 
                                             interior=False, 
                                             on_boundary=on_boundary, \
                                             subforest_flag=subforest_flag) 
     
     
     #
     # Evaluate dirichlet function at vertices associated with dirichlet dofs
     # 
     dirichlet_vertices = dh.get_dof_vertices(dirichlet_dofs)
     if isinstance(dirichlet_function, numbers.Number):
         #
         # Dirichlet function is constant
         # 
         n_dirichlet = len(dirichlet_dofs)
         if dirichlet_function==0:
             #
             # Homogeneous boundary conditions
             # 
             dirichlet_vals = np.zeros(n_dirichlet)
         else:
             #
             # Non-homogeneous, constant boundary conditions
             # 
             dirichlet_vals = dirichlet_function*np.ones(n_dirichlet)
     else:
         #
         # Nonhomogeneous, nonconstant Dirichlet boundary conditions 
         #
         x_dir = convert_to_array(dirichlet_vertices)
         dirichlet_vals = dirichlet_function.eval(x_dir).ravel()
         
     constraints = dh.constraints
     for dof, val in zip(dirichlet_dofs, dirichlet_vals):
         constraints['constrained_dofs'].append(dof)
         constraints['supporting_dofs'].append([])
         constraints['coefficients'].append([])
         constraints['affine_terms'].append(val)
Example #9
0
    def test_eval(self):
        #
        # Out of the box covariance kernels
        #
        fig, ax = plt.subplots(6, 4, figsize=(5, 7))

        cov_names = [
            'constant', 'linear', 'gaussian', 'exponential', 'matern',
            'rational'
        ]

        anisotropies = {1: [None, 2], 2: [None, np.diag([2, 1])]}
        m_count = 0
        for mesh in [Mesh1D(resolution=(10, )), QuadMesh(resolution=(10, 10))]:
            # Dimension
            dim = mesh.dim()

            #
            # Construct computational mesh
            #
            # Piecewise constant elements
            element = QuadFE(dim, 'DQ0')

            # Define dofhandler -> get vertices
            dofhandler = DofHandler(mesh, element)
            dofhandler.distribute_dofs()
            dofhandler.set_dof_vertices()
            v = dofhandler.get_dof_vertices()

            # Define meshgrid for 1 and 2 dimensions
            n_dofs = dofhandler.n_dofs()
            M1, M2 = np.mgrid[0:n_dofs, 0:n_dofs]
            if dim == 1:
                X = v[:, 0][M1].ravel()
                Y = v[:, 0][M2].ravel()
            elif dim == 2:
                X = np.array([v[:, 0][M1].ravel(), v[:, 1][M1].ravel()]).T
                Y = np.array([v[:, 0][M2].ravel(), v[:, 1][M2].ravel()]).T

            x = convert_to_array(X, dim=dim)
            y = convert_to_array(Y, dim=dim)
            a_count = 0
            isotropic_label = ['isotropic', 'anisotropic']
            for M in anisotropies[dim]:
                # Cycle through anisotropies

                # Define covariance parameters
                cov_pars = {
                    'constant': {
                        'sgm': 1
                    },
                    'linear': {
                        'sgm': 1,
                        'M': M
                    },
                    'gaussian': {
                        'sgm': 1,
                        'l': 0.1,
                        'M': M
                    },
                    'exponential': {
                        'l': 0.1,
                        'M': M
                    },
                    'matern': {
                        'sgm': 1,
                        'nu': 2,
                        'l': 0.5,
                        'M': M
                    },
                    'rational': {
                        'a': 3,
                        'M': M
                    }
                }

                c_count = 0
                for cov_name in cov_names:

                    C = CovKernel(cov_name, cov_pars[cov_name])
                    Z = C.eval((x, y)).reshape(M1.shape)

                    col = int(m_count * 2**1 + a_count * 2**0)
                    row = c_count
                    ax[row, col].imshow(Z)
                    if col == 0:
                        ax[row, col].set_ylabel(cov_name)

                    if row == 0:
                        ax[row, col].set_title('%dD mesh\n %s' %
                                               (dim, isotropic_label[a_count]))

                    ax[row, col].set_xticks([], [])
                    ax[row, col].set_yticks([], [])

                    c_count += 1
                a_count += 1
            m_count += 1
        fig.savefig('test_covkernel_eval.eps')