xref: /libCEED/python/tests/test-3-basis.py (revision c3a5a6094aa370d9b1d225615082a3e1f73f831f)
10ef72598Sjeremylt# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
20ef72598Sjeremylt# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
30ef72598Sjeremylt# reserved. See files LICENSE and NOTICE for details.
40ef72598Sjeremylt#
50ef72598Sjeremylt# This file is part of CEED, a collection of benchmarks, miniapps, software
60ef72598Sjeremylt# libraries and APIs for efficient high-order finite element and spectral
70ef72598Sjeremylt# element discretizations for exascale applications. For more information and
80ef72598Sjeremylt# source code availability see http://github.com/ceed.
90ef72598Sjeremylt#
100ef72598Sjeremylt# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
110ef72598Sjeremylt# a collaborative effort of two U.S. Department of Energy organizations (Office
120ef72598Sjeremylt# of Science and the National Nuclear Security Administration) responsible for
130ef72598Sjeremylt# the planning and preparation of a capable exascale ecosystem, including
140ef72598Sjeremylt# software, applications, hardware, advanced system engineering and early
150ef72598Sjeremylt# testbed platforms, in support of the nation's exascale computing imperative.
160ef72598Sjeremylt
170ef72598Sjeremylt# @file
180ef72598Sjeremylt# Test Ceed Basis functionality
190ef72598Sjeremylt
200ef72598Sjeremyltimport os
210ef72598Sjeremyltimport math
220ef72598Sjeremyltimport libceed
230ef72598Sjeremyltimport numpy as np
240ef72598Sjeremyltimport buildmats as bm
250ef72598Sjeremyltimport check
260ef72598Sjeremylt
270ef72598SjeremyltTOL = np.finfo(float).eps * 256
280ef72598Sjeremylt
290ef72598Sjeremylt# -------------------------------------------------------------------------------
300ef72598Sjeremylt# Utilities
310ef72598Sjeremylt# -------------------------------------------------------------------------------
320ef72598Sjeremylt
330ef72598Sjeremylt
340ef72598Sjeremyltdef eval(dim, x):
350ef72598Sjeremylt    result, center = 1, 0.1
360ef72598Sjeremylt    for d in range(dim):
370ef72598Sjeremylt        result *= math.tanh(x[d] - center)
380ef72598Sjeremylt        center += 0.1
390ef72598Sjeremylt    return result
400ef72598Sjeremylt
410ef72598Sjeremylt
420ef72598Sjeremyltdef feval(x1, x2):
430ef72598Sjeremylt    return x1 * x1 + x2 * x2 + x1 * x2 + 1
440ef72598Sjeremylt
450ef72598Sjeremylt
460ef72598Sjeremyltdef dfeval(x1, x2):
470ef72598Sjeremylt    return 2 * x1 + x2
480ef72598Sjeremylt
490ef72598Sjeremylt# -------------------------------------------------------------------------------
500ef72598Sjeremylt# Test creation and distruction of a H1Lagrange basis
510ef72598Sjeremylt# -------------------------------------------------------------------------------
520ef72598Sjeremylt
530ef72598Sjeremylt
540ef72598Sjeremyltdef test_300(ceed_resource, capsys):
550ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
560ef72598Sjeremylt
570ef72598Sjeremylt    b = ceed.BasisTensorH1Lagrange(1, 1, 4, 4, libceed.GAUSS_LOBATTO)
580ef72598Sjeremylt    print(b)
590ef72598Sjeremylt    del b
600ef72598Sjeremylt
610ef72598Sjeremylt    b = ceed.BasisTensorH1Lagrange(1, 1, 4, 4, libceed.GAUSS)
620ef72598Sjeremylt    print(b)
630ef72598Sjeremylt    del b
640ef72598Sjeremylt
650ef72598Sjeremylt    stdout, stderr, ref_stdout = check.output(capsys)
660ef72598Sjeremylt    assert not stderr
670ef72598Sjeremylt    assert stdout == ref_stdout
680ef72598Sjeremylt
690ef72598Sjeremylt# -------------------------------------------------------------------------------
700ef72598Sjeremylt# Test QR factorization
710ef72598Sjeremylt# -------------------------------------------------------------------------------
720ef72598Sjeremylt
730ef72598Sjeremylt
74*c3a5a609SJeremy L Thompsondef test_301(ceed_resource):
750ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
760ef72598Sjeremylt
77*c3a5a609SJeremy L Thompson    m = 4
78*c3a5a609SJeremy L Thompson    n = 3
79*c3a5a609SJeremy L Thompson    a = np.array([1, -1, 4, 1, 4, -2, 1, 4, 2, 1, -1, 0], dtype="float64")
800ef72598Sjeremylt    qr = np.array([1, -1, 4, 1, 4, -2, 1, 4, 2, 1, -1, 0], dtype="float64")
810ef72598Sjeremylt    tau = np.empty(3, dtype="float64")
820ef72598Sjeremylt
83*c3a5a609SJeremy L Thompson    qr, tau = ceed.qr_factorization(qr, tau, m, n)
84*c3a5a609SJeremy L Thompson    np_qr, np_tau = np.linalg.qr(a.reshape(m, n), mode="raw")
850ef72598Sjeremylt
86*c3a5a609SJeremy L Thompson    for i in range(n):
87*c3a5a609SJeremy L Thompson        assert tau[i] == np_tau[i]
880ef72598Sjeremylt
89*c3a5a609SJeremy L Thompson    qr = qr.reshape(m, n)
90*c3a5a609SJeremy L Thompson    for i in range(m):
91*c3a5a609SJeremy L Thompson        for j in range(n):
92*c3a5a609SJeremy L Thompson            assert round(qr[i, j] - np_qr[j, i], 10) == 0
930ef72598Sjeremylt
940ef72598Sjeremylt# -------------------------------------------------------------------------------
950ef72598Sjeremylt# Test Symmetric Schur Decomposition
960ef72598Sjeremylt# -------------------------------------------------------------------------------
970ef72598Sjeremylt
980ef72598Sjeremylt
99*c3a5a609SJeremy L Thompsondef test_304(ceed_resource):
1000ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1010ef72598Sjeremylt
102673160d7Sjeremylt    A = np.array([0.2, 0.0745355993, -0.0745355993, 0.0333333333,
103673160d7Sjeremylt                  0.0745355993, 1., 0.1666666667, -0.0745355993,
104673160d7Sjeremylt                  -0.0745355993, 0.1666666667, 1., 0.0745355993,
105673160d7Sjeremylt                  0.0333333333, -0.0745355993, 0.0745355993, 0.2], dtype="float64")
1060ef72598Sjeremylt
107673160d7Sjeremylt    Q = A.copy()
1080ef72598Sjeremylt
109673160d7Sjeremylt    lam = ceed.symmetric_schur_decomposition(Q, 4)
110673160d7Sjeremylt    Q = Q.reshape(4, 4)
111673160d7Sjeremylt    lam = np.diag(lam)
1120ef72598Sjeremylt
113673160d7Sjeremylt    Q_lambda_Qt = np.matmul(np.matmul(Q, lam), Q.T)
114673160d7Sjeremylt    assert np.max(Q_lambda_Qt - A.reshape(4, 4)) < 1E-14
1150ef72598Sjeremylt
1160ef72598Sjeremylt# -------------------------------------------------------------------------------
1170ef72598Sjeremylt# Test Simultaneous Diagonalization
1180ef72598Sjeremylt# -------------------------------------------------------------------------------
1190ef72598Sjeremylt
1200ef72598Sjeremylt
121*c3a5a609SJeremy L Thompsondef test_305(ceed_resource):
1220ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1230ef72598Sjeremylt
124673160d7Sjeremylt    M = np.array([0.2, 0.0745355993, -0.0745355993, 0.0333333333,
125673160d7Sjeremylt                  0.0745355993, 1., 0.1666666667, -0.0745355993,
126673160d7Sjeremylt                  -0.0745355993, 0.1666666667, 1., 0.0745355993,
127673160d7Sjeremylt                  0.0333333333, -0.0745355993, 0.0745355993, 0.2], dtype="float64")
128673160d7Sjeremylt    K = np.array([3.0333333333, -3.4148928136, 0.4982261470, -0.1166666667,
129673160d7Sjeremylt                  -3.4148928136, 5.8333333333, -2.9166666667, 0.4982261470,
130673160d7Sjeremylt                  0.4982261470, -2.9166666667, 5.8333333333, -3.4148928136,
131673160d7Sjeremylt                  -0.1166666667, 0.4982261470, -3.4148928136, 3.0333333333], dtype="float64")
1320ef72598Sjeremylt
133673160d7Sjeremylt    X, lam = ceed.simultaneous_diagonalization(K, M, 4)
134673160d7Sjeremylt    X = X.reshape(4, 4)
135673160d7Sjeremylt    np.diag(lam)
1360ef72598Sjeremylt
137673160d7Sjeremylt    M = M.reshape(4, 4)
138673160d7Sjeremylt    K = K.reshape(4, 4)
1390ef72598Sjeremylt
140673160d7Sjeremylt    Xt_M_X = np.matmul(X.T, np.matmul(M, X))
141673160d7Sjeremylt    assert np.max(Xt_M_X - np.identity(4)) < 1E-14
1420ef72598Sjeremylt
143673160d7Sjeremylt    Xt_K_X = np.matmul(X.T, np.matmul(K, X))
144673160d7Sjeremylt    assert np.max(Xt_K_X - lam) < 1E-14
1450ef72598Sjeremylt
1460ef72598Sjeremylt# -------------------------------------------------------------------------------
1470ef72598Sjeremylt# Test GetNumNodes and GetNumQuadraturePoints for basis
1480ef72598Sjeremylt# -------------------------------------------------------------------------------
1490ef72598Sjeremylt
1500ef72598Sjeremylt
1510ef72598Sjeremyltdef test_306(ceed_resource):
1520ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1530ef72598Sjeremylt
1540ef72598Sjeremylt    b = ceed.BasisTensorH1Lagrange(3, 1, 4, 5, libceed.GAUSS_LOBATTO)
1550ef72598Sjeremylt
1560ef72598Sjeremylt    p = b.get_num_nodes()
1570ef72598Sjeremylt    q = b.get_num_quadrature_points()
1580ef72598Sjeremylt
1590ef72598Sjeremylt    assert p == 64
1600ef72598Sjeremylt    assert q == 125
1610ef72598Sjeremylt
1620ef72598Sjeremylt# -------------------------------------------------------------------------------
1630ef72598Sjeremylt# Test interpolation in multiple dimensions
1640ef72598Sjeremylt# -------------------------------------------------------------------------------
1650ef72598Sjeremylt
1660ef72598Sjeremylt
1670ef72598Sjeremyltdef test_313(ceed_resource):
1680ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1690ef72598Sjeremylt
1700ef72598Sjeremylt    for dim in range(1, 4):
1710ef72598Sjeremylt        Q = 10
1720ef72598Sjeremylt        Qdim = Q**dim
1730ef72598Sjeremylt        Xdim = 2**dim
1740ef72598Sjeremylt        x = np.empty(Xdim * dim, dtype="float64")
1750ef72598Sjeremylt        uq = np.empty(Qdim, dtype="float64")
1760ef72598Sjeremylt
1770ef72598Sjeremylt        for d in range(dim):
1780ef72598Sjeremylt            for i in range(Xdim):
1790ef72598Sjeremylt                x[d * Xdim + i] = 1 if (i %
1800ef72598Sjeremylt                                        (2**(dim - d))) // (2**(dim - d - 1)) else -1
1810ef72598Sjeremylt
1820ef72598Sjeremylt        X = ceed.Vector(Xdim * dim)
1830ef72598Sjeremylt        X.set_array(x, cmode=libceed.USE_POINTER)
1840ef72598Sjeremylt        Xq = ceed.Vector(Qdim * dim)
1850ef72598Sjeremylt        Xq.set_value(0)
1860ef72598Sjeremylt        U = ceed.Vector(Qdim)
1870ef72598Sjeremylt        U.set_value(0)
1880ef72598Sjeremylt        Uq = ceed.Vector(Qdim)
1890ef72598Sjeremylt
1900ef72598Sjeremylt        bxl = ceed.BasisTensorH1Lagrange(dim, dim, 2, Q, libceed.GAUSS_LOBATTO)
1910ef72598Sjeremylt        bul = ceed.BasisTensorH1Lagrange(dim, 1, Q, Q, libceed.GAUSS_LOBATTO)
1920ef72598Sjeremylt
1930ef72598Sjeremylt        bxl.apply(1, libceed.EVAL_INTERP, X, Xq)
1940ef72598Sjeremylt
1950ef72598Sjeremylt        with Xq.array_read() as xq:
1960ef72598Sjeremylt            for i in range(Qdim):
1970ef72598Sjeremylt                xx = np.empty(dim, dtype="float64")
1980ef72598Sjeremylt                for d in range(dim):
1990ef72598Sjeremylt                    xx[d] = xq[d * Qdim + i]
2000ef72598Sjeremylt                uq[i] = eval(dim, xx)
2010ef72598Sjeremylt
2020ef72598Sjeremylt        Uq.set_array(uq, cmode=libceed.USE_POINTER)
2030ef72598Sjeremylt
2040ef72598Sjeremylt        # This operation is the identity because the quadrature is collocated
2050ef72598Sjeremylt        bul.T.apply(1, libceed.EVAL_INTERP, Uq, U)
2060ef72598Sjeremylt
2070ef72598Sjeremylt        bxg = ceed.BasisTensorH1Lagrange(dim, dim, 2, Q, libceed.GAUSS)
2080ef72598Sjeremylt        bug = ceed.BasisTensorH1Lagrange(dim, 1, Q, Q, libceed.GAUSS)
2090ef72598Sjeremylt
2100ef72598Sjeremylt        bxg.apply(1, libceed.EVAL_INTERP, X, Xq)
2110ef72598Sjeremylt        bug.apply(1, libceed.EVAL_INTERP, U, Uq)
2120ef72598Sjeremylt
2130ef72598Sjeremylt        with Xq.array_read() as xq, Uq.array_read() as u:
2140ef72598Sjeremylt            for i in range(Qdim):
2150ef72598Sjeremylt                xx = np.empty(dim, dtype="float64")
2160ef72598Sjeremylt                for d in range(dim):
2170ef72598Sjeremylt                    xx[d] = xq[d * Qdim + i]
2180ef72598Sjeremylt                fx = eval(dim, xx)
2190ef72598Sjeremylt                assert math.fabs(u[i] - fx) < 1E-4
2200ef72598Sjeremylt
2210ef72598Sjeremylt# -------------------------------------------------------------------------------
2220ef72598Sjeremylt# Test grad in multiple dimensions
2230ef72598Sjeremylt# -------------------------------------------------------------------------------
2240ef72598Sjeremylt
2250ef72598Sjeremylt
2260ef72598Sjeremyltdef test_314(ceed_resource):
2270ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2280ef72598Sjeremylt
2290ef72598Sjeremylt    for dim in range(1, 4):
2300ef72598Sjeremylt        P, Q = 8, 10
2310ef72598Sjeremylt        Pdim = P**dim
2320ef72598Sjeremylt        Qdim = Q**dim
2330ef72598Sjeremylt        Xdim = 2**dim
2340ef72598Sjeremylt        sum1 = sum2 = 0
2350ef72598Sjeremylt        x = np.empty(Xdim * dim, dtype="float64")
2360ef72598Sjeremylt        u = np.empty(Pdim, dtype="float64")
2370ef72598Sjeremylt
2380ef72598Sjeremylt        for d in range(dim):
2390ef72598Sjeremylt            for i in range(Xdim):
2400ef72598Sjeremylt                x[d * Xdim + i] = 1 if (i %
2410ef72598Sjeremylt                                        (2**(dim - d))) // (2**(dim - d - 1)) else -1
2420ef72598Sjeremylt
2430ef72598Sjeremylt        X = ceed.Vector(Xdim * dim)
2440ef72598Sjeremylt        X.set_array(x, cmode=libceed.USE_POINTER)
2450ef72598Sjeremylt        Xq = ceed.Vector(Pdim * dim)
2460ef72598Sjeremylt        Xq.set_value(0)
2470ef72598Sjeremylt        U = ceed.Vector(Pdim)
2480ef72598Sjeremylt        Uq = ceed.Vector(Qdim * dim)
2490ef72598Sjeremylt        Uq.set_value(0)
2500ef72598Sjeremylt        Ones = ceed.Vector(Qdim * dim)
2510ef72598Sjeremylt        Ones.set_value(1)
2520ef72598Sjeremylt        Gtposeones = ceed.Vector(Pdim)
2530ef72598Sjeremylt        Gtposeones.set_value(0)
2540ef72598Sjeremylt
2550ef72598Sjeremylt        # Get function values at quadrature points
2560ef72598Sjeremylt        bxl = ceed.BasisTensorH1Lagrange(dim, dim, 2, P, libceed.GAUSS_LOBATTO)
2570ef72598Sjeremylt        bxl.apply(1, libceed.EVAL_INTERP, X, Xq)
2580ef72598Sjeremylt
2590ef72598Sjeremylt        with Xq.array_read() as xq:
2600ef72598Sjeremylt            for i in range(Pdim):
2610ef72598Sjeremylt                xx = np.empty(dim, dtype="float64")
2620ef72598Sjeremylt                for d in range(dim):
2630ef72598Sjeremylt                    xx[d] = xq[d * Pdim + i]
2640ef72598Sjeremylt                u[i] = eval(dim, xx)
2650ef72598Sjeremylt
2660ef72598Sjeremylt        U.set_array(u, cmode=libceed.USE_POINTER)
2670ef72598Sjeremylt
2680ef72598Sjeremylt        # Calculate G u at quadrature points, G' * 1 at dofs
2690ef72598Sjeremylt        bug = ceed.BasisTensorH1Lagrange(dim, 1, P, Q, libceed.GAUSS)
2700ef72598Sjeremylt        bug.apply(1, libceed.EVAL_GRAD, U, Uq)
2710ef72598Sjeremylt        bug.T.apply(1, libceed.EVAL_GRAD, Ones, Gtposeones)
2720ef72598Sjeremylt
2730ef72598Sjeremylt        # Check if 1' * G * u = u' * (G' * 1)
2740ef72598Sjeremylt        with Gtposeones.array_read() as gtposeones, Uq.array_read() as uq:
2750ef72598Sjeremylt            for i in range(Pdim):
2760ef72598Sjeremylt                sum1 += gtposeones[i] * u[i]
2770ef72598Sjeremylt            for i in range(dim * Qdim):
2780ef72598Sjeremylt                sum2 += uq[i]
2790ef72598Sjeremylt
2800ef72598Sjeremylt        assert math.fabs(sum1 - sum2) < 1E-10
2810ef72598Sjeremylt
2820ef72598Sjeremylt# -------------------------------------------------------------------------------
2830ef72598Sjeremylt# Test creation and destruction of a 2D Simplex non-tensor H1 basis
2840ef72598Sjeremylt# -------------------------------------------------------------------------------
2850ef72598Sjeremylt
2860ef72598Sjeremylt
2870ef72598Sjeremyltdef test_320(ceed_resource):
2880ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2890ef72598Sjeremylt
2900ef72598Sjeremylt    P, Q, dim = 6, 4, 2
2910ef72598Sjeremylt
2920ef72598Sjeremylt    in_array = np.empty(P, dtype="float64")
2930ef72598Sjeremylt    qref = np.empty(dim * Q, dtype="float64")
2940ef72598Sjeremylt    qweight = np.empty(Q, dtype="float64")
2950ef72598Sjeremylt
2960ef72598Sjeremylt    interp, grad = bm.buildmats(qref, qweight)
2970ef72598Sjeremylt
2980ef72598Sjeremylt    b = ceed.BasisH1(libceed.TRIANGLE, 1, P, Q, interp, grad, qref, qweight)
2990ef72598Sjeremylt
3000ef72598Sjeremylt    print(b)
3010ef72598Sjeremylt    del b
3020ef72598Sjeremylt
3030ef72598Sjeremylt# -------------------------------------------------------------------------------
3040ef72598Sjeremylt# Test integration with a 2D Simplex non-tensor H1 basis
3050ef72598Sjeremylt# -------------------------------------------------------------------------------
3060ef72598Sjeremylt
3070ef72598Sjeremylt
3080ef72598Sjeremyltdef test_322(ceed_resource):
3090ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
3100ef72598Sjeremylt
3110ef72598Sjeremylt    P, Q, dim = 6, 4, 2
3120ef72598Sjeremylt
3130ef72598Sjeremylt    xr = np.array([0., 0.5, 1., 0., 0.5, 0., 0., 0.,
3140ef72598Sjeremylt                   0., 0.5, 0.5, 1.], dtype="float64")
3150ef72598Sjeremylt    in_array = np.empty(P, dtype="float64")
3160ef72598Sjeremylt    qref = np.empty(dim * Q, dtype="float64")
3170ef72598Sjeremylt    qweight = np.empty(Q, dtype="float64")
3180ef72598Sjeremylt
3190ef72598Sjeremylt    interp, grad = bm.buildmats(qref, qweight)
3200ef72598Sjeremylt
3210ef72598Sjeremylt    b = ceed.BasisH1(libceed.TRIANGLE, 1, P, Q, interp, grad, qref, qweight)
3220ef72598Sjeremylt
3230ef72598Sjeremylt    # Interpolate function to quadrature points
3240ef72598Sjeremylt    for i in range(P):
3250ef72598Sjeremylt        in_array[i] = feval(xr[0 * P + i], xr[1 * P + i])
3260ef72598Sjeremylt
3270ef72598Sjeremylt    in_vec = ceed.Vector(P)
3280ef72598Sjeremylt    in_vec.set_array(in_array, cmode=libceed.USE_POINTER)
3290ef72598Sjeremylt    out_vec = ceed.Vector(Q)
3300ef72598Sjeremylt    out_vec.set_value(0)
3310ef72598Sjeremylt    weights_vec = ceed.Vector(Q)
3320ef72598Sjeremylt    weights_vec.set_value(0)
3330ef72598Sjeremylt
3340ef72598Sjeremylt    b.apply(1, libceed.EVAL_INTERP, in_vec, out_vec)
3350ef72598Sjeremylt    b.apply(1, libceed.EVAL_WEIGHT, libceed.VECTOR_NONE, weights_vec)
3360ef72598Sjeremylt
3370ef72598Sjeremylt    # Check values at quadrature points
3380ef72598Sjeremylt    with out_vec.array_read() as out_array, weights_vec.array_read() as weights_array:
3390ef72598Sjeremylt        sum = 0
3400ef72598Sjeremylt        for i in range(Q):
3410ef72598Sjeremylt            sum += out_array[i] * weights_array[i]
3420ef72598Sjeremylt        assert math.fabs(sum - 17. / 24.) < 1E-10
3430ef72598Sjeremylt
3440ef72598Sjeremylt# -------------------------------------------------------------------------------
3450ef72598Sjeremylt# Test grad with a 2D Simplex non-tensor H1 basis
3460ef72598Sjeremylt# -------------------------------------------------------------------------------
3470ef72598Sjeremylt
3480ef72598Sjeremylt
3490ef72598Sjeremyltdef test_323(ceed_resource):
3500ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
3510ef72598Sjeremylt
3520ef72598Sjeremylt    P, Q, dim = 6, 4, 2
3530ef72598Sjeremylt
3540ef72598Sjeremylt    xq = np.array([0.2, 0.6, 1. / 3., 0.2, 0.2, 0.2,
3550ef72598Sjeremylt                   1. / 3., 0.6], dtype="float64")
3560ef72598Sjeremylt    xr = np.array([0., 0.5, 1., 0., 0.5, 0., 0., 0.,
3570ef72598Sjeremylt                   0., 0.5, 0.5, 1.], dtype="float64")
3580ef72598Sjeremylt    in_array = np.empty(P, dtype="float64")
3590ef72598Sjeremylt    qref = np.empty(dim * Q, dtype="float64")
3600ef72598Sjeremylt    qweight = np.empty(Q, dtype="float64")
3610ef72598Sjeremylt
3620ef72598Sjeremylt    interp, grad = bm.buildmats(qref, qweight)
3630ef72598Sjeremylt
3640ef72598Sjeremylt    b = ceed.BasisH1(libceed.TRIANGLE, 1, P, Q, interp, grad, qref, qweight)
3650ef72598Sjeremylt
3660ef72598Sjeremylt    # Interpolate function to quadrature points
3670ef72598Sjeremylt    for i in range(P):
3680ef72598Sjeremylt        in_array[i] = feval(xr[0 * P + i], xr[1 * P + i])
3690ef72598Sjeremylt
3700ef72598Sjeremylt    in_vec = ceed.Vector(P)
3710ef72598Sjeremylt    in_vec.set_array(in_array, cmode=libceed.USE_POINTER)
3720ef72598Sjeremylt    out_vec = ceed.Vector(Q * dim)
3730ef72598Sjeremylt    out_vec.set_value(0)
3740ef72598Sjeremylt
3750ef72598Sjeremylt    b.apply(1, libceed.EVAL_GRAD, in_vec, out_vec)
3760ef72598Sjeremylt
3770ef72598Sjeremylt    # Check values at quadrature points
3780ef72598Sjeremylt    with out_vec.array_read() as out_array:
3790ef72598Sjeremylt        for i in range(Q):
3800ef72598Sjeremylt            value = dfeval(xq[0 * Q + i], xq[1 * Q + i])
3810ef72598Sjeremylt            assert math.fabs(out_array[0 * Q + i] - value) < 1E-10
3820ef72598Sjeremylt
3830ef72598Sjeremylt            value = dfeval(xq[1 * Q + i], xq[0 * Q + i])
3840ef72598Sjeremylt            assert math.fabs(out_array[1 * Q + i] - value) < 1E-10
3850ef72598Sjeremylt
3860ef72598Sjeremylt# -------------------------------------------------------------------------------
387