xref: /libCEED/python/tests/test-4-qfunction.py (revision bf185410af015d53ed6d3b520013ce284095d550)
1# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3# reserved. See files LICENSE and NOTICE for details.
4#
5# This file is part of CEED, a collection of benchmarks, miniapps, software
6# libraries and APIs for efficient high-order finite element and spectral
7# element discretizations for exascale applications. For more information and
8# source code availability see http://github.com/ceed.
9#
10# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11# a collaborative effort of two U.S. Department of Energy organizations (Office
12# of Science and the National Nuclear Security Administration) responsible for
13# the planning and preparation of a capable exascale ecosystem, including
14# software, applications, hardware, advanced system engineering and early
15# testbed platforms, in support of the nation's exascale computing imperative.
16
17# @file
18# Test Ceed QFunction functionality
19
20import os
21import libceed
22import numpy as np
23import check
24
25# -------------------------------------------------------------------------------
26# Utility
27# -------------------------------------------------------------------------------
28
29
30def load_qfs_so():
31    from distutils.sysconfig import get_config_var
32    import ctypes
33
34    file_dir = os.path.dirname(os.path.abspath(__file__))
35    qfs_so = os.path.join(
36        file_dir,
37        "libceed_qfunctions" + get_config_var("EXT_SUFFIX"))
38
39    # Load library
40    return ctypes.cdll.LoadLibrary(qfs_so)
41
42# -------------------------------------------------------------------------------
43# Test creation, evaluation, and destruction for qfunction
44# -------------------------------------------------------------------------------
45
46
47def test_400(ceed_resource):
48    ceed = libceed.Ceed(ceed_resource)
49
50    file_dir = os.path.dirname(os.path.abspath(__file__))
51    qfs = load_qfs_so()
52
53    qf_setup = ceed.QFunction(1, qfs.setup_mass,
54                              os.path.join(file_dir, "test-qfunctions.h:setup_mass"))
55    qf_setup.add_input("w", 1, libceed.EVAL_WEIGHT)
56    qf_setup.add_input("dx", 1, libceed.EVAL_GRAD)
57    qf_setup.add_output("qdata", 1, libceed.EVAL_NONE)
58
59    qf_mass = ceed.QFunction(1, qfs.apply_mass,
60                             os.path.join(file_dir, "test-qfunctions.h:apply_mass"))
61    qf_mass.add_input("qdata", 1, libceed.EVAL_NONE)
62    qf_mass.add_input("u", 1, libceed.EVAL_INTERP)
63    qf_mass.add_output("v", 1, libceed.EVAL_INTERP)
64
65    q = 8
66
67    w_array = np.zeros(q, dtype="float64")
68    u_array = np.zeros(q, dtype="float64")
69    v_true = np.zeros(q, dtype="float64")
70    for i in range(q):
71        x = 2. * i / (q - 1) - 1
72        w_array[i] = 1 - x * x
73        u_array[i] = 2 + 3 * x + 5 * x * x
74        v_true[i] = w_array[i] * u_array[i]
75
76    dx = ceed.Vector(q)
77    dx.set_value(1)
78    w = ceed.Vector(q)
79    w.set_array(w_array, cmode=libceed.USE_POINTER)
80    u = ceed.Vector(q)
81    u.set_array(u_array, cmode=libceed.USE_POINTER)
82    v = ceed.Vector(q)
83    v.set_value(0)
84    qdata = ceed.Vector(q)
85    qdata.set_value(0)
86
87    inputs = [dx, w]
88    outputs = [qdata]
89    qf_setup.apply(q, inputs, outputs)
90
91    inputs = [qdata, u]
92    outputs = [v]
93    qf_mass.apply(q, inputs, outputs)
94
95    with v.array_read() as v_array:
96        for i in range(q):
97            assert v_array[i] == v_true[i]
98
99# -------------------------------------------------------------------------------
100# Test creation, evaluation, and destruction for qfunction
101# -------------------------------------------------------------------------------
102
103
104def test_401(ceed_resource):
105    ceed = libceed.Ceed(ceed_resource)
106
107    file_dir = os.path.dirname(os.path.abspath(__file__))
108    qfs = load_qfs_so()
109
110    qf_setup = ceed.QFunction(1, qfs.setup_mass,
111                              os.path.join(file_dir, "test-qfunctions.h:setup_mass"))
112    qf_setup.add_input("w", 1, libceed.EVAL_WEIGHT)
113    qf_setup.add_input("dx", 1, libceed.EVAL_GRAD)
114    qf_setup.add_output("qdata", 1, libceed.EVAL_NONE)
115
116    qf_mass = ceed.QFunction(1, qfs.apply_mass,
117                             os.path.join(file_dir, "t400-qfunction.h:apply_mass"))
118    qf_mass.add_input("qdata", 1, libceed.EVAL_NONE)
119    qf_mass.add_input("u", 1, libceed.EVAL_INTERP)
120    qf_mass.add_output("v", 1, libceed.EVAL_INTERP)
121
122    ctx_data = np.array([1., 2., 3., 4., 5.])
123    ctx = ceed.QFunctionContext()
124    ctx.set_data(ctx_data)
125    qf_mass.set_context(ctx)
126
127    q = 8
128
129    w_array = np.zeros(q, dtype="float64")
130    u_array = np.zeros(q, dtype="float64")
131    v_true = np.zeros(q, dtype="float64")
132    for i in range(q):
133        x = 2. * i / (q - 1) - 1
134        w_array[i] = 1 - x * x
135        u_array[i] = 2 + 3 * x + 5 * x * x
136        v_true[i] = 5 * w_array[i] * u_array[i]
137
138    dx = ceed.Vector(q)
139    dx.set_value(1)
140    w = ceed.Vector(q)
141    w.set_array(w_array, cmode=libceed.USE_POINTER)
142    u = ceed.Vector(q)
143    u.set_array(u_array, cmode=libceed.USE_POINTER)
144    v = ceed.Vector(q)
145    v.set_value(0)
146    qdata = ceed.Vector(q)
147    qdata.set_value(0)
148
149    inputs = [dx, w]
150    outputs = [qdata]
151    qf_setup.apply(q, inputs, outputs)
152
153    inputs = [qdata, u]
154    outputs = [v]
155    qf_mass.apply(q, inputs, outputs)
156
157    with v.array_read() as v_array:
158        for i in range(q):
159            assert v_array[i] == v_true[i]
160
161# -------------------------------------------------------------------------------
162# Test viewing of qfunction
163# -------------------------------------------------------------------------------
164
165
166def test_402(ceed_resource, capsys):
167    ceed = libceed.Ceed(ceed_resource)
168
169    file_dir = os.path.dirname(os.path.abspath(__file__))
170    qfs = load_qfs_so()
171
172    qf_setup = ceed.QFunction(1, qfs.setup_mass,
173                              os.path.join(file_dir, "test-qfunctions.h:setup_mass"))
174    qf_setup.add_input("w", 1, libceed.EVAL_WEIGHT)
175    qf_setup.add_input("dx", 1, libceed.EVAL_GRAD)
176    qf_setup.add_output("qdata", 1, libceed.EVAL_NONE)
177
178    qf_mass = ceed.QFunction(1, qfs.apply_mass,
179                             os.path.join(file_dir, "t400-qfunction.h:apply_mass"))
180    qf_mass.add_input("qdata", 1, libceed.EVAL_NONE)
181    qf_mass.add_input("u", 1, libceed.EVAL_INTERP)
182    qf_mass.add_output("v", 1, libceed.EVAL_INTERP)
183
184    print(qf_setup)
185    print(qf_mass)
186
187    ctx_data = np.array([1., 2., 3., 4., 5.])
188    ctx = ceed.QFunctionContext()
189    ctx.set_data(ctx_data)
190    print(ctx)
191
192    stdout, stderr, ref_stdout = check.output(capsys)
193    assert not stderr
194    assert stdout == ref_stdout
195
196# -------------------------------------------------------------------------------
197# Test creation, evaluation, and destruction for qfunction by name
198# -------------------------------------------------------------------------------
199
200
201def test_410(ceed_resource):
202    ceed = libceed.Ceed(ceed_resource)
203
204    qf_setup = ceed.QFunctionByName("Mass1DBuild")
205    qf_mass = ceed.QFunctionByName("MassApply")
206
207    q = 8
208
209    j_array = np.zeros(q, dtype="float64")
210    w_array = np.zeros(q, dtype="float64")
211    u_array = np.zeros(q, dtype="float64")
212    v_true = np.zeros(q, dtype="float64")
213    for i in range(q):
214        x = 2. * i / (q - 1) - 1
215        j_array[i] = 1
216        w_array[i] = 1 - x * x
217        u_array[i] = 2 + 3 * x + 5 * x * x
218        v_true[i] = w_array[i] * u_array[i]
219
220    j = ceed.Vector(q)
221    j.set_array(j_array, cmode=libceed.USE_POINTER)
222    w = ceed.Vector(q)
223    w.set_array(w_array, cmode=libceed.USE_POINTER)
224    u = ceed.Vector(q)
225    u.set_array(u_array, cmode=libceed.USE_POINTER)
226    v = ceed.Vector(q)
227    v.set_value(0)
228    qdata = ceed.Vector(q)
229    qdata.set_value(0)
230
231    inputs = [j, w]
232    outputs = [qdata]
233    qf_setup.apply(q, inputs, outputs)
234
235    inputs = [w, u]
236    outputs = [v]
237    qf_mass.apply(q, inputs, outputs)
238
239    with v.array_read() as v_array:
240        for i in range(q):
241            assert v_array[i] == v_true[i]
242
243# -------------------------------------------------------------------------------
244# Test creation, evaluation, and destruction of identity qfunction
245# -------------------------------------------------------------------------------
246
247
248def test_411(ceed_resource):
249    ceed = libceed.Ceed(ceed_resource)
250
251    qf = ceed.IdentityQFunction(1, libceed.EVAL_INTERP, libceed.EVAL_INTERP)
252
253    q = 8
254
255    u_array = np.zeros(q, dtype="float64")
256    for i in range(q):
257        u_array[i] = i * i
258
259    u = ceed.Vector(q)
260    u.set_array(u_array, cmode=libceed.USE_POINTER)
261    v = ceed.Vector(q)
262    v.set_value(0)
263
264    inputs = [u]
265    outputs = [v]
266    qf.apply(q, inputs, outputs)
267
268    with v.array_read() as v_array:
269        for i in range(q):
270            assert v_array[i] == i * i
271
272# -------------------------------------------------------------------------------
273# Test creation, evaluation, and destruction of identity qfunction with size>1
274# -------------------------------------------------------------------------------
275
276
277def test_412(ceed_resource):
278    ceed = libceed.Ceed(ceed_resource)
279
280    size = 3
281    qf = ceed.IdentityQFunction(size, libceed.EVAL_INTERP, libceed.EVAL_INTERP)
282
283    q = 8
284
285    u_array = np.zeros(q * size, dtype="float64")
286    for i in range(q * size):
287        u_array[i] = i * i
288
289    u = ceed.Vector(q * size)
290    u.set_array(u_array, cmode=libceed.USE_POINTER)
291    v = ceed.Vector(q * size)
292    v.set_value(0)
293
294    inputs = [u]
295    outputs = [v]
296    qf.apply(q, inputs, outputs)
297
298    with v.array_read() as v_array:
299        for i in range(q * size):
300            assert v_array[i] == i * i
301
302# -------------------------------------------------------------------------------
303# Test viewing of qfunction by name
304# -------------------------------------------------------------------------------
305
306
307def test_413(ceed_resource, capsys):
308    ceed = libceed.Ceed(ceed_resource)
309
310    qf_setup = ceed.QFunctionByName("Mass1DBuild")
311    qf_mass = ceed.QFunctionByName("MassApply")
312
313    print(qf_setup)
314    print(qf_mass)
315
316    stdout, stderr, ref_stdout = check.output(capsys)
317    assert not stderr
318    assert stdout == ref_stdout
319
320# -------------------------------------------------------------------------------
321