xref: /libCEED/python/tests/test-3-basis.py (revision 0ef725981a32b9079ff6c5100673b913b8f4d7c0)
1*0ef72598Sjeremylt# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2*0ef72598Sjeremylt# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3*0ef72598Sjeremylt# reserved. See files LICENSE and NOTICE for details.
4*0ef72598Sjeremylt#
5*0ef72598Sjeremylt# This file is part of CEED, a collection of benchmarks, miniapps, software
6*0ef72598Sjeremylt# libraries and APIs for efficient high-order finite element and spectral
7*0ef72598Sjeremylt# element discretizations for exascale applications. For more information and
8*0ef72598Sjeremylt# source code availability see http://github.com/ceed.
9*0ef72598Sjeremylt#
10*0ef72598Sjeremylt# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11*0ef72598Sjeremylt# a collaborative effort of two U.S. Department of Energy organizations (Office
12*0ef72598Sjeremylt# of Science and the National Nuclear Security Administration) responsible for
13*0ef72598Sjeremylt# the planning and preparation of a capable exascale ecosystem, including
14*0ef72598Sjeremylt# software, applications, hardware, advanced system engineering and early
15*0ef72598Sjeremylt# testbed platforms, in support of the nation's exascale computing imperative.
16*0ef72598Sjeremylt
17*0ef72598Sjeremylt# @file
18*0ef72598Sjeremylt# Test Ceed Basis functionality
19*0ef72598Sjeremylt
20*0ef72598Sjeremyltimport os
21*0ef72598Sjeremyltimport math
22*0ef72598Sjeremyltimport libceed
23*0ef72598Sjeremyltimport numpy as np
24*0ef72598Sjeremyltimport buildmats as bm
25*0ef72598Sjeremyltimport check
26*0ef72598Sjeremylt
27*0ef72598SjeremyltTOL = np.finfo(float).eps * 256
28*0ef72598Sjeremylt
29*0ef72598Sjeremylt# -------------------------------------------------------------------------------
30*0ef72598Sjeremylt# Utilities
31*0ef72598Sjeremylt# -------------------------------------------------------------------------------
32*0ef72598Sjeremylt
33*0ef72598Sjeremylt
34*0ef72598Sjeremyltdef eval(dim, x):
35*0ef72598Sjeremylt    result, center = 1, 0.1
36*0ef72598Sjeremylt    for d in range(dim):
37*0ef72598Sjeremylt        result *= math.tanh(x[d] - center)
38*0ef72598Sjeremylt        center += 0.1
39*0ef72598Sjeremylt    return result
40*0ef72598Sjeremylt
41*0ef72598Sjeremylt
42*0ef72598Sjeremyltdef feval(x1, x2):
43*0ef72598Sjeremylt    return x1 * x1 + x2 * x2 + x1 * x2 + 1
44*0ef72598Sjeremylt
45*0ef72598Sjeremylt
46*0ef72598Sjeremyltdef dfeval(x1, x2):
47*0ef72598Sjeremylt    return 2 * x1 + x2
48*0ef72598Sjeremylt
49*0ef72598Sjeremylt# -------------------------------------------------------------------------------
50*0ef72598Sjeremylt# Test creation and distruction of a H1Lagrange basis
51*0ef72598Sjeremylt# -------------------------------------------------------------------------------
52*0ef72598Sjeremylt
53*0ef72598Sjeremylt
54*0ef72598Sjeremyltdef test_300(ceed_resource, capsys):
55*0ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
56*0ef72598Sjeremylt
57*0ef72598Sjeremylt    b = ceed.BasisTensorH1Lagrange(1, 1, 4, 4, libceed.GAUSS_LOBATTO)
58*0ef72598Sjeremylt    print(b)
59*0ef72598Sjeremylt    del b
60*0ef72598Sjeremylt
61*0ef72598Sjeremylt    b = ceed.BasisTensorH1Lagrange(1, 1, 4, 4, libceed.GAUSS)
62*0ef72598Sjeremylt    print(b)
63*0ef72598Sjeremylt    del b
64*0ef72598Sjeremylt
65*0ef72598Sjeremylt    stdout, stderr, ref_stdout = check.output(capsys)
66*0ef72598Sjeremylt    assert not stderr
67*0ef72598Sjeremylt    assert stdout == ref_stdout
68*0ef72598Sjeremylt
69*0ef72598Sjeremylt# -------------------------------------------------------------------------------
70*0ef72598Sjeremylt# Test QR factorization
71*0ef72598Sjeremylt# -------------------------------------------------------------------------------
72*0ef72598Sjeremylt
73*0ef72598Sjeremylt
74*0ef72598Sjeremyltdef test_301(ceed_resource, capsys):
75*0ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
76*0ef72598Sjeremylt
77*0ef72598Sjeremylt    qr = np.array([1, -1, 4, 1, 4, -2, 1, 4, 2, 1, -1, 0], dtype="float64")
78*0ef72598Sjeremylt    tau = np.empty(3, dtype="float64")
79*0ef72598Sjeremylt
80*0ef72598Sjeremylt    qr, tau = ceed.qr_factorization(qr, tau, 4, 3)
81*0ef72598Sjeremylt
82*0ef72598Sjeremylt    for i in range(len(qr)):
83*0ef72598Sjeremylt        if qr[i] <= TOL and qr[i] >= -TOL:
84*0ef72598Sjeremylt            qr[i] = 0
85*0ef72598Sjeremylt        print("%12.8f" % qr[i])
86*0ef72598Sjeremylt
87*0ef72598Sjeremylt    for i in range(len(tau)):
88*0ef72598Sjeremylt        if tau[i] <= TOL and tau[i] >= -TOL:
89*0ef72598Sjeremylt            tau[i] = 0
90*0ef72598Sjeremylt        print("%12.8f" % tau[i])
91*0ef72598Sjeremylt
92*0ef72598Sjeremylt    stdout, stderr, ref_stdout = check.output(capsys)
93*0ef72598Sjeremylt    assert not stderr
94*0ef72598Sjeremylt    assert stdout == ref_stdout
95*0ef72598Sjeremylt
96*0ef72598Sjeremylt# -------------------------------------------------------------------------------
97*0ef72598Sjeremylt# Test Symmetric Schur Decomposition
98*0ef72598Sjeremylt# -------------------------------------------------------------------------------
99*0ef72598Sjeremylt
100*0ef72598Sjeremylt
101*0ef72598Sjeremyltdef test_304(ceed_resource, capsys):
102*0ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
103*0ef72598Sjeremylt
104*0ef72598Sjeremylt    A = np.array([0.19996678, 0.0745459, -0.07448852, 0.0332866,
105*0ef72598Sjeremylt                  0.0745459, 1., 0.16666509, -0.07448852,
106*0ef72598Sjeremylt                  -0.07448852, 0.16666509, 1., 0.0745459,
107*0ef72598Sjeremylt                  0.0332866, -0.07448852, 0.0745459, 0.19996678], dtype="float64")
108*0ef72598Sjeremylt
109*0ef72598Sjeremylt    lam = ceed.symmetric_schur_decomposition(A, 4)
110*0ef72598Sjeremylt
111*0ef72598Sjeremylt    print("Q: ")
112*0ef72598Sjeremylt    for i in range(4):
113*0ef72598Sjeremylt        for j in range(4):
114*0ef72598Sjeremylt            if A[j + 4 * i] <= TOL and A[j + 4 * i] >= -TOL:
115*0ef72598Sjeremylt                A[j + 4 * i] = 0
116*0ef72598Sjeremylt            print("%12.8f" % A[j + 4 * i])
117*0ef72598Sjeremylt
118*0ef72598Sjeremylt    print("lambda: ")
119*0ef72598Sjeremylt    for i in range(4):
120*0ef72598Sjeremylt        if lam[i] <= TOL and lam[i] >= -TOL:
121*0ef72598Sjeremylt            lam[i] = 0
122*0ef72598Sjeremylt        print("%12.8f" % lam[i])
123*0ef72598Sjeremylt
124*0ef72598Sjeremylt    stdout, stderr, ref_stdout = check.output(capsys)
125*0ef72598Sjeremylt    assert not stderr
126*0ef72598Sjeremylt    assert stdout == ref_stdout
127*0ef72598Sjeremylt
128*0ef72598Sjeremylt# -------------------------------------------------------------------------------
129*0ef72598Sjeremylt# Test Simultaneous Diagonalization
130*0ef72598Sjeremylt# -------------------------------------------------------------------------------
131*0ef72598Sjeremylt
132*0ef72598Sjeremylt
133*0ef72598Sjeremyltdef test_305(ceed_resource, capsys):
134*0ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
135*0ef72598Sjeremylt
136*0ef72598Sjeremylt    M = np.array([0.19996678, 0.0745459, -0.07448852, 0.0332866,
137*0ef72598Sjeremylt                  0.0745459, 1., 0.16666509, -0.07448852,
138*0ef72598Sjeremylt                  -0.07448852, 0.16666509, 1., 0.0745459,
139*0ef72598Sjeremylt                  0.0332866, -0.07448852, 0.0745459, 0.19996678], dtype="float64")
140*0ef72598Sjeremylt    K = np.array([3.03344425, -3.41501767, 0.49824435, -0.11667092,
141*0ef72598Sjeremylt                  -3.41501767, 5.83354662, -2.9167733, 0.49824435,
142*0ef72598Sjeremylt                  0.49824435, -2.9167733, 5.83354662, -3.41501767,
143*0ef72598Sjeremylt                  -0.11667092, 0.49824435, -3.41501767, 3.03344425], dtype="float64")
144*0ef72598Sjeremylt
145*0ef72598Sjeremylt    x, lam = ceed.simultaneous_diagonalization(K, M, 4)
146*0ef72598Sjeremylt
147*0ef72598Sjeremylt    print("x: ")
148*0ef72598Sjeremylt    for i in range(4):
149*0ef72598Sjeremylt        for j in range(4):
150*0ef72598Sjeremylt            if x[j + 4 * i] <= TOL and x[j + 4 * i] >= -TOL:
151*0ef72598Sjeremylt                x[j + 4 * i] = 0
152*0ef72598Sjeremylt            print("%12.8f" % x[j + 4 * i])
153*0ef72598Sjeremylt
154*0ef72598Sjeremylt    print("lambda: ")
155*0ef72598Sjeremylt    for i in range(4):
156*0ef72598Sjeremylt        if lam[i] <= TOL and lam[i] >= -TOL:
157*0ef72598Sjeremylt            lam[i] = 0
158*0ef72598Sjeremylt        print("%12.8f" % lam[i])
159*0ef72598Sjeremylt
160*0ef72598Sjeremylt    stdout, stderr, ref_stdout = check.output(capsys)
161*0ef72598Sjeremylt    assert not stderr
162*0ef72598Sjeremylt    assert stdout == ref_stdout
163*0ef72598Sjeremylt
164*0ef72598Sjeremylt# -------------------------------------------------------------------------------
165*0ef72598Sjeremylt# Test GetNumNodes and GetNumQuadraturePoints for basis
166*0ef72598Sjeremylt# -------------------------------------------------------------------------------
167*0ef72598Sjeremylt
168*0ef72598Sjeremylt
169*0ef72598Sjeremyltdef test_306(ceed_resource):
170*0ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
171*0ef72598Sjeremylt
172*0ef72598Sjeremylt    b = ceed.BasisTensorH1Lagrange(3, 1, 4, 5, libceed.GAUSS_LOBATTO)
173*0ef72598Sjeremylt
174*0ef72598Sjeremylt    p = b.get_num_nodes()
175*0ef72598Sjeremylt    q = b.get_num_quadrature_points()
176*0ef72598Sjeremylt
177*0ef72598Sjeremylt    assert p == 64
178*0ef72598Sjeremylt    assert q == 125
179*0ef72598Sjeremylt
180*0ef72598Sjeremylt# -------------------------------------------------------------------------------
181*0ef72598Sjeremylt# Test interpolation in multiple dimensions
182*0ef72598Sjeremylt# -------------------------------------------------------------------------------
183*0ef72598Sjeremylt
184*0ef72598Sjeremylt
185*0ef72598Sjeremyltdef test_313(ceed_resource):
186*0ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
187*0ef72598Sjeremylt
188*0ef72598Sjeremylt    for dim in range(1, 4):
189*0ef72598Sjeremylt        Q = 10
190*0ef72598Sjeremylt        Qdim = Q**dim
191*0ef72598Sjeremylt        Xdim = 2**dim
192*0ef72598Sjeremylt        x = np.empty(Xdim * dim, dtype="float64")
193*0ef72598Sjeremylt        uq = np.empty(Qdim, dtype="float64")
194*0ef72598Sjeremylt
195*0ef72598Sjeremylt        for d in range(dim):
196*0ef72598Sjeremylt            for i in range(Xdim):
197*0ef72598Sjeremylt                x[d * Xdim + i] = 1 if (i %
198*0ef72598Sjeremylt                                        (2**(dim - d))) // (2**(dim - d - 1)) else -1
199*0ef72598Sjeremylt
200*0ef72598Sjeremylt        X = ceed.Vector(Xdim * dim)
201*0ef72598Sjeremylt        X.set_array(x, cmode=libceed.USE_POINTER)
202*0ef72598Sjeremylt        Xq = ceed.Vector(Qdim * dim)
203*0ef72598Sjeremylt        Xq.set_value(0)
204*0ef72598Sjeremylt        U = ceed.Vector(Qdim)
205*0ef72598Sjeremylt        U.set_value(0)
206*0ef72598Sjeremylt        Uq = ceed.Vector(Qdim)
207*0ef72598Sjeremylt
208*0ef72598Sjeremylt        bxl = ceed.BasisTensorH1Lagrange(dim, dim, 2, Q, libceed.GAUSS_LOBATTO)
209*0ef72598Sjeremylt        bul = ceed.BasisTensorH1Lagrange(dim, 1, Q, Q, libceed.GAUSS_LOBATTO)
210*0ef72598Sjeremylt
211*0ef72598Sjeremylt        bxl.apply(1, libceed.EVAL_INTERP, X, Xq)
212*0ef72598Sjeremylt
213*0ef72598Sjeremylt        with Xq.array_read() as xq:
214*0ef72598Sjeremylt            for i in range(Qdim):
215*0ef72598Sjeremylt                xx = np.empty(dim, dtype="float64")
216*0ef72598Sjeremylt                for d in range(dim):
217*0ef72598Sjeremylt                    xx[d] = xq[d * Qdim + i]
218*0ef72598Sjeremylt                uq[i] = eval(dim, xx)
219*0ef72598Sjeremylt
220*0ef72598Sjeremylt        Uq.set_array(uq, cmode=libceed.USE_POINTER)
221*0ef72598Sjeremylt
222*0ef72598Sjeremylt        # This operation is the identity because the quadrature is collocated
223*0ef72598Sjeremylt        bul.T.apply(1, libceed.EVAL_INTERP, Uq, U)
224*0ef72598Sjeremylt
225*0ef72598Sjeremylt        bxg = ceed.BasisTensorH1Lagrange(dim, dim, 2, Q, libceed.GAUSS)
226*0ef72598Sjeremylt        bug = ceed.BasisTensorH1Lagrange(dim, 1, Q, Q, libceed.GAUSS)
227*0ef72598Sjeremylt
228*0ef72598Sjeremylt        bxg.apply(1, libceed.EVAL_INTERP, X, Xq)
229*0ef72598Sjeremylt        bug.apply(1, libceed.EVAL_INTERP, U, Uq)
230*0ef72598Sjeremylt
231*0ef72598Sjeremylt        with Xq.array_read() as xq, Uq.array_read() as u:
232*0ef72598Sjeremylt            for i in range(Qdim):
233*0ef72598Sjeremylt                xx = np.empty(dim, dtype="float64")
234*0ef72598Sjeremylt                for d in range(dim):
235*0ef72598Sjeremylt                    xx[d] = xq[d * Qdim + i]
236*0ef72598Sjeremylt                fx = eval(dim, xx)
237*0ef72598Sjeremylt                assert math.fabs(u[i] - fx) < 1E-4
238*0ef72598Sjeremylt
239*0ef72598Sjeremylt# -------------------------------------------------------------------------------
240*0ef72598Sjeremylt# Test grad in multiple dimensions
241*0ef72598Sjeremylt# -------------------------------------------------------------------------------
242*0ef72598Sjeremylt
243*0ef72598Sjeremylt
244*0ef72598Sjeremyltdef test_314(ceed_resource):
245*0ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
246*0ef72598Sjeremylt
247*0ef72598Sjeremylt    for dim in range(1, 4):
248*0ef72598Sjeremylt        P, Q = 8, 10
249*0ef72598Sjeremylt        Pdim = P**dim
250*0ef72598Sjeremylt        Qdim = Q**dim
251*0ef72598Sjeremylt        Xdim = 2**dim
252*0ef72598Sjeremylt        sum1 = sum2 = 0
253*0ef72598Sjeremylt        x = np.empty(Xdim * dim, dtype="float64")
254*0ef72598Sjeremylt        u = np.empty(Pdim, dtype="float64")
255*0ef72598Sjeremylt
256*0ef72598Sjeremylt        for d in range(dim):
257*0ef72598Sjeremylt            for i in range(Xdim):
258*0ef72598Sjeremylt                x[d * Xdim + i] = 1 if (i %
259*0ef72598Sjeremylt                                        (2**(dim - d))) // (2**(dim - d - 1)) else -1
260*0ef72598Sjeremylt
261*0ef72598Sjeremylt        X = ceed.Vector(Xdim * dim)
262*0ef72598Sjeremylt        X.set_array(x, cmode=libceed.USE_POINTER)
263*0ef72598Sjeremylt        Xq = ceed.Vector(Pdim * dim)
264*0ef72598Sjeremylt        Xq.set_value(0)
265*0ef72598Sjeremylt        U = ceed.Vector(Pdim)
266*0ef72598Sjeremylt        Uq = ceed.Vector(Qdim * dim)
267*0ef72598Sjeremylt        Uq.set_value(0)
268*0ef72598Sjeremylt        Ones = ceed.Vector(Qdim * dim)
269*0ef72598Sjeremylt        Ones.set_value(1)
270*0ef72598Sjeremylt        Gtposeones = ceed.Vector(Pdim)
271*0ef72598Sjeremylt        Gtposeones.set_value(0)
272*0ef72598Sjeremylt
273*0ef72598Sjeremylt        # Get function values at quadrature points
274*0ef72598Sjeremylt        bxl = ceed.BasisTensorH1Lagrange(dim, dim, 2, P, libceed.GAUSS_LOBATTO)
275*0ef72598Sjeremylt        bxl.apply(1, libceed.EVAL_INTERP, X, Xq)
276*0ef72598Sjeremylt
277*0ef72598Sjeremylt        with Xq.array_read() as xq:
278*0ef72598Sjeremylt            for i in range(Pdim):
279*0ef72598Sjeremylt                xx = np.empty(dim, dtype="float64")
280*0ef72598Sjeremylt                for d in range(dim):
281*0ef72598Sjeremylt                    xx[d] = xq[d * Pdim + i]
282*0ef72598Sjeremylt                u[i] = eval(dim, xx)
283*0ef72598Sjeremylt
284*0ef72598Sjeremylt        U.set_array(u, cmode=libceed.USE_POINTER)
285*0ef72598Sjeremylt
286*0ef72598Sjeremylt        # Calculate G u at quadrature points, G' * 1 at dofs
287*0ef72598Sjeremylt        bug = ceed.BasisTensorH1Lagrange(dim, 1, P, Q, libceed.GAUSS)
288*0ef72598Sjeremylt        bug.apply(1, libceed.EVAL_GRAD, U, Uq)
289*0ef72598Sjeremylt        bug.T.apply(1, libceed.EVAL_GRAD, Ones, Gtposeones)
290*0ef72598Sjeremylt
291*0ef72598Sjeremylt        # Check if 1' * G * u = u' * (G' * 1)
292*0ef72598Sjeremylt        with Gtposeones.array_read() as gtposeones, Uq.array_read() as uq:
293*0ef72598Sjeremylt            for i in range(Pdim):
294*0ef72598Sjeremylt                sum1 += gtposeones[i] * u[i]
295*0ef72598Sjeremylt            for i in range(dim * Qdim):
296*0ef72598Sjeremylt                sum2 += uq[i]
297*0ef72598Sjeremylt
298*0ef72598Sjeremylt        assert math.fabs(sum1 - sum2) < 1E-10
299*0ef72598Sjeremylt
300*0ef72598Sjeremylt# -------------------------------------------------------------------------------
301*0ef72598Sjeremylt# Test creation and destruction of a 2D Simplex non-tensor H1 basis
302*0ef72598Sjeremylt# -------------------------------------------------------------------------------
303*0ef72598Sjeremylt
304*0ef72598Sjeremylt
305*0ef72598Sjeremyltdef test_320(ceed_resource):
306*0ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
307*0ef72598Sjeremylt
308*0ef72598Sjeremylt    P, Q, dim = 6, 4, 2
309*0ef72598Sjeremylt
310*0ef72598Sjeremylt    in_array = np.empty(P, dtype="float64")
311*0ef72598Sjeremylt    qref = np.empty(dim * Q, dtype="float64")
312*0ef72598Sjeremylt    qweight = np.empty(Q, dtype="float64")
313*0ef72598Sjeremylt
314*0ef72598Sjeremylt    interp, grad = bm.buildmats(qref, qweight)
315*0ef72598Sjeremylt
316*0ef72598Sjeremylt    b = ceed.BasisH1(libceed.TRIANGLE, 1, P, Q, interp, grad, qref, qweight)
317*0ef72598Sjeremylt
318*0ef72598Sjeremylt    print(b)
319*0ef72598Sjeremylt    del b
320*0ef72598Sjeremylt
321*0ef72598Sjeremylt# -------------------------------------------------------------------------------
322*0ef72598Sjeremylt# Test integration with a 2D Simplex non-tensor H1 basis
323*0ef72598Sjeremylt# -------------------------------------------------------------------------------
324*0ef72598Sjeremylt
325*0ef72598Sjeremylt
326*0ef72598Sjeremyltdef test_322(ceed_resource):
327*0ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
328*0ef72598Sjeremylt
329*0ef72598Sjeremylt    P, Q, dim = 6, 4, 2
330*0ef72598Sjeremylt
331*0ef72598Sjeremylt    xr = np.array([0., 0.5, 1., 0., 0.5, 0., 0., 0.,
332*0ef72598Sjeremylt                   0., 0.5, 0.5, 1.], dtype="float64")
333*0ef72598Sjeremylt    in_array = np.empty(P, dtype="float64")
334*0ef72598Sjeremylt    qref = np.empty(dim * Q, dtype="float64")
335*0ef72598Sjeremylt    qweight = np.empty(Q, dtype="float64")
336*0ef72598Sjeremylt
337*0ef72598Sjeremylt    interp, grad = bm.buildmats(qref, qweight)
338*0ef72598Sjeremylt
339*0ef72598Sjeremylt    b = ceed.BasisH1(libceed.TRIANGLE, 1, P, Q, interp, grad, qref, qweight)
340*0ef72598Sjeremylt
341*0ef72598Sjeremylt    # Interpolate function to quadrature points
342*0ef72598Sjeremylt    for i in range(P):
343*0ef72598Sjeremylt        in_array[i] = feval(xr[0 * P + i], xr[1 * P + i])
344*0ef72598Sjeremylt
345*0ef72598Sjeremylt    in_vec = ceed.Vector(P)
346*0ef72598Sjeremylt    in_vec.set_array(in_array, cmode=libceed.USE_POINTER)
347*0ef72598Sjeremylt    out_vec = ceed.Vector(Q)
348*0ef72598Sjeremylt    out_vec.set_value(0)
349*0ef72598Sjeremylt    weights_vec = ceed.Vector(Q)
350*0ef72598Sjeremylt    weights_vec.set_value(0)
351*0ef72598Sjeremylt
352*0ef72598Sjeremylt    b.apply(1, libceed.EVAL_INTERP, in_vec, out_vec)
353*0ef72598Sjeremylt    b.apply(1, libceed.EVAL_WEIGHT, libceed.VECTOR_NONE, weights_vec)
354*0ef72598Sjeremylt
355*0ef72598Sjeremylt    # Check values at quadrature points
356*0ef72598Sjeremylt    with out_vec.array_read() as out_array, weights_vec.array_read() as weights_array:
357*0ef72598Sjeremylt        sum = 0
358*0ef72598Sjeremylt        for i in range(Q):
359*0ef72598Sjeremylt            sum += out_array[i] * weights_array[i]
360*0ef72598Sjeremylt        assert math.fabs(sum - 17. / 24.) < 1E-10
361*0ef72598Sjeremylt
362*0ef72598Sjeremylt# -------------------------------------------------------------------------------
363*0ef72598Sjeremylt# Test grad with a 2D Simplex non-tensor H1 basis
364*0ef72598Sjeremylt# -------------------------------------------------------------------------------
365*0ef72598Sjeremylt
366*0ef72598Sjeremylt
367*0ef72598Sjeremyltdef test_323(ceed_resource):
368*0ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
369*0ef72598Sjeremylt
370*0ef72598Sjeremylt    P, Q, dim = 6, 4, 2
371*0ef72598Sjeremylt
372*0ef72598Sjeremylt    xq = np.array([0.2, 0.6, 1. / 3., 0.2, 0.2, 0.2,
373*0ef72598Sjeremylt                   1. / 3., 0.6], dtype="float64")
374*0ef72598Sjeremylt    xr = np.array([0., 0.5, 1., 0., 0.5, 0., 0., 0.,
375*0ef72598Sjeremylt                   0., 0.5, 0.5, 1.], dtype="float64")
376*0ef72598Sjeremylt    in_array = np.empty(P, dtype="float64")
377*0ef72598Sjeremylt    qref = np.empty(dim * Q, dtype="float64")
378*0ef72598Sjeremylt    qweight = np.empty(Q, dtype="float64")
379*0ef72598Sjeremylt
380*0ef72598Sjeremylt    interp, grad = bm.buildmats(qref, qweight)
381*0ef72598Sjeremylt
382*0ef72598Sjeremylt    b = ceed.BasisH1(libceed.TRIANGLE, 1, P, Q, interp, grad, qref, qweight)
383*0ef72598Sjeremylt
384*0ef72598Sjeremylt    # Interpolate function to quadrature points
385*0ef72598Sjeremylt    for i in range(P):
386*0ef72598Sjeremylt        in_array[i] = feval(xr[0 * P + i], xr[1 * P + i])
387*0ef72598Sjeremylt
388*0ef72598Sjeremylt    in_vec = ceed.Vector(P)
389*0ef72598Sjeremylt    in_vec.set_array(in_array, cmode=libceed.USE_POINTER)
390*0ef72598Sjeremylt    out_vec = ceed.Vector(Q * dim)
391*0ef72598Sjeremylt    out_vec.set_value(0)
392*0ef72598Sjeremylt
393*0ef72598Sjeremylt    b.apply(1, libceed.EVAL_GRAD, in_vec, out_vec)
394*0ef72598Sjeremylt
395*0ef72598Sjeremylt    # Check values at quadrature points
396*0ef72598Sjeremylt    with out_vec.array_read() as out_array:
397*0ef72598Sjeremylt        for i in range(Q):
398*0ef72598Sjeremylt            value = dfeval(xq[0 * Q + i], xq[1 * Q + i])
399*0ef72598Sjeremylt            assert math.fabs(out_array[0 * Q + i] - value) < 1E-10
400*0ef72598Sjeremylt
401*0ef72598Sjeremylt            value = dfeval(xq[1 * Q + i], xq[0 * Q + i])
402*0ef72598Sjeremylt            assert math.fabs(out_array[1 * Q + i] - value) < 1E-10
403*0ef72598Sjeremylt
404*0ef72598Sjeremylt# -------------------------------------------------------------------------------
405