def test_TFE_2Dx1D_scalar_quad(): T = UFCInterval() P1 = Lagrange(T, 1) P1_DG = DiscontinuousLagrange(T, 1) elt = TensorProductElement(TensorProductElement(P1, P1_DG), P1) assert elt.value_shape() == () tab = elt.tabulate(1, [(0.1, 0.2, 0.3)]) tA = P1.tabulate(1, [(0.1, )]) tB = P1_DG.tabulate(1, [(0.2, )]) tC = P1.tabulate(1, [(0.3, )]) for da, db, dc in [[(0, ), (0, ), (0, )], [(1, ), (0, ), (0, )], [(0, ), (1, ), (0, )], [(0, ), (0, ), (1, )]]: dd = da + db + dc assert np.isclose(tab[dd][0][0], tA[da][0][0] * tB[db][0][0] * tC[dc][0][0]) assert np.isclose(tab[dd][1][0], tA[da][0][0] * tB[db][0][0] * tC[dc][1][0]) assert np.isclose(tab[dd][2][0], tA[da][0][0] * tB[db][1][0] * tC[dc][0][0]) assert np.isclose(tab[dd][3][0], tA[da][0][0] * tB[db][1][0] * tC[dc][1][0]) assert np.isclose(tab[dd][4][0], tA[da][1][0] * tB[db][0][0] * tC[dc][0][0]) assert np.isclose(tab[dd][5][0], tA[da][1][0] * tB[db][0][0] * tC[dc][1][0]) assert np.isclose(tab[dd][6][0], tA[da][1][0] * tB[db][1][0] * tC[dc][0][0]) assert np.isclose(tab[dd][7][0], tA[da][1][0] * tB[db][1][0] * tC[dc][1][0])
def construct_dg_element(ref_el, degree): """Constructs a discontinuous galerkin element of a given degree on a particular reference cell. """ if ref_el.get_shape() in [LINE, TRIANGLE]: dg_element = DiscontinuousLagrange(ref_el, degree) # Quadrilateral facets could be on a FiredrakeQuadrilateral. # In this case, we treat this as an interval x interval cell: elif ref_el.get_shape() == QUADRILATERAL: dg_a = DiscontinuousLagrange(ufc_simplex(1), degree) dg_b = DiscontinuousLagrange(ufc_simplex(1), degree) dg_element = TensorProductElement(dg_a, dg_b) # This handles the more general case for facets: elif ref_el.get_shape() == TENSORPRODUCT: assert len(degree) == len(ref_el.cells), ( "Must provide the same number of degrees as the number " "of cells that make up the tensor product cell." ) sub_elements = [construct_dg_element(c, d) for c, d in zip(ref_el.cells, degree) if c.get_shape() != POINT] if len(sub_elements) > 1: dg_element = TensorProductElement(*sub_elements) else: dg_element, = sub_elements else: raise NotImplementedError( "Reference cells of type %s not currently supported" % type(ref_el) ) return dg_element
def test_TFE_2Dx1D_vector_quad_hdiv(): T = UFCInterval() P1 = Lagrange(T, 1) P0 = DiscontinuousLagrange(T, 0) P1_DG = DiscontinuousLagrange(T, 1) P1P0 = Hdiv(TensorProductElement(P1, P0)) P0P1 = Hdiv(TensorProductElement(P0, P1)) horiz_elt = EnrichedElement(P1P0, P0P1) elt = Hdiv(TensorProductElement(horiz_elt, P1_DG)) assert elt.value_shape() == (3, ) tab = elt.tabulate(1, [(0.1, 0.2, 0.3)]) tA = P1.tabulate(1, [(0.1, )]) tB = P0.tabulate(1, [(0.2, )]) tC = P0.tabulate(1, [(0.1, )]) tD = P1.tabulate(1, [(0.2, )]) tE = P1_DG.tabulate(1, [(0.3, )]) for da, db, dc in [[(0, ), (0, ), (0, )], [(1, ), (0, ), (0, )], [(0, ), (1, ), (0, )], [(0, ), (0, ), (1, )]]: dd = da + db + dc assert np.isclose(tab[dd][0][0][0], -tA[da][0][0] * tB[db][0][0] * tE[dc][0][0]) assert np.isclose(tab[dd][1][0][0], -tA[da][0][0] * tB[db][0][0] * tE[dc][1][0]) assert np.isclose(tab[dd][2][0][0], -tA[da][1][0] * tB[db][0][0] * tE[dc][0][0]) assert np.isclose(tab[dd][3][0][0], -tA[da][1][0] * tB[db][0][0] * tE[dc][1][0]) assert tab[dd][4][0][0] == 0.0 assert tab[dd][5][0][0] == 0.0 assert tab[dd][6][0][0] == 0.0 assert tab[dd][7][0][0] == 0.0 assert tab[dd][0][1][0] == 0.0 assert tab[dd][1][1][0] == 0.0 assert tab[dd][2][1][0] == 0.0 assert tab[dd][3][1][0] == 0.0 assert np.isclose(tab[dd][4][1][0], tC[da][0][0] * tD[db][0][0] * tE[dc][0][0]) assert np.isclose(tab[dd][5][1][0], tC[da][0][0] * tD[db][0][0] * tE[dc][1][0]) assert np.isclose(tab[dd][6][1][0], tC[da][0][0] * tD[db][1][0] * tE[dc][0][0]) assert np.isclose(tab[dd][7][1][0], tC[da][0][0] * tD[db][1][0] * tE[dc][1][0]) assert tab[dd][0][2][0] == 0.0 assert tab[dd][1][2][0] == 0.0 assert tab[dd][2][2][0] == 0.0 assert tab[dd][3][2][0] == 0.0 assert tab[dd][4][2][0] == 0.0 assert tab[dd][5][2][0] == 0.0 assert tab[dd][6][2][0] == 0.0 assert tab[dd][7][2][0] == 0.0
def test_flattened_against_tpe_quad(): T = UFCInterval() P1 = Lagrange(T, 1) tpe_quad = TensorProductElement(P1, P1) flattened_quad = FlattenedDimensions(tpe_quad) assert tpe_quad.value_shape() == () tpe_tab = tpe_quad.tabulate(1, [(0.1, 0.2)]) flattened_tab = flattened_quad.tabulate(1, [(0.1, 0.2)]) for da, db in [[(0,), (0,)], [(1,), (0,)], [(0,), (1,)]]: dc = da + db assert np.isclose(tpe_tab[dc][0][0], flattened_tab[dc][0][0]) assert np.isclose(tpe_tab[dc][1][0], flattened_tab[dc][1][0]) assert np.isclose(tpe_tab[dc][2][0], flattened_tab[dc][2][0]) assert np.isclose(tpe_tab[dc][3][0], flattened_tab[dc][3][0])
def test_flattened_against_tpe_quad(): T = UFCInterval() P1 = Lagrange(T, 1) tpe_quad = TensorProductElement(P1, P1) flattened_quad = FlattenedDimensions(tpe_quad) assert tpe_quad.value_shape() == () tpe_tab = tpe_quad.tabulate(1, [(0.1, 0.2)]) flattened_tab = flattened_quad.tabulate(1, [(0.1, 0.2)]) for da, db in [[(0, ), (0, )], [(1, ), (0, )], [(0, ), (1, )]]: dc = da + db assert np.isclose(tpe_tab[dc][0][0], flattened_tab[dc][0][0]) assert np.isclose(tpe_tab[dc][1][0], flattened_tab[dc][1][0]) assert np.isclose(tpe_tab[dc][2][0], flattened_tab[dc][2][0]) assert np.isclose(tpe_tab[dc][3][0], flattened_tab[dc][3][0])
def test_TFE_2Dx1D_vector_triangle_hcurl(): S = UFCTriangle() T = UFCInterval() Ned1 = Nedelec(S, 1) P1 = Lagrange(T, 1) elt = Hcurl(TensorProductElement(Ned1, P1)) assert elt.value_shape() == (3, ) tab = elt.tabulate(1, [(0.1, 0.2, 0.3)]) tabA = Ned1.tabulate(1, [(0.1, 0.2)]) tabB = P1.tabulate(1, [(0.3, )]) for da, db in [[(0, 0), (0, )], [(1, 0), (0, )], [(0, 1), (0, )], [(0, 0), (1, )]]: dc = da + db assert np.isclose(tab[dc][0][0][0], tabA[da][0][0][0] * tabB[db][0][0]) assert np.isclose(tab[dc][1][0][0], tabA[da][0][0][0] * tabB[db][1][0]) assert np.isclose(tab[dc][2][0][0], tabA[da][1][0][0] * tabB[db][0][0]) assert np.isclose(tab[dc][3][0][0], tabA[da][1][0][0] * tabB[db][1][0]) assert np.isclose(tab[dc][4][0][0], tabA[da][2][0][0] * tabB[db][0][0]) assert np.isclose(tab[dc][5][0][0], tabA[da][2][0][0] * tabB[db][1][0]) assert np.isclose(tab[dc][0][1][0], tabA[da][0][1][0] * tabB[db][0][0]) assert np.isclose(tab[dc][1][1][0], tabA[da][0][1][0] * tabB[db][1][0]) assert np.isclose(tab[dc][2][1][0], tabA[da][1][1][0] * tabB[db][0][0]) assert np.isclose(tab[dc][3][1][0], tabA[da][1][1][0] * tabB[db][1][0]) assert np.isclose(tab[dc][4][1][0], tabA[da][2][1][0] * tabB[db][0][0]) assert np.isclose(tab[dc][5][1][0], tabA[da][2][1][0] * tabB[db][1][0]) assert tab[dc][0][2][0] == 0.0 assert tab[dc][1][2][0] == 0.0 assert tab[dc][2][2][0] == 0.0 assert tab[dc][3][2][0] == 0.0 assert tab[dc][4][2][0] == 0.0 assert tab[dc][5][2][0] == 0.0
def test_TFE_2Dx1D_vector_triangle_hdiv(): S = UFCTriangle() T = UFCInterval() RT1 = RaviartThomas(S, 1) P1_DG = DiscontinuousLagrange(T, 1) elt = Hdiv(TensorProductElement(RT1, P1_DG)) assert elt.value_shape() == (3, ) tab = elt.tabulate(1, [(0.1, 0.2, 0.3)]) tabA = RT1.tabulate(1, [(0.1, 0.2)]) tabB = P1_DG.tabulate(1, [(0.3, )]) for da, db in [[(0, 0), (0, )], [(1, 0), (0, )], [(0, 1), (0, )], [(0, 0), (1, )]]: dc = da + db assert np.isclose(tab[dc][0][0][0], tabA[da][0][0][0] * tabB[db][0][0]) assert np.isclose(tab[dc][1][0][0], tabA[da][0][0][0] * tabB[db][1][0]) assert np.isclose(tab[dc][2][0][0], tabA[da][1][0][0] * tabB[db][0][0]) assert np.isclose(tab[dc][3][0][0], tabA[da][1][0][0] * tabB[db][1][0]) assert np.isclose(tab[dc][4][0][0], tabA[da][2][0][0] * tabB[db][0][0]) assert np.isclose(tab[dc][5][0][0], tabA[da][2][0][0] * tabB[db][1][0]) assert np.isclose(tab[dc][0][1][0], tabA[da][0][1][0] * tabB[db][0][0]) assert np.isclose(tab[dc][1][1][0], tabA[da][0][1][0] * tabB[db][1][0]) assert np.isclose(tab[dc][2][1][0], tabA[da][1][1][0] * tabB[db][0][0]) assert np.isclose(tab[dc][3][1][0], tabA[da][1][1][0] * tabB[db][1][0]) assert np.isclose(tab[dc][4][1][0], tabA[da][2][1][0] * tabB[db][0][0]) assert np.isclose(tab[dc][5][1][0], tabA[da][2][1][0] * tabB[db][1][0]) assert tab[dc][0][2][0] == 0.0 assert tab[dc][1][2][0] == 0.0 assert tab[dc][2][2][0] == 0.0 assert tab[dc][3][2][0] == 0.0 assert tab[dc][4][2][0] == 0.0 assert tab[dc][5][2][0] == 0.0
def test_TFE_1Dx1D_scalar(): T = UFCInterval() P1_DG = DiscontinuousLagrange(T, 1) P2 = Lagrange(T, 2) elt = TensorProductElement(P1_DG, P2) assert elt.value_shape() == () tab = elt.tabulate(1, [(0.1, 0.2)]) tabA = P1_DG.tabulate(1, [(0.1,)]) tabB = P2.tabulate(1, [(0.2,)]) for da, db in [[(0,), (0,)], [(1,), (0,)], [(0,), (1,)]]: dc = da + db assert np.isclose(tab[dc][0][0], tabA[da][0][0]*tabB[db][0][0]) assert np.isclose(tab[dc][1][0], tabA[da][0][0]*tabB[db][1][0]) assert np.isclose(tab[dc][2][0], tabA[da][0][0]*tabB[db][2][0]) assert np.isclose(tab[dc][3][0], tabA[da][1][0]*tabB[db][0][0]) assert np.isclose(tab[dc][4][0], tabA[da][1][0]*tabB[db][1][0]) assert np.isclose(tab[dc][5][0], tabA[da][1][0]*tabB[db][2][0])
def test_TFE_1Dx1D_vector(): T = UFCInterval() P1_DG = DiscontinuousLagrange(T, 1) P2 = Lagrange(T, 2) elt = TensorProductElement(P1_DG, P2) hdiv_elt = Hdiv(elt) hcurl_elt = Hcurl(elt) assert hdiv_elt.value_shape() == (2, ) assert hcurl_elt.value_shape() == (2, ) tabA = P1_DG.tabulate(1, [(0.1, )]) tabB = P2.tabulate(1, [(0.2, )]) hdiv_tab = hdiv_elt.tabulate(1, [(0.1, 0.2)]) for da, db in [[(0, ), (0, )], [(1, ), (0, )], [(0, ), (1, )]]: dc = da + db assert hdiv_tab[dc][0][0][0] == 0.0 assert hdiv_tab[dc][1][0][0] == 0.0 assert hdiv_tab[dc][2][0][0] == 0.0 assert hdiv_tab[dc][3][0][0] == 0.0 assert hdiv_tab[dc][4][0][0] == 0.0 assert hdiv_tab[dc][5][0][0] == 0.0 assert np.isclose(hdiv_tab[dc][0][1][0], tabA[da][0][0] * tabB[db][0][0]) assert np.isclose(hdiv_tab[dc][1][1][0], tabA[da][0][0] * tabB[db][1][0]) assert np.isclose(hdiv_tab[dc][2][1][0], tabA[da][0][0] * tabB[db][2][0]) assert np.isclose(hdiv_tab[dc][3][1][0], tabA[da][1][0] * tabB[db][0][0]) assert np.isclose(hdiv_tab[dc][4][1][0], tabA[da][1][0] * tabB[db][1][0]) assert np.isclose(hdiv_tab[dc][5][1][0], tabA[da][1][0] * tabB[db][2][0]) hcurl_tab = hcurl_elt.tabulate(1, [(0.1, 0.2)]) for da, db in [[(0, ), (0, )], [(1, ), (0, )], [(0, ), (1, )]]: dc = da + db assert np.isclose(hcurl_tab[dc][0][0][0], tabA[da][0][0] * tabB[db][0][0]) assert np.isclose(hcurl_tab[dc][1][0][0], tabA[da][0][0] * tabB[db][1][0]) assert np.isclose(hcurl_tab[dc][2][0][0], tabA[da][0][0] * tabB[db][2][0]) assert np.isclose(hcurl_tab[dc][3][0][0], tabA[da][1][0] * tabB[db][0][0]) assert np.isclose(hcurl_tab[dc][4][0][0], tabA[da][1][0] * tabB[db][1][0]) assert np.isclose(hcurl_tab[dc][5][0][0], tabA[da][1][0] * tabB[db][2][0]) assert hcurl_tab[dc][0][1][0] == 0.0 assert hcurl_tab[dc][1][1][0] == 0.0 assert hcurl_tab[dc][2][1][0] == 0.0 assert hcurl_tab[dc][3][1][0] == 0.0 assert hcurl_tab[dc][4][1][0] == 0.0 assert hcurl_tab[dc][5][1][0] == 0.0
def test_TFE_1Dx1D_scalar(): T = UFCInterval() P1_DG = DiscontinuousLagrange(T, 1) P2 = Lagrange(T, 2) elt = TensorProductElement(P1_DG, P2) assert elt.value_shape() == () tab = elt.tabulate(1, [(0.1, 0.2)]) tabA = P1_DG.tabulate(1, [(0.1, )]) tabB = P2.tabulate(1, [(0.2, )]) for da, db in [[(0, ), (0, )], [(1, ), (0, )], [(0, ), (1, )]]: dc = da + db assert np.isclose(tab[dc][0][0], tabA[da][0][0] * tabB[db][0][0]) assert np.isclose(tab[dc][1][0], tabA[da][0][0] * tabB[db][1][0]) assert np.isclose(tab[dc][2][0], tabA[da][0][0] * tabB[db][2][0]) assert np.isclose(tab[dc][3][0], tabA[da][1][0] * tabB[db][0][0]) assert np.isclose(tab[dc][4][0], tabA[da][1][0] * tabB[db][1][0]) assert np.isclose(tab[dc][5][0], tabA[da][1][0] * tabB[db][2][0])
def test_flattened_against_tpe_hex(): T = UFCInterval() P1 = Lagrange(T, 1) tpe_quad = TensorProductElement(P1, P1) tpe_hex = TensorProductElement(tpe_quad, P1) flattened_quad = FlattenedDimensions(tpe_quad) flattened_hex = FlattenedDimensions(TensorProductElement(flattened_quad, P1)) assert tpe_quad.value_shape() == () tpe_tab = tpe_hex.tabulate(1, [(0.1, 0.2, 0.3)]) flattened_tab = flattened_hex.tabulate(1, [(0.1, 0.2, 0.3)]) for da, db, dc in [[(0,), (0,), (0,)], [(1,), (0,), (0,)], [(0,), (1,), (0,)], [(0,), (0,), (1,)]]: dd = da + db + dc assert np.isclose(tpe_tab[dd][0][0], flattened_tab[dd][0][0]) assert np.isclose(tpe_tab[dd][1][0], flattened_tab[dd][1][0]) assert np.isclose(tpe_tab[dd][2][0], flattened_tab[dd][2][0]) assert np.isclose(tpe_tab[dd][3][0], flattened_tab[dd][3][0]) assert np.isclose(tpe_tab[dd][4][0], flattened_tab[dd][4][0]) assert np.isclose(tpe_tab[dd][5][0], flattened_tab[dd][5][0]) assert np.isclose(tpe_tab[dd][6][0], flattened_tab[dd][6][0]) assert np.isclose(tpe_tab[dd][7][0], flattened_tab[dd][7][0])
def test_TFE_2Dx1D_scalar_quad(): T = UFCInterval() P1 = Lagrange(T, 1) P1_DG = DiscontinuousLagrange(T, 1) elt = TensorProductElement(TensorProductElement(P1, P1_DG), P1) assert elt.value_shape() == () tab = elt.tabulate(1, [(0.1, 0.2, 0.3)]) tA = P1.tabulate(1, [(0.1,)]) tB = P1_DG.tabulate(1, [(0.2,)]) tC = P1.tabulate(1, [(0.3,)]) for da, db, dc in [[(0,), (0,), (0,)], [(1,), (0,), (0,)], [(0,), (1,), (0,)], [(0,), (0,), (1,)]]: dd = da + db + dc assert np.isclose(tab[dd][0][0], tA[da][0][0]*tB[db][0][0]*tC[dc][0][0]) assert np.isclose(tab[dd][1][0], tA[da][0][0]*tB[db][0][0]*tC[dc][1][0]) assert np.isclose(tab[dd][2][0], tA[da][0][0]*tB[db][1][0]*tC[dc][0][0]) assert np.isclose(tab[dd][3][0], tA[da][0][0]*tB[db][1][0]*tC[dc][1][0]) assert np.isclose(tab[dd][4][0], tA[da][1][0]*tB[db][0][0]*tC[dc][0][0]) assert np.isclose(tab[dd][5][0], tA[da][1][0]*tB[db][0][0]*tC[dc][1][0]) assert np.isclose(tab[dd][6][0], tA[da][1][0]*tB[db][1][0]*tC[dc][0][0]) assert np.isclose(tab[dd][7][0], tA[da][1][0]*tB[db][1][0]*tC[dc][1][0])
def test_TFE_2Dx1D_scalar_triangle_hdiv(): S = UFCTriangle() T = UFCInterval() P1_DG = DiscontinuousLagrange(S, 1) P2 = Lagrange(T, 2) elt = Hdiv(TensorProductElement(P1_DG, P2)) assert elt.value_shape() == (3, ) tab = elt.tabulate(1, [(0.1, 0.2, 0.3)]) tabA = P1_DG.tabulate(1, [(0.1, 0.2)]) tabB = P2.tabulate(1, [(0.3, )]) for da, db in [[(0, 0), (0, )], [(1, 0), (0, )], [(0, 1), (0, )], [(0, 0), (1, )]]: dc = da + db assert tab[dc][0][0][0] == 0.0 assert tab[dc][1][0][0] == 0.0 assert tab[dc][2][0][0] == 0.0 assert tab[dc][3][0][0] == 0.0 assert tab[dc][4][0][0] == 0.0 assert tab[dc][5][0][0] == 0.0 assert tab[dc][6][0][0] == 0.0 assert tab[dc][7][0][0] == 0.0 assert tab[dc][8][0][0] == 0.0 assert tab[dc][0][1][0] == 0.0 assert tab[dc][1][1][0] == 0.0 assert tab[dc][2][1][0] == 0.0 assert tab[dc][3][1][0] == 0.0 assert tab[dc][4][1][0] == 0.0 assert tab[dc][5][1][0] == 0.0 assert tab[dc][6][1][0] == 0.0 assert tab[dc][7][1][0] == 0.0 assert tab[dc][8][1][0] == 0.0 assert np.isclose(tab[dc][0][2][0], tabA[da][0][0] * tabB[db][0][0]) assert np.isclose(tab[dc][1][2][0], tabA[da][0][0] * tabB[db][1][0]) assert np.isclose(tab[dc][2][2][0], tabA[da][0][0] * tabB[db][2][0]) assert np.isclose(tab[dc][3][2][0], tabA[da][1][0] * tabB[db][0][0]) assert np.isclose(tab[dc][4][2][0], tabA[da][1][0] * tabB[db][1][0]) assert np.isclose(tab[dc][5][2][0], tabA[da][1][0] * tabB[db][2][0]) assert np.isclose(tab[dc][6][2][0], tabA[da][2][0] * tabB[db][0][0]) assert np.isclose(tab[dc][7][2][0], tabA[da][2][0] * tabB[db][1][0]) assert np.isclose(tab[dc][8][2][0], tabA[da][2][0] * tabB[db][2][0])
def test_flattened_against_tpe_hex(): T = UFCInterval() P1 = Lagrange(T, 1) tpe_quad = TensorProductElement(P1, P1) tpe_hex = TensorProductElement(tpe_quad, P1) flattened_quad = FlattenedDimensions(tpe_quad) flattened_hex = FlattenedDimensions( TensorProductElement(flattened_quad, P1)) assert tpe_quad.value_shape() == () tpe_tab = tpe_hex.tabulate(1, [(0.1, 0.2, 0.3)]) flattened_tab = flattened_hex.tabulate(1, [(0.1, 0.2, 0.3)]) for da, db, dc in [[(0, ), (0, ), (0, )], [(1, ), (0, ), (0, )], [(0, ), (1, ), (0, )], [(0, ), (0, ), (1, )]]: dd = da + db + dc assert np.isclose(tpe_tab[dd][0][0], flattened_tab[dd][0][0]) assert np.isclose(tpe_tab[dd][1][0], flattened_tab[dd][1][0]) assert np.isclose(tpe_tab[dd][2][0], flattened_tab[dd][2][0]) assert np.isclose(tpe_tab[dd][3][0], flattened_tab[dd][3][0]) assert np.isclose(tpe_tab[dd][4][0], flattened_tab[dd][4][0]) assert np.isclose(tpe_tab[dd][5][0], flattened_tab[dd][5][0]) assert np.isclose(tpe_tab[dd][6][0], flattened_tab[dd][6][0]) assert np.isclose(tpe_tab[dd][7][0], flattened_tab[dd][7][0])
def Hdiv(element): if not isinstance(element, TensorProductElement): raise NotImplementedError if element.A.get_formdegree() is None or element.B.get_formdegree( ) is None: raise ValueError( "form degree of sub-element was None (not set during initialisation), Hdiv cannot be done without this information" ) formdegree = element.A.get_formdegree() + element.B.get_formdegree() if formdegree != element.get_reference_element().get_spatial_dimension( ) - 1: raise ValueError("Tried to use Hdiv on a non-(n-1)-form element") newelement = TensorProductElement(element.A, element.B) # make a copy to return # redefine value_shape() def value_shape(self): "Return the value shape of the finite element functions." return (self.get_reference_element().get_spatial_dimension(), ) newelement.value_shape = types.MethodType(value_shape, newelement) # store old _mapping newelement._oldmapping = newelement._mapping # redefine _mapping newelement._mapping = "contravariant piola" # store formdegree newelement.formdegree = formdegree # redefine tabulate newelement.old_tabulate = newelement.tabulate def tabulate(self, order, points, entity=None): """Return tabulated values of derivatives up to given order of basis functions at given points.""" # don't duplicate what the old function does fine... old_result = self.old_tabulate(order, points, entity) new_result = {} sd = self.get_reference_element().get_spatial_dimension() for alpha in old_result.keys(): temp_old = old_result[alpha] if self._oldmapping == "affine": temp = numpy.zeros((temp_old.shape[0], sd, temp_old.shape[1]), dtype=temp_old.dtype) # both constituents affine, i.e., they were 0 forms or n-forms. # to sum to n-1, we must have "0-form on an interval" crossed # with something discontinuous. # look for the (continuous) 0-form, and put the value there if self.A.get_formdegree() == 0: # first element, so (-x, 0, ...) # Sign flip to ensure that a positive value of the node # means a vector field having a direction "to the left" # relative to direction in which the nodes are placed on an # edge in case of higher-order schemes. # This is required for unstructured quadrilateral meshes. temp[:, 0, :] = -temp_old[:, :] elif self.B.get_formdegree() == 0: # second element, so (..., 0, x) temp[:, -1, :] = temp_old[:, :] else: raise Exception("Hdiv affine/affine form degrees broke") elif self._oldmapping == "contravariant piola": temp = numpy.zeros((temp_old.shape[0], sd, temp_old.shape[2]), dtype=temp_old.dtype) Asd = self.A.get_reference_element().get_spatial_dimension() # one component is affine, one is contravariant piola # the affine one must be an n-form, hence discontinuous # this component/these components get zeroed out if element.A.mapping()[0] == "contravariant piola": # first element, so (x1, ..., xn, 0, ...) temp[:, :Asd, :] = temp_old[:, :, :] elif element.B.mapping()[0] == "contravariant piola": # second element, so (..., 0, x1, ..., xn) temp[:, Asd:, :] = temp_old[:, :, :] else: raise ValueError( "Hdiv contravariant piola couldn't find an existing ConPi subelement" ) elif self._oldmapping == "covariant piola": temp = numpy.zeros((temp_old.shape[0], sd, temp_old.shape[2]), dtype=temp_old.dtype) # one component is affine, one is covariant piola # the affine one must be an n-form, hence discontinuous # this component/these components get zeroed out # the remaining part gets perped if element.A.mapping()[0] == "covariant piola": Asd = self.A.get_reference_element().get_spatial_dimension( ) if not Asd == 2: raise ValueError( "Must be 2d shape to automatically convert covariant to contravariant" ) temp_perp = numpy.zeros(temp_old.shape, dtype=temp_old.dtype) # first element, so (x2, -x1, 0, ...) temp_perp[:, 0, :] = temp_old[:, 1, :] temp_perp[:, 1, :] = -temp_old[:, 0, :] temp[:, :Asd, :] = temp_perp[:, :, :] elif element.B.mapping()[0] == "covariant piola": Bsd = self.B.get_reference_element().get_spatial_dimension( ) if not Bsd == 2: raise ValueError( "Must be 2d shape to automatically convert covariant to contravariant" ) temp_perp = numpy.zeros(temp_old.shape, dtype=temp_old.dtype) # second element, so (..., 0, x2, -x1) temp_perp[:, 0, :] = temp_old[:, 1, :] temp_perp[:, 1, :] = -temp_old[:, 0, :] temp[:, Asd:, :] = temp_old[:, :, :] else: raise ValueError( "Hdiv covariant piola couldn't find an existing CovPi subelement" ) new_result[alpha] = temp return new_result newelement.tabulate = types.MethodType(tabulate, newelement) # splat any PointEvaluation functionals. # they become a nasty mix of internal and external component DOFs if newelement._oldmapping == "affine": oldnodes = newelement.dual.nodes newnodes = [] for node in oldnodes: if isinstance(node, functional.PointEvaluation): newnodes.append( functional.Functional(None, None, None, {}, "Undefined")) else: newnodes.append(node) newelement.dual.nodes = newnodes return newelement
def Hdiv(element): if not isinstance(element, TensorProductElement): raise NotImplementedError if element.A.get_formdegree() is None or element.B.get_formdegree() is None: raise ValueError("form degree of sub-element was None (not set during initialisation), Hdiv cannot be done without this information") formdegree = element.A.get_formdegree() + element.B.get_formdegree() if formdegree != element.get_reference_element().get_spatial_dimension() - 1: raise ValueError("Tried to use Hdiv on a non-(n-1)-form element") newelement = TensorProductElement(element.A, element.B) # make a copy to return # redefine value_shape() def value_shape(self): "Return the value shape of the finite element functions." return (self.get_reference_element().get_spatial_dimension(),) newelement.value_shape = types.MethodType(value_shape, newelement) # store old _mapping newelement._oldmapping = newelement._mapping # redefine _mapping newelement._mapping = "contravariant piola" # store formdegree newelement.formdegree = formdegree # redefine tabulate newelement.old_tabulate = newelement.tabulate def tabulate(self, order, points, entity=None): """Return tabulated values of derivatives up to given order of basis functions at given points.""" # don't duplicate what the old function does fine... old_result = self.old_tabulate(order, points, entity) new_result = {} sd = self.get_reference_element().get_spatial_dimension() for alpha in old_result.keys(): temp_old = old_result[alpha] if self._oldmapping == "affine": temp = numpy.zeros((temp_old.shape[0], sd, temp_old.shape[1]), dtype=temp_old.dtype) # both constituents affine, i.e., they were 0 forms or n-forms. # to sum to n-1, we must have "0-form on an interval" crossed # with something discontinuous. # look for the (continuous) 0-form, and put the value there if self.A.get_formdegree() == 0: # first element, so (-x, 0, ...) # Sign flip to ensure that a positive value of the node # means a vector field having a direction "to the left" # relative to direction in which the nodes are placed on an # edge in case of higher-order schemes. # This is required for unstructured quadrilateral meshes. temp[:, 0, :] = -temp_old[:, :] elif self.B.get_formdegree() == 0: # second element, so (..., 0, x) temp[:, -1, :] = temp_old[:, :] else: raise Exception("Hdiv affine/affine form degrees broke") elif self._oldmapping == "contravariant piola": temp = numpy.zeros((temp_old.shape[0], sd, temp_old.shape[2]), dtype=temp_old.dtype) Asd = self.A.get_reference_element().get_spatial_dimension() # one component is affine, one is contravariant piola # the affine one must be an n-form, hence discontinuous # this component/these components get zeroed out if element.A.mapping()[0] == "contravariant piola": # first element, so (x1, ..., xn, 0, ...) temp[:, :Asd, :] = temp_old[:, :, :] elif element.B.mapping()[0] == "contravariant piola": # second element, so (..., 0, x1, ..., xn) temp[:, Asd:, :] = temp_old[:, :, :] else: raise ValueError("Hdiv contravariant piola couldn't find an existing ConPi subelement") elif self._oldmapping == "covariant piola": temp = numpy.zeros((temp_old.shape[0], sd, temp_old.shape[2]), dtype=temp_old.dtype) # one component is affine, one is covariant piola # the affine one must be an n-form, hence discontinuous # this component/these components get zeroed out # the remaining part gets perped if element.A.mapping()[0] == "covariant piola": Asd = self.A.get_reference_element().get_spatial_dimension() if not Asd == 2: raise ValueError("Must be 2d shape to automatically convert covariant to contravariant") temp_perp = numpy.zeros(temp_old.shape, dtype=temp_old.dtype) # first element, so (x2, -x1, 0, ...) temp_perp[:, 0, :] = temp_old[:, 1, :] temp_perp[:, 1, :] = -temp_old[:, 0, :] temp[:, :Asd, :] = temp_perp[:, :, :] elif element.B.mapping()[0] == "covariant piola": Bsd = self.B.get_reference_element().get_spatial_dimension() if not Bsd == 2: raise ValueError("Must be 2d shape to automatically convert covariant to contravariant") temp_perp = numpy.zeros(temp_old.shape, dtype=temp_old.dtype) # second element, so (..., 0, x2, -x1) temp_perp[:, 0, :] = temp_old[:, 1, :] temp_perp[:, 1, :] = -temp_old[:, 0, :] temp[:, Asd:, :] = temp_old[:, :, :] else: raise ValueError("Hdiv covariant piola couldn't find an existing CovPi subelement") new_result[alpha] = temp return new_result newelement.tabulate = types.MethodType(tabulate, newelement) # splat any PointEvaluation functionals. # they become a nasty mix of internal and external component DOFs if newelement._oldmapping == "affine": oldnodes = newelement.dual.nodes newnodes = [] for node in oldnodes: if isinstance(node, functional.PointEvaluation): newnodes.append(functional.Functional(None, None, None, {}, "Undefined")) else: newnodes.append(node) newelement.dual.nodes = newnodes return newelement