def test_quad_trace(degree): """Test the trace element defined on a quadrilateral cell""" from FIAT import ufc_simplex, HDivTrace, make_quadrature from FIAT.reference_element import TensorProductCell tpc = TensorProductCell(ufc_simplex(1), ufc_simplex(1)) fiat_element = HDivTrace(tpc, (degree, degree)) facet_elements = fiat_element.dg_elements quadrule = make_quadrature(ufc_simplex(1), degree + 1) for i, entity in enumerate([((0, 1), 0), ((0, 1), 1), ((1, 0), 0), ((1, 0), 1)]): entity_dim, _ = entity element = facet_elements[entity_dim] nf = element.space_dimension() tab = fiat_element.tabulate(0, quadrule.pts, entity)[(0, 0)][nf*i:nf*(i+1)] for test_degree in range(degree + 1): coeffs = [n(lambda x: x[0]**test_degree) for n in element.dual.nodes] integral = np.dot(coeffs, np.dot(tab, quadrule.wts)) reference = np.dot([x[0]**test_degree for x in quadrule.pts], quadrule.wts) assert np.allclose(integral, reference, rtol=1e-14)
def test_quad_trace(degree): """Test the trace element defined on a quadrilateral cell""" from FIAT import ufc_simplex, HDivTrace, make_quadrature from FIAT.reference_element import TensorProductCell tpc = TensorProductCell(ufc_simplex(1), ufc_simplex(1)) fiat_element = HDivTrace(tpc, (degree, degree)) facet_elements = fiat_element.dg_elements quadrule = make_quadrature(ufc_simplex(1), degree + 1) for i, entity in enumerate([((0, 1), 0), ((0, 1), 1), ((1, 0), 0), ((1, 0), 1)]): entity_dim, _ = entity element = facet_elements[entity_dim] nf = element.space_dimension() tab = fiat_element.tabulate(0, quadrule.pts, entity)[(0, 0)][nf * i:nf * (i + 1)] for test_degree in range(degree + 1): coeffs = [ n(lambda x: x[0]**test_degree) for n in element.dual.nodes ] integral = np.dot(coeffs, np.dot(tab, quadrule.wts)) reference = np.dot([x[0]**test_degree for x in quadrule.pts], quadrule.wts) assert np.allclose(integral, reference, rtol=1e-14)
def test_cell_traceerror(dim, degree): """Ensure that the TraceError appears in all dict entries when deliberately attempting to tabulate the cell of a trace element.""" from FIAT import ufc_simplex, HDivTrace, make_quadrature from FIAT.hdiv_trace import TraceError fiat_element = HDivTrace(ufc_simplex(dim), degree) pts = make_quadrature(ufc_simplex(dim), 1).pts tab = fiat_element.tabulate(0, pts, entity=(dim, 0)) for key in tab.keys(): assert isinstance(tab[key], TraceError)
def test_gradient_traceerror(dim, order, degree): """Ensure that the TraceError appears in the appropriate dict entries when attempting to tabulate certain orders of derivatives.""" from FIAT import ufc_simplex, HDivTrace, make_quadrature from FIAT.hdiv_trace import TraceError fiat_element = HDivTrace(ufc_simplex(dim), degree) pts = make_quadrature(ufc_simplex(dim - 1), degree + 1).pts for facet_id in range(dim + 1): tab = fiat_element.tabulate(order, pts, entity=(dim - 1, facet_id)) for key in tab.keys(): if key != (0, ) * dim: assert isinstance(tab[key], TraceError)
def test_gradient_traceerror(dim, order, degree): """Ensure that the TraceError appears in the appropriate dict entries when attempting to tabulate certain orders of derivatives.""" from FIAT import ufc_simplex, HDivTrace, make_quadrature from FIAT.hdiv_trace import TraceError fiat_element = HDivTrace(ufc_simplex(dim), degree) pts = make_quadrature(ufc_simplex(dim - 1), degree + 1).pts for facet_id in range(dim + 1): tab = fiat_element.tabulate(order, pts, entity=(dim - 1, facet_id)) for key in tab.keys(): if key != (0,)*dim: assert isinstance(tab[key], TraceError)
def test_basis_values(dim, degree): """Ensure that integrating simple monomials produces the expected results for each facet entity of the reference triangle and tetrahedron. This test performs the trace tabulation in two ways: (1) The entity is not specified, in which case the element uses numerical tolerance to determine the facet id; (2) The entity pair (dim, id) is provided, and the trace element tabulates accordingly using the new tabulate API. """ from FIAT import ufc_simplex, HDivTrace, make_quadrature ref_el = ufc_simplex(dim) quadrule = make_quadrature(ufc_simplex(dim - 1), degree + 1) fiat_element = HDivTrace(ref_el, degree) facet_element = fiat_element.dg_elements[dim - 1] nf = facet_element.space_dimension() for facet_id in range(dim + 1): # Tabulate without an entity pair given --- need to map to cell coordinates cell_transform = ref_el.get_entity_transform(dim - 1, facet_id) cell_points = np.array(list(map(cell_transform, quadrule.pts))) ctab = fiat_element.tabulate( 0, cell_points)[(0, ) * dim][nf * facet_id:nf * (facet_id + 1)] # Tabulate with entity pair provided entity = (ref_el.get_spatial_dimension() - 1, facet_id) etab = fiat_element.tabulate(0, quadrule.pts, entity)[(0, ) * dim][nf * facet_id:nf * (facet_id + 1)] for test_degree in range(degree + 1): coeffs = [ n(lambda x: x[0]**test_degree) for n in facet_element.dual.nodes ] cintegral = np.dot(coeffs, np.dot(ctab, quadrule.wts)) eintegral = np.dot(coeffs, np.dot(etab, quadrule.wts)) assert np.allclose(cintegral, eintegral, rtol=1e-14) reference = np.dot([x[0]**test_degree for x in quadrule.pts], quadrule.wts) assert np.allclose(cintegral, reference, rtol=1e-14) assert np.allclose(eintegral, reference, rtol=1e-14)
def test_projection(): T = ufc_simplex(2) T.vertices = np.asarray([(0.0, 0.0), (1.0, 0.0), (0.5, 2.1)]) AW = ArnoldWinther(T, 3) Q = make_quadrature(T, 4) qpts = np.asarray(Q.pts) qwts = np.asarray(Q.wts) nqp = len(Q.wts) nbf = 24 m = np.zeros((nbf, nbf)) b = np.zeros((24,)) rhs_vals = np.zeros((2, 2, nqp)) bfvals = AW.tabulate(0, qpts)[(0, 0)][:nbf, :, :, :] for i in range(nbf): for j in range(nbf): for k in range(nqp): m[i, j] += qwts[k] * frob(bfvals[i, :, :, k], bfvals[j, :, :, k]) assert np.linalg.cond(m) < 1.e12 comps = [(0, 0), (0, 1), (0, 0)] # loop over monomials up to degree 2 for deg in range(3): for jj in range(deg+1): ii = deg-jj for comp in comps: b[:] = 0.0 # set RHS (symmetrically) to be the monomial in # the proper component. rhs_vals[comp] = qpts[:, 0]**ii * qpts[:, 1]**jj rhs_vals[tuple(reversed(comp))] = rhs_vals[comp] for i in range(nbf): for k in range(nqp): b[i] += qwts[k] * frob(bfvals[i, :, :, k], rhs_vals[:, :, k]) x = np.linalg.solve(m, b) sol_at_qpts = np.zeros(rhs_vals.shape) for i in range(nbf): for k in range(nqp): sol_at_qpts[:, :, k] += x[i] * bfvals[i, :, :, k] diff = sol_at_qpts - rhs_vals err = 0.0 for k in range(nqp): err += qwts[k] * frob(diff[:, :, k], diff[:, :, k]) assert np.sqrt(err) < 1.e-12
def test_basis_values(dim, degree): """Ensure that integrating simple monomials produces the expected results for each facet entity of the reference triangle and tetrahedron. This test performs the trace tabulation in two ways: (1) The entity is not specified, in which case the element uses numerical tolerance to determine the facet id; (2) The entity pair (dim, id) is provided, and the trace element tabulates accordingly using the new tabulate API. """ from FIAT import ufc_simplex, HDivTrace, make_quadrature ref_el = ufc_simplex(dim) quadrule = make_quadrature(ufc_simplex(dim - 1), degree + 1) fiat_element = HDivTrace(ref_el, degree) facet_element = fiat_element.dg_elements[dim - 1] nf = facet_element.space_dimension() for facet_id in range(dim + 1): # Tabulate without an entity pair given --- need to map to cell coordinates cell_transform = ref_el.get_entity_transform(dim - 1, facet_id) cell_points = np.array(list(map(cell_transform, quadrule.pts))) ctab = fiat_element.tabulate(0, cell_points)[(0,) * dim][nf*facet_id:nf*(facet_id + 1)] # Tabulate with entity pair provided entity = (ref_el.get_spatial_dimension() - 1, facet_id) etab = fiat_element.tabulate(0, quadrule.pts, entity)[(0,) * dim][nf*facet_id:nf*(facet_id + 1)] for test_degree in range(degree + 1): coeffs = [n(lambda x: x[0]**test_degree) for n in facet_element.dual.nodes] cintegral = np.dot(coeffs, np.dot(ctab, quadrule.wts)) eintegral = np.dot(coeffs, np.dot(etab, quadrule.wts)) assert np.allclose(cintegral, eintegral, rtol=1e-14) reference = np.dot([x[0]**test_degree for x in quadrule.pts], quadrule.wts) assert np.allclose(cintegral, reference, rtol=1e-14) assert np.allclose(eintegral, reference, rtol=1e-14)
def test_dofs(): line = ufc_simplex(1) T = ufc_simplex(2) T.vertices = np.asarray([(0.0, 0.0), (1.0, 0.25), (-0.75, 1.1)]) MTW = MardalTaiWinther(T, 3) Qline = make_quadrature(line, 6) linebfs = expansions.LineExpansionSet(line) linevals = linebfs.tabulate(1, Qline.pts) for ed in range(3): n = T.compute_scaled_normal(ed) wts = np.asarray(Qline.wts) vals = MTW.tabulate(0, Qline.pts, (1, ed))[(0, 0)] nvals = np.dot(np.transpose(vals, (0, 2, 1)), n) normal_moments = np.zeros((9, 2)) for bf in range(9): for k in range(len(Qline.wts)): for m in (0, 1): normal_moments[bf, m] += wts[k] * nvals[bf, k] * linevals[m, k] right = np.zeros((9, 2)) right[3 * ed, 0] = 1.0 right[3 * ed + 2, 1] = 1.0 assert np.allclose(normal_moments, right) for ed in range(3): t = T.compute_edge_tangent(ed) wts = np.asarray(Qline.wts) vals = MTW.tabulate(0, Qline.pts, (1, ed))[(0, 0)] tvals = np.dot(np.transpose(vals, (0, 2, 1)), t) tangent_moments = np.zeros(9) for bf in range(9): for k in range(len(Qline.wts)): tangent_moments[bf] += wts[k] * tvals[bf, k] * linevals[0, k] right = np.zeros(9) right[3 * ed + 1] = 1.0 assert np.allclose(tangent_moments, right)
def create_data(family, dim, degree): '''Create the reference data. ''' # Get domain and element class domain = ufc_simplex(dim) ElementClass = supported_elements[family] # Create element element = ElementClass(domain, degree) # Create quadrature points quad_rule = make_quadrature(domain, num_points) points = quad_rule.get_points() # Tabulate at quadrature points table = element.tabulate(max_derivative, points) return table
def test_gll_basis_values(degree): """Ensure that integrating a simple monomial produces the expected results.""" from FIAT import ufc_simplex, GaussLobattoLegendre, make_quadrature s = ufc_simplex(1) q = make_quadrature(s, degree + 1) fe = GaussLobattoLegendre(s, degree) tab = fe.tabulate(0, q.pts)[(0, )] for test_degree in range(degree + 1): coefs = [n(lambda x: x[0]**test_degree) for n in fe.dual.nodes] integral = np.dot(coefs, np.dot(tab, q.wts)) reference = np.dot([x[0]**test_degree for x in q.pts], q.wts) assert np.allclose(integral, reference, rtol=1e-14)
def test_basis_values(dim, degree): """Ensure that integrating a simple monomial produces the expected results.""" from FIAT import ufc_simplex, DiscontinuousTaylor, make_quadrature s = ufc_simplex(dim) q = make_quadrature(s, degree + 1) fe = DiscontinuousTaylor(s, degree) tab = fe.tabulate(0, q.pts)[(0, ) * dim] for test_degree in range(degree + 1): coefs = [n(lambda x: x[0]**test_degree) for n in fe.dual.nodes] integral = np.float(np.dot(coefs, np.dot(tab, q.wts))) reference = np.dot([x[0]**test_degree for x in q.pts], q.wts) assert np.isclose(integral, reference, rtol=1e-14)
def test_basis_values(dim, degree): """Ensure that integrating a simple monomial produces the expected results.""" from FIAT import ufc_simplex, DiscontinuousTaylor, make_quadrature s = ufc_simplex(dim) q = make_quadrature(s, degree + 1) fe = DiscontinuousTaylor(s, degree) tab = fe.tabulate(0, q.pts)[(0,) * dim] for test_degree in range(degree + 1): coefs = [n(lambda x: x[0]**test_degree) for n in fe.dual.nodes] integral = np.float(np.dot(coefs, np.dot(tab, q.wts))) reference = np.dot([x[0]**test_degree for x in q.pts], q.wts) assert np.isclose(integral, reference, rtol=1e-14)
def test_sparsity(degree): from FIAT import ufc_simplex, FDMLagrange, make_quadrature cell = ufc_simplex(1) fe = FDMLagrange(cell, degree) rule = make_quadrature(cell, degree + 1) basis = fe.tabulate(1, rule.get_points()) Jhat = basis[(0, )] Dhat = basis[(1, )] what = rule.get_weights() Ahat = np.dot(np.multiply(Dhat, what), Dhat.T) Bhat = np.dot(np.multiply(Jhat, what), Jhat.T) nnz = lambda A: A.size - np.sum(np.isclose(A, 0.0E0, rtol=1E-14)) ndof = fe.space_dimension() assert nnz(Ahat) == 5 * ndof - 6 assert nnz(Bhat) == ndof + 2
def test_gl_basis_values(degree): """Ensure that integrating a simple monomial produces the expected results.""" from FIAT import ufc_simplex, GaussLegendre, make_quadrature s = ufc_simplex(1) q = make_quadrature(s, degree + 1) fe = GaussLegendre(s, degree) tab = fe.tabulate(0, q.pts)[(0,)] for test_degree in range(degree + 1): coefs = [n(lambda x: x[0]**test_degree) for n in fe.dual.nodes] integral = np.dot(coefs, np.dot(tab, q.wts)) reference = np.dot([x[0]**test_degree for x in q.pts], q.wts) assert np.allclose(integral, reference, rtol=1e-14)
def test_dofs(): line = ufc_simplex(1) T = ufc_simplex(2) T.vertices = np.random.rand(3, 2) AW = ArnoldWinther(T, 3) # check Kronecker property at vertices bases = [[[1, 0], [0, 0]], [[0, 1], [1, 0]], [[0, 0], [0, 1]]] vert_vals = AW.tabulate(0, T.vertices)[(0, 0)] for i in range(3): for j in range(3): assert np.allclose(vert_vals[3*i+j, :, :, i], bases[j]) for k in (1, 2): assert np.allclose(vert_vals[3*i+j, :, :, (i+k) % 3], np.zeros((2, 2))) # check edge moments Qline = make_quadrature(line, 6) linebfs = expansions.LineExpansionSet(line) linevals = linebfs.tabulate(1, Qline.pts) # n, n moments for ed in range(3): n = T.compute_scaled_normal(ed) wts = np.asarray(Qline.wts) nqpline = len(wts) vals = AW.tabulate(0, Qline.pts, (1, ed))[(0, 0)] nnvals = np.zeros((30, nqpline)) for i in range(30): for j in range(len(wts)): nnvals[i, j] = n @ vals[i, :, :, j] @ n nnmoments = np.zeros((30, 2)) for bf in range(30): for k in range(nqpline): for m in (0, 1): nnmoments[bf, m] += wts[k] * nnvals[bf, k] * linevals[m, k] for bf in range(30): if bf != AW.dual.entity_ids[1][ed][0] and bf != AW.dual.entity_ids[1][ed][2]: assert np.allclose(nnmoments[bf, :], np.zeros(2)) # n, t moments for ed in range(3): n = T.compute_scaled_normal(ed) t = T.compute_edge_tangent(ed) wts = np.asarray(Qline.wts) nqpline = len(wts) vals = AW.tabulate(0, Qline.pts, (1, ed))[(0, 0)] ntvals = np.zeros((30, nqpline)) for i in range(30): for j in range(len(wts)): ntvals[i, j] = n @ vals[i, :, :, j] @ t ntmoments = np.zeros((30, 2)) for bf in range(30): for k in range(nqpline): for m in (0, 1): ntmoments[bf, m] += wts[k] * ntvals[bf, k] * linevals[m, k] for bf in range(30): if bf != AW.dual.entity_ids[1][ed][1] and bf != AW.dual.entity_ids[1][ed][3]: assert np.allclose(ntmoments[bf, :], np.zeros(2)) # check internal dofs Q = make_quadrature(T, 6) qpvals = AW.tabulate(0, Q.pts)[(0, 0)] const_moms = qpvals @ Q.wts assert np.allclose(const_moms[:21], np.zeros((21, 2, 2))) assert np.allclose(const_moms[24:], np.zeros((6, 2, 2))) assert np.allclose(const_moms[21:24, 0, 0], np.asarray([1, 0, 0])) assert np.allclose(const_moms[21:24, 0, 1], np.asarray([0, 1, 0])) assert np.allclose(const_moms[21:24, 1, 0], np.asarray([0, 1, 0])) assert np.allclose(const_moms[21:24, 1, 1], np.asarray([0, 0, 1]))
def test_entity(element, quadrature): dim = element.get_reference_element().get_spatial_dimension() points = make_quadrature(ufc_simplex(dim - 1), 2).get_points() with pytest.raises(ValueError): element.tabulate(0, points, entity=(dim - 1, 1))
def cell(request): return ufc_simplex(request.param)
def test_dofs(): line = ufc_simplex(1) T = ufc_simplex(2) T.vertices = np.asarray([(0.0, 0.0), (1.0, 0.25), (-0.75, 1.1)]) AW = ArnoldWintherNC(T, 2) Qline = make_quadrature(line, 6) linebfs = expansions.LineExpansionSet(line) linevals = linebfs.tabulate(1, Qline.pts) # n, n moments for ed in range(3): n = T.compute_scaled_normal(ed) wts = np.asarray(Qline.wts) nqpline = len(wts) vals = AW.tabulate(0, Qline.pts, (1, ed))[(0, 0)] nnvals = np.zeros((18, nqpline)) for i in range(18): for j in range(len(wts)): nnvals[i, j] = n @ vals[i, :, :, j] @ n nnmoments = np.zeros((18, 2)) for bf in range(18): for k in range(nqpline): for m in (0, 1): nnmoments[bf, m] += wts[k] * nnvals[bf, k] * linevals[m, k] for bf in range(18): if bf != AW.dual.entity_ids[1][ed][0] and bf != AW.dual.entity_ids[ 1][ed][2]: assert np.allclose(nnmoments[bf, :], np.zeros(2)) # n, t moments for ed in range(3): n = T.compute_scaled_normal(ed) t = T.compute_edge_tangent(ed) wts = np.asarray(Qline.wts) nqpline = len(wts) vals = AW.tabulate(0, Qline.pts, (1, ed))[(0, 0)] ntvals = np.zeros((18, nqpline)) for i in range(18): for j in range(len(wts)): ntvals[i, j] = n @ vals[i, :, :, j] @ t ntmoments = np.zeros((18, 2)) for bf in range(18): for k in range(nqpline): for m in (0, 1): ntmoments[bf, m] += wts[k] * ntvals[bf, k] * linevals[m, k] for bf in range(18): if bf != AW.dual.entity_ids[1][ed][1] and bf != AW.dual.entity_ids[ 1][ed][3]: assert np.allclose(ntmoments[bf, :], np.zeros(2), atol=1.e-7) # check internal dofs Q = make_quadrature(T, 6) qpvals = AW.tabulate(0, Q.pts)[(0, 0)] const_moms = qpvals @ Q.wts assert np.allclose(const_moms[:12], np.zeros((12, 2, 2))) assert np.allclose(const_moms[15:], np.zeros((3, 2, 2))) assert np.allclose(const_moms[12:15, 0, 0], np.asarray([1, 0, 0])) assert np.allclose(const_moms[12:15, 0, 1], np.asarray([0, 1, 0])) assert np.allclose(const_moms[12:15, 1, 0], np.asarray([0, 1, 0])) assert np.allclose(const_moms[12:15, 1, 1], np.asarray([0, 0, 1]))