Beispiel #1
0
 def test_constructor(self):
     """
     Constructor
     """
     #
     # Triangle
     # 
     v1 = Vertex((0,0))
     v2 = Vertex((1,0))
     v3 = Vertex((0,1))
     
     h12 = HalfEdge(v1, v2)
     h23 = HalfEdge(v2, v3)
     h31 = HalfEdge(v3, v1)
     
     # Vertices not in order
     bad_list_1 = [h12, h31, h23]
     self.assertRaises(Exception, Cell, *[bad_list_1])
     
     # Not a closed loop
     bad_list_2 = [h12, h23]
     self.assertRaises(Exception, Cell, *[bad_list_2])
 
     triangle_half_edges = [h12, h23, h31]
     cell = Cell(triangle_half_edges)
     self.assertAlmostEqual(cell.area(),0.5)
     self.assertEqual(cell.n_vertices(),3)
     self.assertEqual(cell.n_half_edges(),3)
     half_edge = cell.get_half_edge(0)
     for i in range(3):
         self.assertEqual(half_edge.next(), triangle_half_edges[(i+1)%3])
         half_edge = half_edge.next()
     
     #
     # Square 
     # 
     v4 = Vertex((1,1))
     h24 = HalfEdge(v2,v4)
     h43 = HalfEdge(v4,v3)
     square_half_edges = [h12, h24, h43, h31]
     cell = Cell(square_half_edges)
     self.assertAlmostEqual(cell.area(),1)
     self.assertEqual(cell.n_vertices(),4)
     self.assertEqual(cell.n_half_edges(),4)
Beispiel #2
0
 def test_split(self):
     #
     # New HalfEdge
     #
     v1 = Vertex((0,0))
     v2 = Vertex((2,2))
     half_edge = HalfEdge(v1, v2)
     #
     # Split it
     # 
     half_edge.split()
     #
     # Check if the children behave
     # 
     child_0, child_1 = half_edge.get_children()
     self.assertEqual(child_0.head(), child_1.base(),\
                      'First child head should equal second child base.')    
     #
     # Define twin half edge
     # 
     twin = HalfEdge(v2, v1)
     half_edge.assign_twin(twin)
     twin.assign_twin(half_edge)
     
     #
     # Split twin
     # 
     twin.split()
     
     #
     # Check wether children are twinned
     # 
     c0, c1 = half_edge.get_children()
     t0, t1 = twin.get_children()
     self.assertEqual(c0.base(),t1.head(),\
                      'Children have incorrect twins.')
     self.assertEqual(c0.head(),t1.base(),\
                      'Children have incorrect twins.')
     self.assertEqual(c1.base(),t0.head(),\
                      'Children have incorrect twins.')
     self.assertEqual(c1.head(),t0.base(),\
                      'Children have incorrect twins.')
Beispiel #3
0
 def test_make_twin(self):
     #
     # New HalfEdge
     #
     v1 = Vertex((0,0))
     v2 = Vertex((2,2))
     h12 = HalfEdge(v1,v2)
     h21 = h12.make_twin()
     self.assertIsNotNone(h12.twin())
     self.assertIsNotNone(h21.twin())
     self.assertEqual(h12.base(),h21.head())
     self.assertEqual(h21.base(),h12.head())
Beispiel #4
0
 def test_reference_map(self):
     v1 = Vertex((1,1))
     v2 = Vertex((2,3))
     
     h = HalfEdge(v1,v2)
     
     x = np.linspace(0, 1, 5)
     points = h.reference_map(x)
             
     y = h.reference_map(points, mapsto='reference')
     for (yi,xi) in zip(x,y):
         self.assertAlmostEqual(xi,yi)
Beispiel #5
0
 def test_assign_twin(self):
     #
     # New half-edge
     # 
     v1 = Vertex((0,0))
     v2 = Vertex((1,1))
     half_edge = HalfEdge(v1, v2)
     #
     # Try to assign incorrect twin
     # 
     false_twin = HalfEdge(v1, v2)
     self.assertRaises(Exception, half_edge.assign_twin, false_twin,\
                       'This twin should not be assignable.')
     #
     # Assign a good twin and check 
     # 
     good_twin = HalfEdge(v2, v1)
     half_edge.assign_twin(good_twin)
     self.assertEqual(good_twin.base(),half_edge.head(), \
                      'Heads and bases do not match.')
     self.assertEqual(good_twin.head(),half_edge.base(), \
                      'Heads and bases do not match.')
Beispiel #6
0
 def test_unit_normal(self):
     # 
     # Define a HalfEdge
     # 
     v1 = Vertex((0,0))
     v2 = Vertex((0,1))
     h1 = HalfEdge(v1,v2)
     #
     # Make sure computed unit normal is correct
     #
     u  = np.array([1,0])
     self.assertTrue(np.allclose(h1.unit_normal(), u),\
                            'Incorrect unit normal')
     #
     # Reverse direction of unit HalfEdge
     # 
     h2 = HalfEdge(v2,v1)
     #
     # Check unit normal
     # 
     u = np.array([-1,0])
     self.assertTrue(np.allclose(h2.unit_normal(), u),\
                            'Incorrect unit normal')
Beispiel #7
0
 def test_mark(self):
     #
     # Define a HalfEdge
     # 
     v1 = Vertex((0,0))
     v2 = Vertex((0,1))
     h_edge = HalfEdge(v1,v2)
     #
     # Mark it
     # 
     h_edge.mark(1)
     self.assertTrue(h_edge.is_marked(1),'HalfEdge should be marked.') 
     #
     # Mark when initializing
     # 
     h_edge = HalfEdge(v1, v2, flag=1)
     self.assertTrue(h_edge.is_marked(1),'HalfEdge should be marked.')
     #
     # Split and mark recursively
     # 
     h_edge.split()
     h_edge.mark(flag=1, recursive=True)
     for child in h_edge.get_children():
         self.assertTrue(child.is_marked(1),'HalfEdge should be marked.')
Beispiel #8
0
 def test_get_parent(self):
     #
     # New HalfEdge
     #
     v1 = Vertex((0,0))
     v2 = Vertex((2,2))
     half_edge = HalfEdge(v1, v2)
     
     # Split
     half_edge.split()
     
     # Check if half_edge is children's parent
     for child in half_edge.get_children():
         self.assertEqual(half_edge, child.get_parent(),\
                          'HalfEdge should be child"s parent')
Beispiel #9
0
 def test_assign_previous(self):
     #
     # New HalfEdge
     #
     v1 = Vertex((0,0))
     v2 = Vertex((2,2))
     v3 = Vertex((3,4))
     h = HalfEdge(v1, v2)
     #
     # Incompatible previous half_edge
     # 
     bad_h_prev = HalfEdge(v1, v3)
     self.assertRaises(Exception, h.assign_previous, (bad_h_prev))
     #
     # Assign good next half-edge
     # 
     good_h_previous = HalfEdge(v2, v1)
     h.assign_previous(good_h_previous)
     
     # Check
     self.assertEqual(h.previous(),good_h_previous,\
                      'Next HalfEdge incorrect.')
     self.assertEqual(h.base(), h.previous().head(), \
                      'Bases and heads should align.')
Beispiel #10
0
 def test_assign_next(self):
     #
     # New HalfEdge
     #
     v1 = Vertex((0,0))
     v2 = Vertex((2,2))
     v3 = Vertex((3,4))
     h = HalfEdge(v1, v2)
     #
     # Incompatible next half_edge
     # 
     bad_h_next = HalfEdge(v1, v3)
     self.assertRaises(Exception, h.assign_next, (bad_h_next))
     #
     # Assign good next half-edge
     # 
     good_h_next = HalfEdge(v2, v3)
     h.assign_next(good_h_next)
     
     # Check
     self.assertEqual(h.next(),good_h_next,\
                      'Next HalfEdge incorrect.')
     self.assertEqual(h.head(), h.next().base(), \
                      'Bases and heads should align.')
Beispiel #11
0
 def test_incident_half_edge(self):
     #
     # Triangle
     # 
     v1 = Vertex((0,0))
     v2 = Vertex((1,0))
     v3 = Vertex((0,1))
     
     h12 = HalfEdge(v1, v2)
     h23 = HalfEdge(v2, v3)
     h31 = HalfEdge(v3, v1)
     
     cell = Cell([h12, h23, h31])
     
     hes_forward = [h31, h12, h23]
     hes_reverse = [h12, h23, h31]
     vs = [v1,v2,v3]
     for i in range(3):
         # forward
         self.assertEqual(cell.incident_half_edge(vs[i]),hes_forward[i])
         
         # backward
         self.assertEqual(cell.incident_half_edge(vs[i], reverse=True),\
                          hes_reverse[i])
Beispiel #12
0
 def test_has_children(self):
     #
     # New HalfEdge
     #
     v1 = Vertex((0,0))
     v2 = Vertex((2,2))
     half_edge = HalfEdge(v1, v2)
     
     # Shouldn't have children
     self.assertFalse(half_edge.has_children(),\
                      'Half Edge should not have children')
     
     # Split edge
     half_edge.split()
     
     # Should have children
     self.assertTrue(half_edge.has_children(),\
                     'HalfEdge should have children.')
Beispiel #13
0
 def test_has_parent(self):
     #
     # New HalfEdge
     #
     v1 = Vertex((0,0))
     v2 = Vertex((2,2))
     half_edge = HalfEdge(v1, v2)
     
     self.assertFalse(half_edge.has_parent(), \
                      'Half Edge should not have a parent.')
     
     # Split edge
     half_edge.split()
     
     # Children should have parent
     for child in half_edge.get_children():
         self.assertTrue(child.has_parent(), \
                         'HalfEdge children should have a parent.')
Beispiel #14
0
 def test_unmark(self):
     #
     # Define a HalfEdge
     # 
     v1 = Vertex((0,0))
     v2 = Vertex((0,1))
     h_edge = HalfEdge(v1,v2)
     #
     # Mark it with a specific flag
     # 
     h_edge.mark(1)
     self.assertTrue(h_edge.is_marked(1),'HalfEdge should be marked.')
     #
     # Unmark it 
     # 
     h_edge.unmark(1)
     self.assertFalse(h_edge.is_marked(),'HalfEdge should be marked.')
     self.assertFalse(h_edge.is_marked(1),'HalfEdge should be marked.')
Beispiel #15
0
    def test_split(self):
        # Rectangle
        v1 = Vertex((0, 0))
        v2 = Vertex((1, 0))
        v3 = Vertex((1, 1))
        v4 = Vertex((0, 1))
        v5 = Vertex((2, 0))
        v6 = Vertex((2, 1))

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

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

        cell.split()

        self.assertTrue(cell.has_children())

        # Check that interior half_edges are twinned
        child_0 = cell.get_child(0)
        child_1 = cell.get_child(1)
        self.assertEqual(child_0.get_half_edge(1).twin(), \
                         child_1.get_half_edge(3))

        # Make another cell, check that it is a neighbor, and then split it
        h25 = HalfEdge(v2, v5)
        h56 = HalfEdge(v5, v6)
        h63 = HalfEdge(v6, v3)
        h32 = h23.make_twin()

        cell_1 = QuadCell([h25, h56, h63, h32])

        # Check that they are neighbors
        self.assertEqual(cell_1.get_neighbors(h32), cell)

        # Child_s doesn't have a neighbor
        self.assertIsNone(child_1.get_neighbors(child_1.get_half_edge(1)))

        cell_1.split()

        # Now the child has a neighbor
        self.assertEqual(child_1.get_neighbors(child_1.get_half_edge(1)),
                         cell_1.get_child(0))
Beispiel #16
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.')
Beispiel #17
0
    def test_is_rectangle(self):
        #
        # Rectangle
        #
        v1 = Vertex((0, 0))
        v2 = Vertex((1, 0))
        v3 = Vertex((1, 1))
        v4 = Vertex((0, 1))
        h12 = HalfEdge(v1, v2)
        h23 = HalfEdge(v2, v3)
        h34 = HalfEdge(v3, v4)
        h41 = HalfEdge(v4, v1)

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

        # Check cell
        self.assertTrue(cell.is_rectangle())

        cell.split()

        # Check child
        self.assertTrue(cell.get_child(0).is_rectangle())

        #
        # Not a rectangle
        #
        v5 = Vertex((2, 2))
        h25 = HalfEdge(v2, v5)
        h54 = HalfEdge(v5, v4)

        cell = QuadCell([h12, h25, h54, h41])

        # Check cell
        self.assertFalse(cell.is_rectangle())

        cell.split()

        # Check child
        self.assertFalse(cell.get_child(0).is_rectangle())
Beispiel #18
0
    print(phii[cell][phi_1])

    f_loc = problem[0].eval(cell, xi_g, wi_g, phii, dofsi)
    #print(f_loc,'\n')

plot = Plot(quickview=False)
fig, ax = plt.subplots(1, 1)
ax = plot.mesh(mesh, axis=ax, show_axis=True)
plt.show()

#%% Mapping to a rectangular cell

# Define a QuadCell
v1, v2, v3, v4 = Vertex((1, 1)), Vertex((2, 1)), Vertex((2, 5)), Vertex((1, 5))
halfedges = [
    HalfEdge(v1, v2),
    HalfEdge(v2, v3),
    HalfEdge(v3, v4),
    HalfEdge(v4, v1)
]
cell = QuadCell(halfedges)
cell.split()

plot = Plot(quickview=False)
fig, ax = plt.subplots(1, 1)

# Plot cell and children
for c in cell.traverse():
    vertices = [v.coordinates() for v in c.get_vertices()]
    poly = plt.Polygon(vertices, fc=clrs.to_rgba('w'), edgecolor=(0, 0, 0, 1))
    ax.add_patch(poly)
Beispiel #19
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')
Beispiel #20
0
ax = plt.subplot(111)
print(ax)

#
# Define vertices
#
v1 = Vertex((1, 1))
v2 = Vertex((2, 3))
v3 = Vertex((1.5, 5))
v4 = Vertex((0, 2))
vertices = [v1, v2, v3, v4]

#
# Define HalfEdges
#
h12 = HalfEdge(v1, v2)
h23 = HalfEdge(v2, v3)
h34 = HalfEdge(v3, v4)
h41 = HalfEdge(v4, v1)
halfedges = [h12, h23, h34, h41]
#
# Define QuadCell
#
cell = QuadCell(halfedges)
print(cell.is_rectangle())
for v in vertices:
    x, y = v.coordinates()
    plt.plot(x, y, '.k')

for he in halfedges:
    x0, y0 = he.base().coordinates()
Beispiel #21
0
from function import Explicit
from mesh import Mesh1D
from mesh import QuadMesh
from mesh import Vertex
from mesh import HalfEdge
from solver import LinearSystem as LS
from plot import Plot
import numpy as np

# =============================================================================
# Computational mesh
# =============================================================================
mesh = QuadMesh(box=[-0.5, 0.5, -0.5, 0.5], resolution=(20, 20))

# Mark slit region
slit = HalfEdge(Vertex((0, 0)), Vertex((0, -0.5)))
sf = lambda x, y: slit.contains_points(np.array([x, y]))[0]
mesh.mark_region('slit', sf, entity_type='half_edge')

# Mark perimeter
tol = 1e-9
pf = lambda x,y: np.abs(x+0.5)<tol or np.abs(x-0.5)<tol or \
                 np.abs(y+0.5)<tol or np.abs(y-0.5)<tol
mesh.mark_region('perimeter', pf, entity_type='half_edge')

# Get rid of neighbors of half-edges on slit
for he in mesh.half_edges.get_leaves('slit'):
    if he.unit_normal()[0] < 0:
        he.mark('B')
mesh.tear_region('B')
Beispiel #22
0
 def test_get_neighbors(self):
     #
     # HalfEdge pivot
     # 
     
     #
     # Cell with no neighbors
     # 
     v1 = Vertex((0,0))
     v2 = Vertex((1,0))
     v3 = Vertex((0,1))
     
     h12 = HalfEdge(v1, v2)
     h23 = HalfEdge(v2, v3)
     h31 = HalfEdge(v3, v1)
     #
     # Make triangle
     # 
     cell = Cell([h12, h23, h31])
     # No neighbors
     self.assertIsNone(cell.get_neighbors(h12))
     self.assertEqual(cell.get_neighbors(v1),[])
     
     # Add a new neighboring triangle
     v4 = Vertex((1,1))
     h24 = HalfEdge(v2, v4)
     h43 = HalfEdge(v4 ,v3)
     h32 = h23.make_twin()
     
     ncell_1 = Cell([h24, h43, h32])
     
     # Make sure they are neighbors wrt halfedge
     self.assertEqual(cell.get_neighbors(h23),ncell_1)
     
     # Neighbors wrt vertices
     self.assertEqual(cell.get_neighbors(v2),[ncell_1])
     self.assertEqual(cell.get_neighbors(v3),[ncell_1])
     
     #
     # Add a third neighboring triangle
     #
     v5 = Vertex((1,2))
     h34 = h43.make_twin()
     h45 = HalfEdge(v4, v5)
     h53 = HalfEdge(v5, v3)
     
     ncell_2 = Cell([h34, h45, h53])
     
     # Check if it's a neighbor wrt halfedge
     self.assertEqual(ncell_1.get_neighbors(h43), ncell_2)
     
     # 2 Neighbors wrt v3 
     self.assertEqual(cell.get_neighbors(v3),[ncell_1, ncell_2])
     self.assertEqual(ncell_1.get_neighbors(v3), [ncell_2, cell])
     self.assertEqual(ncell_2.get_neighbors(v3), [cell, ncell_1])
     
     #
     # Split h31 and make an illegal neighbor
     #
     v6 = Vertex((-1,0.5))
      
     h31.split()
     h331 = h31.get_child(0)
     
     h133 = h331.make_twin()
     h36 = HalfEdge(v3, v6)
     h613 = HalfEdge(v6, h133.base())
     
     ncell_3 = Cell([h133, h36, h613])
     
     # No neighbors wrt shared edges
     self.assertIsNone(cell.get_neighbors(h31))
     self.assertIsNone(ncell_3.get_neighbors(h133))
     
     # Neighbors wrt vertices remain as they are.
     self.assertEqual(cell.get_neighbors(v3),[ncell_1, ncell_2])
     self.assertEqual(ncell_1.get_neighbors(v3), [ncell_2, cell])
     self.assertEqual(ncell_2.get_neighbors(v3), [cell, ncell_1])
     self.assertEqual(ncell_3.get_neighbors(v3), [])
Beispiel #23
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.')
Beispiel #24
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))