xref: /libCEED/python/tests/test-3-basis.py (revision 80a9ef0545a39c00cdcaab1ca26f8053604f3120)
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
27*80a9ef05SNatalie BeamsTOL = libceed.EPSILON * 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
65*80a9ef05SNatalie Beams    # Only run this test in double precision
66*80a9ef05SNatalie Beams    if libceed.lib.CEED_SCALAR_TYPE == libceed.SCALAR_FP64:
670ef72598Sjeremylt        stdout, stderr, ref_stdout = check.output(capsys)
680ef72598Sjeremylt        assert not stderr
690ef72598Sjeremylt        assert stdout == ref_stdout
700ef72598Sjeremylt
710ef72598Sjeremylt# -------------------------------------------------------------------------------
720ef72598Sjeremylt# Test QR factorization
730ef72598Sjeremylt# -------------------------------------------------------------------------------
740ef72598Sjeremylt
750ef72598Sjeremylt
76c3a5a609SJeremy L Thompsondef test_301(ceed_resource):
770ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
780ef72598Sjeremylt
79c3a5a609SJeremy L Thompson    m = 4
80c3a5a609SJeremy L Thompson    n = 3
81*80a9ef05SNatalie Beams    a = np.array([1, -1, 4, 1, 4, -2, 1, 4, 2, 1, -1, 0],
82*80a9ef05SNatalie Beams                 dtype=ceed.scalar_type())
83*80a9ef05SNatalie Beams    qr = np.array([1, -1, 4, 1, 4, -2, 1, 4, 2, 1, -1, 0],
84*80a9ef05SNatalie Beams                  dtype=ceed.scalar_type())
85*80a9ef05SNatalie Beams    tau = np.empty(3, dtype=ceed.scalar_type())
860ef72598Sjeremylt
87c3a5a609SJeremy L Thompson    qr, tau = ceed.qr_factorization(qr, tau, m, n)
88c3a5a609SJeremy L Thompson    np_qr, np_tau = np.linalg.qr(a.reshape(m, n), mode="raw")
890ef72598Sjeremylt
90c3a5a609SJeremy L Thompson    for i in range(n):
91*80a9ef05SNatalie Beams        assert abs(tau[i] - np_tau[i]) < TOL
920ef72598Sjeremylt
93c3a5a609SJeremy L Thompson    qr = qr.reshape(m, n)
94c3a5a609SJeremy L Thompson    for i in range(m):
95c3a5a609SJeremy L Thompson        for j in range(n):
96*80a9ef05SNatalie Beams            assert abs(qr[i, j] - np_qr[j, i]) < TOL
970ef72598Sjeremylt
980ef72598Sjeremylt# -------------------------------------------------------------------------------
990ef72598Sjeremylt# Test Symmetric Schur Decomposition
1000ef72598Sjeremylt# -------------------------------------------------------------------------------
1010ef72598Sjeremylt
1020ef72598Sjeremylt
103c3a5a609SJeremy L Thompsondef test_304(ceed_resource):
1040ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1050ef72598Sjeremylt
106673160d7Sjeremylt    A = np.array([0.2, 0.0745355993, -0.0745355993, 0.0333333333,
107673160d7Sjeremylt                  0.0745355993, 1., 0.1666666667, -0.0745355993,
108673160d7Sjeremylt                  -0.0745355993, 0.1666666667, 1., 0.0745355993,
109*80a9ef05SNatalie Beams                  0.0333333333, -0.0745355993, 0.0745355993, 0.2],
110*80a9ef05SNatalie Beams                 dtype=ceed.scalar_type())
1110ef72598Sjeremylt
112673160d7Sjeremylt    Q = A.copy()
1130ef72598Sjeremylt
114673160d7Sjeremylt    lam = ceed.symmetric_schur_decomposition(Q, 4)
115673160d7Sjeremylt    Q = Q.reshape(4, 4)
116673160d7Sjeremylt    lam = np.diag(lam)
1170ef72598Sjeremylt
118673160d7Sjeremylt    Q_lambda_Qt = np.matmul(np.matmul(Q, lam), Q.T)
119*80a9ef05SNatalie Beams    assert np.max(Q_lambda_Qt - A.reshape(4, 4)) < TOL
1200ef72598Sjeremylt
1210ef72598Sjeremylt# -------------------------------------------------------------------------------
1220ef72598Sjeremylt# Test Simultaneous Diagonalization
1230ef72598Sjeremylt# -------------------------------------------------------------------------------
1240ef72598Sjeremylt
1250ef72598Sjeremylt
126c3a5a609SJeremy L Thompsondef test_305(ceed_resource):
1270ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1280ef72598Sjeremylt
129673160d7Sjeremylt    M = np.array([0.2, 0.0745355993, -0.0745355993, 0.0333333333,
130673160d7Sjeremylt                  0.0745355993, 1., 0.1666666667, -0.0745355993,
131673160d7Sjeremylt                  -0.0745355993, 0.1666666667, 1., 0.0745355993,
132*80a9ef05SNatalie Beams                  0.0333333333, -0.0745355993, 0.0745355993, 0.2],
133*80a9ef05SNatalie Beams                 dtype=ceed.scalar_type())
134673160d7Sjeremylt    K = np.array([3.0333333333, -3.4148928136, 0.4982261470, -0.1166666667,
135673160d7Sjeremylt                  -3.4148928136, 5.8333333333, -2.9166666667, 0.4982261470,
136673160d7Sjeremylt                  0.4982261470, -2.9166666667, 5.8333333333, -3.4148928136,
137*80a9ef05SNatalie Beams                  -0.1166666667, 0.4982261470, -3.4148928136, 3.0333333333],
138*80a9ef05SNatalie Beams                 dtype=ceed.scalar_type())
1390ef72598Sjeremylt
140673160d7Sjeremylt    X, lam = ceed.simultaneous_diagonalization(K, M, 4)
141673160d7Sjeremylt    X = X.reshape(4, 4)
142673160d7Sjeremylt    np.diag(lam)
1430ef72598Sjeremylt
144673160d7Sjeremylt    M = M.reshape(4, 4)
145673160d7Sjeremylt    K = K.reshape(4, 4)
1460ef72598Sjeremylt
147673160d7Sjeremylt    Xt_M_X = np.matmul(X.T, np.matmul(M, X))
148*80a9ef05SNatalie Beams    assert np.max(Xt_M_X - np.identity(4)) < TOL
1490ef72598Sjeremylt
150673160d7Sjeremylt    Xt_K_X = np.matmul(X.T, np.matmul(K, X))
151*80a9ef05SNatalie Beams    assert np.max(Xt_K_X - lam) < TOL
1520ef72598Sjeremylt
1530ef72598Sjeremylt# -------------------------------------------------------------------------------
1540ef72598Sjeremylt# Test GetNumNodes and GetNumQuadraturePoints for basis
1550ef72598Sjeremylt# -------------------------------------------------------------------------------
1560ef72598Sjeremylt
1570ef72598Sjeremylt
1580ef72598Sjeremyltdef test_306(ceed_resource):
1590ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1600ef72598Sjeremylt
1610ef72598Sjeremylt    b = ceed.BasisTensorH1Lagrange(3, 1, 4, 5, libceed.GAUSS_LOBATTO)
1620ef72598Sjeremylt
1630ef72598Sjeremylt    p = b.get_num_nodes()
1640ef72598Sjeremylt    q = b.get_num_quadrature_points()
1650ef72598Sjeremylt
1660ef72598Sjeremylt    assert p == 64
1670ef72598Sjeremylt    assert q == 125
1680ef72598Sjeremylt
1690ef72598Sjeremylt# -------------------------------------------------------------------------------
1700ef72598Sjeremylt# Test interpolation in multiple dimensions
1710ef72598Sjeremylt# -------------------------------------------------------------------------------
1720ef72598Sjeremylt
1730ef72598Sjeremylt
1740ef72598Sjeremyltdef test_313(ceed_resource):
1750ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1760ef72598Sjeremylt
1770ef72598Sjeremylt    for dim in range(1, 4):
1780ef72598Sjeremylt        Q = 10
1790ef72598Sjeremylt        Qdim = Q**dim
1800ef72598Sjeremylt        Xdim = 2**dim
181*80a9ef05SNatalie Beams        x = np.empty(Xdim * dim, dtype=ceed.scalar_type())
182*80a9ef05SNatalie Beams        uq = np.empty(Qdim, dtype=ceed.scalar_type())
1830ef72598Sjeremylt
1840ef72598Sjeremylt        for d in range(dim):
1850ef72598Sjeremylt            for i in range(Xdim):
1860ef72598Sjeremylt                x[d * Xdim + i] = 1 if (i %
1870ef72598Sjeremylt                                        (2**(dim - d))) // (2**(dim - d - 1)) else -1
1880ef72598Sjeremylt
1890ef72598Sjeremylt        X = ceed.Vector(Xdim * dim)
1900ef72598Sjeremylt        X.set_array(x, cmode=libceed.USE_POINTER)
1910ef72598Sjeremylt        Xq = ceed.Vector(Qdim * dim)
1920ef72598Sjeremylt        Xq.set_value(0)
1930ef72598Sjeremylt        U = ceed.Vector(Qdim)
1940ef72598Sjeremylt        U.set_value(0)
1950ef72598Sjeremylt        Uq = ceed.Vector(Qdim)
1960ef72598Sjeremylt
1970ef72598Sjeremylt        bxl = ceed.BasisTensorH1Lagrange(dim, dim, 2, Q, libceed.GAUSS_LOBATTO)
1980ef72598Sjeremylt        bul = ceed.BasisTensorH1Lagrange(dim, 1, Q, Q, libceed.GAUSS_LOBATTO)
1990ef72598Sjeremylt
2000ef72598Sjeremylt        bxl.apply(1, libceed.EVAL_INTERP, X, Xq)
2010ef72598Sjeremylt
2020ef72598Sjeremylt        with Xq.array_read() as xq:
2030ef72598Sjeremylt            for i in range(Qdim):
204*80a9ef05SNatalie Beams                xx = np.empty(dim, dtype=ceed.scalar_type())
2050ef72598Sjeremylt                for d in range(dim):
2060ef72598Sjeremylt                    xx[d] = xq[d * Qdim + i]
2070ef72598Sjeremylt                uq[i] = eval(dim, xx)
2080ef72598Sjeremylt
2090ef72598Sjeremylt        Uq.set_array(uq, cmode=libceed.USE_POINTER)
2100ef72598Sjeremylt
2110ef72598Sjeremylt        # This operation is the identity because the quadrature is collocated
2120ef72598Sjeremylt        bul.T.apply(1, libceed.EVAL_INTERP, Uq, U)
2130ef72598Sjeremylt
2140ef72598Sjeremylt        bxg = ceed.BasisTensorH1Lagrange(dim, dim, 2, Q, libceed.GAUSS)
2150ef72598Sjeremylt        bug = ceed.BasisTensorH1Lagrange(dim, 1, Q, Q, libceed.GAUSS)
2160ef72598Sjeremylt
2170ef72598Sjeremylt        bxg.apply(1, libceed.EVAL_INTERP, X, Xq)
2180ef72598Sjeremylt        bug.apply(1, libceed.EVAL_INTERP, U, Uq)
2190ef72598Sjeremylt
2200ef72598Sjeremylt        with Xq.array_read() as xq, Uq.array_read() as u:
2210ef72598Sjeremylt            for i in range(Qdim):
222*80a9ef05SNatalie Beams                xx = np.empty(dim, dtype=ceed.scalar_type())
2230ef72598Sjeremylt                for d in range(dim):
2240ef72598Sjeremylt                    xx[d] = xq[d * Qdim + i]
2250ef72598Sjeremylt                fx = eval(dim, xx)
2260ef72598Sjeremylt                assert math.fabs(u[i] - fx) < 1E-4
2270ef72598Sjeremylt
2280ef72598Sjeremylt# -------------------------------------------------------------------------------
2290ef72598Sjeremylt# Test grad in multiple dimensions
2300ef72598Sjeremylt# -------------------------------------------------------------------------------
2310ef72598Sjeremylt
2320ef72598Sjeremylt
2330ef72598Sjeremyltdef test_314(ceed_resource):
2340ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2350ef72598Sjeremylt
2360ef72598Sjeremylt    for dim in range(1, 4):
2370ef72598Sjeremylt        P, Q = 8, 10
2380ef72598Sjeremylt        Pdim = P**dim
2390ef72598Sjeremylt        Qdim = Q**dim
2400ef72598Sjeremylt        Xdim = 2**dim
2410ef72598Sjeremylt        sum1 = sum2 = 0
242*80a9ef05SNatalie Beams        x = np.empty(Xdim * dim, dtype=ceed.scalar_type())
243*80a9ef05SNatalie Beams        u = np.empty(Pdim, dtype=ceed.scalar_type())
2440ef72598Sjeremylt
2450ef72598Sjeremylt        for d in range(dim):
2460ef72598Sjeremylt            for i in range(Xdim):
2470ef72598Sjeremylt                x[d * Xdim + i] = 1 if (i %
2480ef72598Sjeremylt                                        (2**(dim - d))) // (2**(dim - d - 1)) else -1
2490ef72598Sjeremylt
2500ef72598Sjeremylt        X = ceed.Vector(Xdim * dim)
2510ef72598Sjeremylt        X.set_array(x, cmode=libceed.USE_POINTER)
2520ef72598Sjeremylt        Xq = ceed.Vector(Pdim * dim)
2530ef72598Sjeremylt        Xq.set_value(0)
2540ef72598Sjeremylt        U = ceed.Vector(Pdim)
2550ef72598Sjeremylt        Uq = ceed.Vector(Qdim * dim)
2560ef72598Sjeremylt        Uq.set_value(0)
2570ef72598Sjeremylt        Ones = ceed.Vector(Qdim * dim)
2580ef72598Sjeremylt        Ones.set_value(1)
2590ef72598Sjeremylt        Gtposeones = ceed.Vector(Pdim)
2600ef72598Sjeremylt        Gtposeones.set_value(0)
2610ef72598Sjeremylt
2620ef72598Sjeremylt        # Get function values at quadrature points
2630ef72598Sjeremylt        bxl = ceed.BasisTensorH1Lagrange(dim, dim, 2, P, libceed.GAUSS_LOBATTO)
2640ef72598Sjeremylt        bxl.apply(1, libceed.EVAL_INTERP, X, Xq)
2650ef72598Sjeremylt
2660ef72598Sjeremylt        with Xq.array_read() as xq:
2670ef72598Sjeremylt            for i in range(Pdim):
268*80a9ef05SNatalie Beams                xx = np.empty(dim, dtype=ceed.scalar_type())
2690ef72598Sjeremylt                for d in range(dim):
2700ef72598Sjeremylt                    xx[d] = xq[d * Pdim + i]
2710ef72598Sjeremylt                u[i] = eval(dim, xx)
2720ef72598Sjeremylt
2730ef72598Sjeremylt        U.set_array(u, cmode=libceed.USE_POINTER)
2740ef72598Sjeremylt
2750ef72598Sjeremylt        # Calculate G u at quadrature points, G' * 1 at dofs
2760ef72598Sjeremylt        bug = ceed.BasisTensorH1Lagrange(dim, 1, P, Q, libceed.GAUSS)
2770ef72598Sjeremylt        bug.apply(1, libceed.EVAL_GRAD, U, Uq)
2780ef72598Sjeremylt        bug.T.apply(1, libceed.EVAL_GRAD, Ones, Gtposeones)
2790ef72598Sjeremylt
2800ef72598Sjeremylt        # Check if 1' * G * u = u' * (G' * 1)
2810ef72598Sjeremylt        with Gtposeones.array_read() as gtposeones, Uq.array_read() as uq:
2820ef72598Sjeremylt            for i in range(Pdim):
2830ef72598Sjeremylt                sum1 += gtposeones[i] * u[i]
2840ef72598Sjeremylt            for i in range(dim * Qdim):
2850ef72598Sjeremylt                sum2 += uq[i]
2860ef72598Sjeremylt
287*80a9ef05SNatalie Beams        assert math.fabs(sum1 - sum2) < 10. * TOL
2880ef72598Sjeremylt
2890ef72598Sjeremylt# -------------------------------------------------------------------------------
2900ef72598Sjeremylt# Test creation and destruction of a 2D Simplex non-tensor H1 basis
2910ef72598Sjeremylt# -------------------------------------------------------------------------------
2920ef72598Sjeremylt
2930ef72598Sjeremylt
2940ef72598Sjeremyltdef test_320(ceed_resource):
2950ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2960ef72598Sjeremylt
2970ef72598Sjeremylt    P, Q, dim = 6, 4, 2
2980ef72598Sjeremylt
299*80a9ef05SNatalie Beams    in_array = np.empty(P, dtype=ceed.scalar_type())
300*80a9ef05SNatalie Beams    qref = np.empty(dim * Q, dtype=ceed.scalar_type())
301*80a9ef05SNatalie Beams    qweight = np.empty(Q, dtype=ceed.scalar_type())
3020ef72598Sjeremylt
303*80a9ef05SNatalie Beams    interp, grad = bm.buildmats(qref, qweight, libceed.scalar_types[
304*80a9ef05SNatalie Beams        libceed.lib.CEED_SCALAR_TYPE])
3050ef72598Sjeremylt
3060ef72598Sjeremylt    b = ceed.BasisH1(libceed.TRIANGLE, 1, P, Q, interp, grad, qref, qweight)
3070ef72598Sjeremylt
3080ef72598Sjeremylt    print(b)
3090ef72598Sjeremylt    del b
3100ef72598Sjeremylt
3110ef72598Sjeremylt# -------------------------------------------------------------------------------
3120ef72598Sjeremylt# Test integration with a 2D Simplex non-tensor H1 basis
3130ef72598Sjeremylt# -------------------------------------------------------------------------------
3140ef72598Sjeremylt
3150ef72598Sjeremylt
3160ef72598Sjeremyltdef test_322(ceed_resource):
3170ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
3180ef72598Sjeremylt
3190ef72598Sjeremylt    P, Q, dim = 6, 4, 2
3200ef72598Sjeremylt
3210ef72598Sjeremylt    xr = np.array([0., 0.5, 1., 0., 0.5, 0., 0., 0.,
322*80a9ef05SNatalie Beams                   0., 0.5, 0.5, 1.], dtype=ceed.scalar_type())
323*80a9ef05SNatalie Beams    in_array = np.empty(P, dtype=ceed.scalar_type())
324*80a9ef05SNatalie Beams    qref = np.empty(dim * Q, dtype=ceed.scalar_type())
325*80a9ef05SNatalie Beams    qweight = np.empty(Q, dtype=ceed.scalar_type())
3260ef72598Sjeremylt
327*80a9ef05SNatalie Beams    interp, grad = bm.buildmats(qref, qweight, libceed.scalar_types[
328*80a9ef05SNatalie Beams        libceed.lib.CEED_SCALAR_TYPE])
3290ef72598Sjeremylt
3300ef72598Sjeremylt    b = ceed.BasisH1(libceed.TRIANGLE, 1, P, Q, interp, grad, qref, qweight)
3310ef72598Sjeremylt
3320ef72598Sjeremylt    # Interpolate function to quadrature points
3330ef72598Sjeremylt    for i in range(P):
3340ef72598Sjeremylt        in_array[i] = feval(xr[0 * P + i], xr[1 * P + i])
3350ef72598Sjeremylt
3360ef72598Sjeremylt    in_vec = ceed.Vector(P)
3370ef72598Sjeremylt    in_vec.set_array(in_array, cmode=libceed.USE_POINTER)
3380ef72598Sjeremylt    out_vec = ceed.Vector(Q)
3390ef72598Sjeremylt    out_vec.set_value(0)
3400ef72598Sjeremylt    weights_vec = ceed.Vector(Q)
3410ef72598Sjeremylt    weights_vec.set_value(0)
3420ef72598Sjeremylt
3430ef72598Sjeremylt    b.apply(1, libceed.EVAL_INTERP, in_vec, out_vec)
3440ef72598Sjeremylt    b.apply(1, libceed.EVAL_WEIGHT, libceed.VECTOR_NONE, weights_vec)
3450ef72598Sjeremylt
3460ef72598Sjeremylt    # Check values at quadrature points
3470ef72598Sjeremylt    with out_vec.array_read() as out_array, weights_vec.array_read() as weights_array:
3480ef72598Sjeremylt        sum = 0
3490ef72598Sjeremylt        for i in range(Q):
3500ef72598Sjeremylt            sum += out_array[i] * weights_array[i]
351*80a9ef05SNatalie Beams        assert math.fabs(sum - 17. / 24.) < 10. * TOL
3520ef72598Sjeremylt
3530ef72598Sjeremylt# -------------------------------------------------------------------------------
3540ef72598Sjeremylt# Test grad with a 2D Simplex non-tensor H1 basis
3550ef72598Sjeremylt# -------------------------------------------------------------------------------
3560ef72598Sjeremylt
3570ef72598Sjeremylt
3580ef72598Sjeremyltdef test_323(ceed_resource):
3590ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
3600ef72598Sjeremylt
3610ef72598Sjeremylt    P, Q, dim = 6, 4, 2
3620ef72598Sjeremylt
3630ef72598Sjeremylt    xq = np.array([0.2, 0.6, 1. / 3., 0.2, 0.2, 0.2,
364*80a9ef05SNatalie Beams                   1. / 3., 0.6], dtype=ceed.scalar_type())
3650ef72598Sjeremylt    xr = np.array([0., 0.5, 1., 0., 0.5, 0., 0., 0.,
366*80a9ef05SNatalie Beams                   0., 0.5, 0.5, 1.], dtype=ceed.scalar_type())
367*80a9ef05SNatalie Beams    in_array = np.empty(P, dtype=ceed.scalar_type())
368*80a9ef05SNatalie Beams    qref = np.empty(dim * Q, dtype=ceed.scalar_type())
369*80a9ef05SNatalie Beams    qweight = np.empty(Q, dtype=ceed.scalar_type())
3700ef72598Sjeremylt
371*80a9ef05SNatalie Beams    interp, grad = bm.buildmats(qref, qweight, libceed.scalar_types[
372*80a9ef05SNatalie Beams        libceed.lib.CEED_SCALAR_TYPE])
3730ef72598Sjeremylt
3740ef72598Sjeremylt    b = ceed.BasisH1(libceed.TRIANGLE, 1, P, Q, interp, grad, qref, qweight)
3750ef72598Sjeremylt
3760ef72598Sjeremylt    # Interpolate function to quadrature points
3770ef72598Sjeremylt    for i in range(P):
3780ef72598Sjeremylt        in_array[i] = feval(xr[0 * P + i], xr[1 * P + i])
3790ef72598Sjeremylt
3800ef72598Sjeremylt    in_vec = ceed.Vector(P)
3810ef72598Sjeremylt    in_vec.set_array(in_array, cmode=libceed.USE_POINTER)
3820ef72598Sjeremylt    out_vec = ceed.Vector(Q * dim)
3830ef72598Sjeremylt    out_vec.set_value(0)
3840ef72598Sjeremylt
3850ef72598Sjeremylt    b.apply(1, libceed.EVAL_GRAD, in_vec, out_vec)
3860ef72598Sjeremylt
3870ef72598Sjeremylt    # Check values at quadrature points
3880ef72598Sjeremylt    with out_vec.array_read() as out_array:
3890ef72598Sjeremylt        for i in range(Q):
3900ef72598Sjeremylt            value = dfeval(xq[0 * Q + i], xq[1 * Q + i])
391*80a9ef05SNatalie Beams            assert math.fabs(out_array[0 * Q + i] - value) < 10. * TOL
3920ef72598Sjeremylt
3930ef72598Sjeremylt            value = dfeval(xq[1 * Q + i], xq[0 * Q + i])
394*80a9ef05SNatalie Beams            assert math.fabs(out_array[1 * Q + i] - value) < 10. * TOL
3950ef72598Sjeremylt
3960ef72598Sjeremylt# -------------------------------------------------------------------------------
397