xref: /libCEED/python/tests/test-4-qfunction.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 QFunction functionality
190ef72598Sjeremylt
200ef72598Sjeremyltimport os
210ef72598Sjeremyltimport libceed
220ef72598Sjeremyltimport numpy as np
230ef72598Sjeremyltimport check
240ef72598Sjeremylt
25*80a9ef05SNatalie BeamsTOL = libceed.EPSILON * 256
26*80a9ef05SNatalie Beams
270ef72598Sjeremylt# -------------------------------------------------------------------------------
280ef72598Sjeremylt# Utility
290ef72598Sjeremylt# -------------------------------------------------------------------------------
300ef72598Sjeremylt
310ef72598Sjeremylt
320ef72598Sjeremyltdef load_qfs_so():
330ef72598Sjeremylt    from distutils.sysconfig import get_config_var
340ef72598Sjeremylt    import ctypes
350ef72598Sjeremylt
360ef72598Sjeremylt    file_dir = os.path.dirname(os.path.abspath(__file__))
370ef72598Sjeremylt    qfs_so = os.path.join(
380ef72598Sjeremylt        file_dir,
390ef72598Sjeremylt        "libceed_qfunctions" + get_config_var("EXT_SUFFIX"))
400ef72598Sjeremylt
410ef72598Sjeremylt    # Load library
420ef72598Sjeremylt    return ctypes.cdll.LoadLibrary(qfs_so)
430ef72598Sjeremylt
440ef72598Sjeremylt# -------------------------------------------------------------------------------
450ef72598Sjeremylt# Test creation, evaluation, and destruction for qfunction
460ef72598Sjeremylt# -------------------------------------------------------------------------------
470ef72598Sjeremylt
480ef72598Sjeremylt
490ef72598Sjeremyltdef test_400(ceed_resource):
500ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
510ef72598Sjeremylt
520ef72598Sjeremylt    file_dir = os.path.dirname(os.path.abspath(__file__))
530ef72598Sjeremylt    qfs = load_qfs_so()
540ef72598Sjeremylt
550ef72598Sjeremylt    qf_setup = ceed.QFunction(1, qfs.setup_mass,
560ef72598Sjeremylt                              os.path.join(file_dir, "test-qfunctions.h:setup_mass"))
570ef72598Sjeremylt    qf_setup.add_input("w", 1, libceed.EVAL_WEIGHT)
580ef72598Sjeremylt    qf_setup.add_input("dx", 1, libceed.EVAL_GRAD)
590ef72598Sjeremylt    qf_setup.add_output("qdata", 1, libceed.EVAL_NONE)
600ef72598Sjeremylt
610ef72598Sjeremylt    qf_mass = ceed.QFunction(1, qfs.apply_mass,
620ef72598Sjeremylt                             os.path.join(file_dir, "test-qfunctions.h:apply_mass"))
630ef72598Sjeremylt    qf_mass.add_input("qdata", 1, libceed.EVAL_NONE)
640ef72598Sjeremylt    qf_mass.add_input("u", 1, libceed.EVAL_INTERP)
650ef72598Sjeremylt    qf_mass.add_output("v", 1, libceed.EVAL_INTERP)
660ef72598Sjeremylt
670ef72598Sjeremylt    q = 8
680ef72598Sjeremylt
69*80a9ef05SNatalie Beams    w_array = np.zeros(q, dtype=ceed.scalar_type())
70*80a9ef05SNatalie Beams    u_array = np.zeros(q, dtype=ceed.scalar_type())
71*80a9ef05SNatalie Beams    v_true = np.zeros(q, dtype=ceed.scalar_type())
720ef72598Sjeremylt    for i in range(q):
730ef72598Sjeremylt        x = 2. * i / (q - 1) - 1
740ef72598Sjeremylt        w_array[i] = 1 - x * x
750ef72598Sjeremylt        u_array[i] = 2 + 3 * x + 5 * x * x
760ef72598Sjeremylt        v_true[i] = w_array[i] * u_array[i]
770ef72598Sjeremylt
780ef72598Sjeremylt    dx = ceed.Vector(q)
790ef72598Sjeremylt    dx.set_value(1)
800ef72598Sjeremylt    w = ceed.Vector(q)
810ef72598Sjeremylt    w.set_array(w_array, cmode=libceed.USE_POINTER)
820ef72598Sjeremylt    u = ceed.Vector(q)
830ef72598Sjeremylt    u.set_array(u_array, cmode=libceed.USE_POINTER)
840ef72598Sjeremylt    v = ceed.Vector(q)
850ef72598Sjeremylt    v.set_value(0)
860ef72598Sjeremylt    qdata = ceed.Vector(q)
870ef72598Sjeremylt    qdata.set_value(0)
880ef72598Sjeremylt
890ef72598Sjeremylt    inputs = [dx, w]
900ef72598Sjeremylt    outputs = [qdata]
910ef72598Sjeremylt    qf_setup.apply(q, inputs, outputs)
920ef72598Sjeremylt
930ef72598Sjeremylt    inputs = [qdata, u]
940ef72598Sjeremylt    outputs = [v]
950ef72598Sjeremylt    qf_mass.apply(q, inputs, outputs)
960ef72598Sjeremylt
970ef72598Sjeremylt    with v.array_read() as v_array:
980ef72598Sjeremylt        for i in range(q):
990ef72598Sjeremylt            assert v_array[i] == v_true[i]
1000ef72598Sjeremylt
1010ef72598Sjeremylt# -------------------------------------------------------------------------------
1020ef72598Sjeremylt# Test creation, evaluation, and destruction for qfunction
1030ef72598Sjeremylt# -------------------------------------------------------------------------------
1040ef72598Sjeremylt
1050ef72598Sjeremylt
1060ef72598Sjeremyltdef test_401(ceed_resource):
1070ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1080ef72598Sjeremylt
1090ef72598Sjeremylt    file_dir = os.path.dirname(os.path.abspath(__file__))
1100ef72598Sjeremylt    qfs = load_qfs_so()
1110ef72598Sjeremylt
1120ef72598Sjeremylt    qf_setup = ceed.QFunction(1, qfs.setup_mass,
1130ef72598Sjeremylt                              os.path.join(file_dir, "test-qfunctions.h:setup_mass"))
1140ef72598Sjeremylt    qf_setup.add_input("w", 1, libceed.EVAL_WEIGHT)
1150ef72598Sjeremylt    qf_setup.add_input("dx", 1, libceed.EVAL_GRAD)
1160ef72598Sjeremylt    qf_setup.add_output("qdata", 1, libceed.EVAL_NONE)
1170ef72598Sjeremylt
1180ef72598Sjeremylt    qf_mass = ceed.QFunction(1, qfs.apply_mass,
119*80a9ef05SNatalie Beams                             os.path.join(file_dir, "test-qfunctions.h:apply_mass"))
1200ef72598Sjeremylt    qf_mass.add_input("qdata", 1, libceed.EVAL_NONE)
1210ef72598Sjeremylt    qf_mass.add_input("u", 1, libceed.EVAL_INTERP)
1220ef72598Sjeremylt    qf_mass.add_output("v", 1, libceed.EVAL_INTERP)
1230ef72598Sjeremylt
124*80a9ef05SNatalie Beams    ctx_data = np.array([1., 2., 3., 4., 5.], dtype=ceed.scalar_type())
1250ef72598Sjeremylt    ctx = ceed.QFunctionContext()
1260ef72598Sjeremylt    ctx.set_data(ctx_data)
1270ef72598Sjeremylt    qf_mass.set_context(ctx)
1280ef72598Sjeremylt
1290ef72598Sjeremylt    q = 8
1300ef72598Sjeremylt
131*80a9ef05SNatalie Beams    w_array = np.zeros(q, dtype=ceed.scalar_type())
132*80a9ef05SNatalie Beams    u_array = np.zeros(q, dtype=ceed.scalar_type())
133*80a9ef05SNatalie Beams    v_true = np.zeros(q, dtype=ceed.scalar_type())
1340ef72598Sjeremylt    for i in range(q):
1350ef72598Sjeremylt        x = 2. * i / (q - 1) - 1
1360ef72598Sjeremylt        w_array[i] = 1 - x * x
1370ef72598Sjeremylt        u_array[i] = 2 + 3 * x + 5 * x * x
1380ef72598Sjeremylt        v_true[i] = 5 * w_array[i] * u_array[i]
1390ef72598Sjeremylt
1400ef72598Sjeremylt    dx = ceed.Vector(q)
1410ef72598Sjeremylt    dx.set_value(1)
1420ef72598Sjeremylt    w = ceed.Vector(q)
1430ef72598Sjeremylt    w.set_array(w_array, cmode=libceed.USE_POINTER)
1440ef72598Sjeremylt    u = ceed.Vector(q)
1450ef72598Sjeremylt    u.set_array(u_array, cmode=libceed.USE_POINTER)
1460ef72598Sjeremylt    v = ceed.Vector(q)
1470ef72598Sjeremylt    v.set_value(0)
1480ef72598Sjeremylt    qdata = ceed.Vector(q)
1490ef72598Sjeremylt    qdata.set_value(0)
1500ef72598Sjeremylt
1510ef72598Sjeremylt    inputs = [dx, w]
1520ef72598Sjeremylt    outputs = [qdata]
1530ef72598Sjeremylt    qf_setup.apply(q, inputs, outputs)
1540ef72598Sjeremylt
1550ef72598Sjeremylt    inputs = [qdata, u]
1560ef72598Sjeremylt    outputs = [v]
1570ef72598Sjeremylt    qf_mass.apply(q, inputs, outputs)
1580ef72598Sjeremylt
1590ef72598Sjeremylt    with v.array_read() as v_array:
1600ef72598Sjeremylt        for i in range(q):
161*80a9ef05SNatalie Beams            assert abs(v_array[i] - v_true[i]) < TOL
1620ef72598Sjeremylt
1630ef72598Sjeremylt# -------------------------------------------------------------------------------
1640ef72598Sjeremylt# Test viewing of qfunction
1650ef72598Sjeremylt# -------------------------------------------------------------------------------
1660ef72598Sjeremylt
1670ef72598Sjeremylt
1680ef72598Sjeremyltdef test_402(ceed_resource, capsys):
1690ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1700ef72598Sjeremylt
1710ef72598Sjeremylt    file_dir = os.path.dirname(os.path.abspath(__file__))
1720ef72598Sjeremylt    qfs = load_qfs_so()
1730ef72598Sjeremylt
1740ef72598Sjeremylt    qf_setup = ceed.QFunction(1, qfs.setup_mass,
1750ef72598Sjeremylt                              os.path.join(file_dir, "test-qfunctions.h:setup_mass"))
1760ef72598Sjeremylt    qf_setup.add_input("w", 1, libceed.EVAL_WEIGHT)
1770ef72598Sjeremylt    qf_setup.add_input("dx", 1, libceed.EVAL_GRAD)
1780ef72598Sjeremylt    qf_setup.add_output("qdata", 1, libceed.EVAL_NONE)
1790ef72598Sjeremylt
1800ef72598Sjeremylt    qf_mass = ceed.QFunction(1, qfs.apply_mass,
181*80a9ef05SNatalie Beams                             os.path.join(file_dir, "test-qfunctions.h:apply_mass"))
1820ef72598Sjeremylt    qf_mass.add_input("qdata", 1, libceed.EVAL_NONE)
1830ef72598Sjeremylt    qf_mass.add_input("u", 1, libceed.EVAL_INTERP)
1840ef72598Sjeremylt    qf_mass.add_output("v", 1, libceed.EVAL_INTERP)
1850ef72598Sjeremylt
1860ef72598Sjeremylt    print(qf_setup)
1870ef72598Sjeremylt    print(qf_mass)
1880ef72598Sjeremylt
189*80a9ef05SNatalie Beams    if libceed.lib.CEED_SCALAR_TYPE == libceed.SCALAR_FP64:
190*80a9ef05SNatalie Beams        ctx_data = np.array([1., 2., 3., 4., 5.], dtype="float64")
191*80a9ef05SNatalie Beams    # Make ctx twice as long in fp32, so size will be the same as fp64 output
192*80a9ef05SNatalie Beams    else:
193*80a9ef05SNatalie Beams        ctx_data = np.array([1., 2., 3., 4., 5., 1., 2., 3., 4., 5.],
194*80a9ef05SNatalie Beams                            dtype="float32")
1950ef72598Sjeremylt    ctx = ceed.QFunctionContext()
1960ef72598Sjeremylt    ctx.set_data(ctx_data)
1970ef72598Sjeremylt    print(ctx)
1980ef72598Sjeremylt
1990ef72598Sjeremylt    stdout, stderr, ref_stdout = check.output(capsys)
2000ef72598Sjeremylt    assert not stderr
2010ef72598Sjeremylt    assert stdout == ref_stdout
2020ef72598Sjeremylt
2030ef72598Sjeremylt# -------------------------------------------------------------------------------
2040ef72598Sjeremylt# Test creation, evaluation, and destruction for qfunction by name
2050ef72598Sjeremylt# -------------------------------------------------------------------------------
2060ef72598Sjeremylt
2070ef72598Sjeremylt
2080ef72598Sjeremyltdef test_410(ceed_resource):
2090ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2100ef72598Sjeremylt
2110ef72598Sjeremylt    qf_setup = ceed.QFunctionByName("Mass1DBuild")
2120ef72598Sjeremylt    qf_mass = ceed.QFunctionByName("MassApply")
2130ef72598Sjeremylt
2140ef72598Sjeremylt    q = 8
2150ef72598Sjeremylt
216*80a9ef05SNatalie Beams    j_array = np.zeros(q, dtype=ceed.scalar_type())
217*80a9ef05SNatalie Beams    w_array = np.zeros(q, dtype=ceed.scalar_type())
218*80a9ef05SNatalie Beams    u_array = np.zeros(q, dtype=ceed.scalar_type())
219*80a9ef05SNatalie Beams    v_true = np.zeros(q, dtype=ceed.scalar_type())
2200ef72598Sjeremylt    for i in range(q):
2210ef72598Sjeremylt        x = 2. * i / (q - 1) - 1
2220ef72598Sjeremylt        j_array[i] = 1
2230ef72598Sjeremylt        w_array[i] = 1 - x * x
2240ef72598Sjeremylt        u_array[i] = 2 + 3 * x + 5 * x * x
2250ef72598Sjeremylt        v_true[i] = w_array[i] * u_array[i]
2260ef72598Sjeremylt
2270ef72598Sjeremylt    j = ceed.Vector(q)
2280ef72598Sjeremylt    j.set_array(j_array, cmode=libceed.USE_POINTER)
2290ef72598Sjeremylt    w = ceed.Vector(q)
2300ef72598Sjeremylt    w.set_array(w_array, cmode=libceed.USE_POINTER)
2310ef72598Sjeremylt    u = ceed.Vector(q)
2320ef72598Sjeremylt    u.set_array(u_array, cmode=libceed.USE_POINTER)
2330ef72598Sjeremylt    v = ceed.Vector(q)
2340ef72598Sjeremylt    v.set_value(0)
2350ef72598Sjeremylt    qdata = ceed.Vector(q)
2360ef72598Sjeremylt    qdata.set_value(0)
2370ef72598Sjeremylt
2380ef72598Sjeremylt    inputs = [j, w]
2390ef72598Sjeremylt    outputs = [qdata]
2400ef72598Sjeremylt    qf_setup.apply(q, inputs, outputs)
2410ef72598Sjeremylt
2420ef72598Sjeremylt    inputs = [w, u]
2430ef72598Sjeremylt    outputs = [v]
2440ef72598Sjeremylt    qf_mass.apply(q, inputs, outputs)
2450ef72598Sjeremylt
2460ef72598Sjeremylt    with v.array_read() as v_array:
2470ef72598Sjeremylt        for i in range(q):
2480ef72598Sjeremylt            assert v_array[i] == v_true[i]
2490ef72598Sjeremylt
2500ef72598Sjeremylt# -------------------------------------------------------------------------------
2510ef72598Sjeremylt# Test creation, evaluation, and destruction of identity qfunction
2520ef72598Sjeremylt# -------------------------------------------------------------------------------
2530ef72598Sjeremylt
2540ef72598Sjeremylt
2550ef72598Sjeremyltdef test_411(ceed_resource):
2560ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2570ef72598Sjeremylt
2580ef72598Sjeremylt    qf = ceed.IdentityQFunction(1, libceed.EVAL_INTERP, libceed.EVAL_INTERP)
2590ef72598Sjeremylt
2600ef72598Sjeremylt    q = 8
2610ef72598Sjeremylt
262*80a9ef05SNatalie Beams    u_array = np.zeros(q, dtype=ceed.scalar_type())
2630ef72598Sjeremylt    for i in range(q):
2640ef72598Sjeremylt        u_array[i] = i * i
2650ef72598Sjeremylt
2660ef72598Sjeremylt    u = ceed.Vector(q)
2670ef72598Sjeremylt    u.set_array(u_array, cmode=libceed.USE_POINTER)
2680ef72598Sjeremylt    v = ceed.Vector(q)
2690ef72598Sjeremylt    v.set_value(0)
2700ef72598Sjeremylt
2710ef72598Sjeremylt    inputs = [u]
2720ef72598Sjeremylt    outputs = [v]
2730ef72598Sjeremylt    qf.apply(q, inputs, outputs)
2740ef72598Sjeremylt
2750ef72598Sjeremylt    with v.array_read() as v_array:
2760ef72598Sjeremylt        for i in range(q):
2770ef72598Sjeremylt            assert v_array[i] == i * i
2780ef72598Sjeremylt
2790ef72598Sjeremylt# -------------------------------------------------------------------------------
2800ef72598Sjeremylt# Test creation, evaluation, and destruction of identity qfunction with size>1
2810ef72598Sjeremylt# -------------------------------------------------------------------------------
2820ef72598Sjeremylt
2830ef72598Sjeremylt
2840ef72598Sjeremyltdef test_412(ceed_resource):
2850ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2860ef72598Sjeremylt
2870ef72598Sjeremylt    size = 3
2880ef72598Sjeremylt    qf = ceed.IdentityQFunction(size, libceed.EVAL_INTERP, libceed.EVAL_INTERP)
2890ef72598Sjeremylt
2900ef72598Sjeremylt    q = 8
2910ef72598Sjeremylt
292*80a9ef05SNatalie Beams    u_array = np.zeros(q * size, dtype=ceed.scalar_type())
2930ef72598Sjeremylt    for i in range(q * size):
2940ef72598Sjeremylt        u_array[i] = i * i
2950ef72598Sjeremylt
2960ef72598Sjeremylt    u = ceed.Vector(q * size)
2970ef72598Sjeremylt    u.set_array(u_array, cmode=libceed.USE_POINTER)
2980ef72598Sjeremylt    v = ceed.Vector(q * size)
2990ef72598Sjeremylt    v.set_value(0)
3000ef72598Sjeremylt
3010ef72598Sjeremylt    inputs = [u]
3020ef72598Sjeremylt    outputs = [v]
3030ef72598Sjeremylt    qf.apply(q, inputs, outputs)
3040ef72598Sjeremylt
3050ef72598Sjeremylt    with v.array_read() as v_array:
3060ef72598Sjeremylt        for i in range(q * size):
3070ef72598Sjeremylt            assert v_array[i] == i * i
3080ef72598Sjeremylt
3090ef72598Sjeremylt# -------------------------------------------------------------------------------
3100ef72598Sjeremylt# Test viewing of qfunction by name
3110ef72598Sjeremylt# -------------------------------------------------------------------------------
3120ef72598Sjeremylt
3130ef72598Sjeremylt
3140ef72598Sjeremyltdef test_413(ceed_resource, capsys):
3150ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
3160ef72598Sjeremylt
3170ef72598Sjeremylt    qf_setup = ceed.QFunctionByName("Mass1DBuild")
3180ef72598Sjeremylt    qf_mass = ceed.QFunctionByName("MassApply")
3190ef72598Sjeremylt
3200ef72598Sjeremylt    print(qf_setup)
3210ef72598Sjeremylt    print(qf_mass)
3220ef72598Sjeremylt
3230ef72598Sjeremylt    stdout, stderr, ref_stdout = check.output(capsys)
3240ef72598Sjeremylt    assert not stderr
3250ef72598Sjeremylt    assert stdout == ref_stdout
3260ef72598Sjeremylt
3270ef72598Sjeremylt# -------------------------------------------------------------------------------
328