xref: /libCEED/python/tests/test-4-qfunction.py (revision 1f401ad2c3fc99c5f846a3f1e8046086243879e6)
13d8e8822SJeremy L Thompson# Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors
23d8e8822SJeremy L Thompson# All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
30ef72598Sjeremylt#
43d8e8822SJeremy L Thompson# SPDX-License-Identifier: BSD-2-Clause
50ef72598Sjeremylt#
63d8e8822SJeremy L Thompson# This file is part of CEED:  http://github.com/ceed
70ef72598Sjeremylt
80ef72598Sjeremylt# @file
90ef72598Sjeremylt# Test Ceed QFunction functionality
100ef72598Sjeremylt
110ef72598Sjeremyltimport os
120ef72598Sjeremyltimport libceed
130ef72598Sjeremyltimport numpy as np
140ef72598Sjeremyltimport check
150ef72598Sjeremylt
1680a9ef05SNatalie BeamsTOL = libceed.EPSILON * 256
1780a9ef05SNatalie Beams
180ef72598Sjeremylt# -------------------------------------------------------------------------------
190ef72598Sjeremylt# Utility
200ef72598Sjeremylt# -------------------------------------------------------------------------------
210ef72598Sjeremylt
220ef72598Sjeremylt
230ef72598Sjeremyltdef load_qfs_so():
24*1f401ad2SJeremy L Thompson    from sysconfig import get_config_var
250ef72598Sjeremylt    import ctypes
260ef72598Sjeremylt
270ef72598Sjeremylt    file_dir = os.path.dirname(os.path.abspath(__file__))
280ef72598Sjeremylt    qfs_so = os.path.join(
290ef72598Sjeremylt        file_dir,
300ef72598Sjeremylt        "libceed_qfunctions" + get_config_var("EXT_SUFFIX"))
310ef72598Sjeremylt
320ef72598Sjeremylt    # Load library
330ef72598Sjeremylt    return ctypes.cdll.LoadLibrary(qfs_so)
340ef72598Sjeremylt
350ef72598Sjeremylt# -------------------------------------------------------------------------------
360ef72598Sjeremylt# Test creation, evaluation, and destruction for qfunction
370ef72598Sjeremylt# -------------------------------------------------------------------------------
380ef72598Sjeremylt
390ef72598Sjeremylt
400ef72598Sjeremyltdef test_400(ceed_resource):
410ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
420ef72598Sjeremylt
430ef72598Sjeremylt    file_dir = os.path.dirname(os.path.abspath(__file__))
440ef72598Sjeremylt    qfs = load_qfs_so()
450ef72598Sjeremylt
460ef72598Sjeremylt    qf_setup = ceed.QFunction(1, qfs.setup_mass,
470ef72598Sjeremylt                              os.path.join(file_dir, "test-qfunctions.h:setup_mass"))
480ef72598Sjeremylt    qf_setup.add_input("w", 1, libceed.EVAL_WEIGHT)
490ef72598Sjeremylt    qf_setup.add_input("dx", 1, libceed.EVAL_GRAD)
500ef72598Sjeremylt    qf_setup.add_output("qdata", 1, libceed.EVAL_NONE)
510ef72598Sjeremylt
520ef72598Sjeremylt    qf_mass = ceed.QFunction(1, qfs.apply_mass,
530ef72598Sjeremylt                             os.path.join(file_dir, "test-qfunctions.h:apply_mass"))
540ef72598Sjeremylt    qf_mass.add_input("qdata", 1, libceed.EVAL_NONE)
550ef72598Sjeremylt    qf_mass.add_input("u", 1, libceed.EVAL_INTERP)
560ef72598Sjeremylt    qf_mass.add_output("v", 1, libceed.EVAL_INTERP)
570ef72598Sjeremylt
580ef72598Sjeremylt    q = 8
590ef72598Sjeremylt
6080a9ef05SNatalie Beams    w_array = np.zeros(q, dtype=ceed.scalar_type())
6180a9ef05SNatalie Beams    u_array = np.zeros(q, dtype=ceed.scalar_type())
6280a9ef05SNatalie Beams    v_true = np.zeros(q, dtype=ceed.scalar_type())
630ef72598Sjeremylt    for i in range(q):
640ef72598Sjeremylt        x = 2. * i / (q - 1) - 1
650ef72598Sjeremylt        w_array[i] = 1 - x * x
660ef72598Sjeremylt        u_array[i] = 2 + 3 * x + 5 * x * x
670ef72598Sjeremylt        v_true[i] = w_array[i] * u_array[i]
680ef72598Sjeremylt
690ef72598Sjeremylt    dx = ceed.Vector(q)
700ef72598Sjeremylt    dx.set_value(1)
710ef72598Sjeremylt    w = ceed.Vector(q)
720ef72598Sjeremylt    w.set_array(w_array, cmode=libceed.USE_POINTER)
730ef72598Sjeremylt    u = ceed.Vector(q)
740ef72598Sjeremylt    u.set_array(u_array, cmode=libceed.USE_POINTER)
750ef72598Sjeremylt    v = ceed.Vector(q)
760ef72598Sjeremylt    v.set_value(0)
770ef72598Sjeremylt    qdata = ceed.Vector(q)
780ef72598Sjeremylt    qdata.set_value(0)
790ef72598Sjeremylt
800ef72598Sjeremylt    inputs = [dx, w]
810ef72598Sjeremylt    outputs = [qdata]
820ef72598Sjeremylt    qf_setup.apply(q, inputs, outputs)
830ef72598Sjeremylt
840ef72598Sjeremylt    inputs = [qdata, u]
850ef72598Sjeremylt    outputs = [v]
860ef72598Sjeremylt    qf_mass.apply(q, inputs, outputs)
870ef72598Sjeremylt
880ef72598Sjeremylt    with v.array_read() as v_array:
890ef72598Sjeremylt        for i in range(q):
900ef72598Sjeremylt            assert v_array[i] == v_true[i]
910ef72598Sjeremylt
920ef72598Sjeremylt# -------------------------------------------------------------------------------
930ef72598Sjeremylt# Test creation, evaluation, and destruction for qfunction
940ef72598Sjeremylt# -------------------------------------------------------------------------------
950ef72598Sjeremylt
960ef72598Sjeremylt
970ef72598Sjeremyltdef test_401(ceed_resource):
980ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
990ef72598Sjeremylt
1000ef72598Sjeremylt    file_dir = os.path.dirname(os.path.abspath(__file__))
1010ef72598Sjeremylt    qfs = load_qfs_so()
1020ef72598Sjeremylt
1030ef72598Sjeremylt    qf_setup = ceed.QFunction(1, qfs.setup_mass,
1040ef72598Sjeremylt                              os.path.join(file_dir, "test-qfunctions.h:setup_mass"))
1050ef72598Sjeremylt    qf_setup.add_input("w", 1, libceed.EVAL_WEIGHT)
1060ef72598Sjeremylt    qf_setup.add_input("dx", 1, libceed.EVAL_GRAD)
1070ef72598Sjeremylt    qf_setup.add_output("qdata", 1, libceed.EVAL_NONE)
1080ef72598Sjeremylt
1090ef72598Sjeremylt    qf_mass = ceed.QFunction(1, qfs.apply_mass,
11080a9ef05SNatalie Beams                             os.path.join(file_dir, "test-qfunctions.h:apply_mass"))
1110ef72598Sjeremylt    qf_mass.add_input("qdata", 1, libceed.EVAL_NONE)
1120ef72598Sjeremylt    qf_mass.add_input("u", 1, libceed.EVAL_INTERP)
1130ef72598Sjeremylt    qf_mass.add_output("v", 1, libceed.EVAL_INTERP)
1140ef72598Sjeremylt
11580a9ef05SNatalie Beams    ctx_data = np.array([1., 2., 3., 4., 5.], dtype=ceed.scalar_type())
1160ef72598Sjeremylt    ctx = ceed.QFunctionContext()
1170ef72598Sjeremylt    ctx.set_data(ctx_data)
1180ef72598Sjeremylt    qf_mass.set_context(ctx)
1190ef72598Sjeremylt
1200ef72598Sjeremylt    q = 8
1210ef72598Sjeremylt
12280a9ef05SNatalie Beams    w_array = np.zeros(q, dtype=ceed.scalar_type())
12380a9ef05SNatalie Beams    u_array = np.zeros(q, dtype=ceed.scalar_type())
12480a9ef05SNatalie Beams    v_true = np.zeros(q, dtype=ceed.scalar_type())
1250ef72598Sjeremylt    for i in range(q):
1260ef72598Sjeremylt        x = 2. * i / (q - 1) - 1
1270ef72598Sjeremylt        w_array[i] = 1 - x * x
1280ef72598Sjeremylt        u_array[i] = 2 + 3 * x + 5 * x * x
1290ef72598Sjeremylt        v_true[i] = 5 * w_array[i] * u_array[i]
1300ef72598Sjeremylt
1310ef72598Sjeremylt    dx = ceed.Vector(q)
1320ef72598Sjeremylt    dx.set_value(1)
1330ef72598Sjeremylt    w = ceed.Vector(q)
1340ef72598Sjeremylt    w.set_array(w_array, cmode=libceed.USE_POINTER)
1350ef72598Sjeremylt    u = ceed.Vector(q)
1360ef72598Sjeremylt    u.set_array(u_array, cmode=libceed.USE_POINTER)
1370ef72598Sjeremylt    v = ceed.Vector(q)
1380ef72598Sjeremylt    v.set_value(0)
1390ef72598Sjeremylt    qdata = ceed.Vector(q)
1400ef72598Sjeremylt    qdata.set_value(0)
1410ef72598Sjeremylt
1420ef72598Sjeremylt    inputs = [dx, w]
1430ef72598Sjeremylt    outputs = [qdata]
1440ef72598Sjeremylt    qf_setup.apply(q, inputs, outputs)
1450ef72598Sjeremylt
1460ef72598Sjeremylt    inputs = [qdata, u]
1470ef72598Sjeremylt    outputs = [v]
1480ef72598Sjeremylt    qf_mass.apply(q, inputs, outputs)
1490ef72598Sjeremylt
1500ef72598Sjeremylt    with v.array_read() as v_array:
1510ef72598Sjeremylt        for i in range(q):
15280a9ef05SNatalie Beams            assert abs(v_array[i] - v_true[i]) < TOL
1530ef72598Sjeremylt
1540ef72598Sjeremylt# -------------------------------------------------------------------------------
1550ef72598Sjeremylt# Test viewing of qfunction
1560ef72598Sjeremylt# -------------------------------------------------------------------------------
1570ef72598Sjeremylt
1580ef72598Sjeremylt
1590ef72598Sjeremyltdef test_402(ceed_resource, capsys):
1600ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
1610ef72598Sjeremylt
1620ef72598Sjeremylt    file_dir = os.path.dirname(os.path.abspath(__file__))
1630ef72598Sjeremylt    qfs = load_qfs_so()
1640ef72598Sjeremylt
1650ef72598Sjeremylt    qf_setup = ceed.QFunction(1, qfs.setup_mass,
1660ef72598Sjeremylt                              os.path.join(file_dir, "test-qfunctions.h:setup_mass"))
1670ef72598Sjeremylt    qf_setup.add_input("w", 1, libceed.EVAL_WEIGHT)
1680ef72598Sjeremylt    qf_setup.add_input("dx", 1, libceed.EVAL_GRAD)
1690ef72598Sjeremylt    qf_setup.add_output("qdata", 1, libceed.EVAL_NONE)
1700ef72598Sjeremylt
1710ef72598Sjeremylt    qf_mass = ceed.QFunction(1, qfs.apply_mass,
17280a9ef05SNatalie Beams                             os.path.join(file_dir, "test-qfunctions.h:apply_mass"))
1730ef72598Sjeremylt    qf_mass.add_input("qdata", 1, libceed.EVAL_NONE)
1740ef72598Sjeremylt    qf_mass.add_input("u", 1, libceed.EVAL_INTERP)
1750ef72598Sjeremylt    qf_mass.add_output("v", 1, libceed.EVAL_INTERP)
1760ef72598Sjeremylt
1770ef72598Sjeremylt    print(qf_setup)
1780ef72598Sjeremylt    print(qf_mass)
1790ef72598Sjeremylt
18080a9ef05SNatalie Beams    if libceed.lib.CEED_SCALAR_TYPE == libceed.SCALAR_FP64:
18180a9ef05SNatalie Beams        ctx_data = np.array([1., 2., 3., 4., 5.], dtype="float64")
18280a9ef05SNatalie Beams    # Make ctx twice as long in fp32, so size will be the same as fp64 output
18380a9ef05SNatalie Beams    else:
18480a9ef05SNatalie Beams        ctx_data = np.array([1., 2., 3., 4., 5., 1., 2., 3., 4., 5.],
18580a9ef05SNatalie Beams                            dtype="float32")
1860ef72598Sjeremylt    ctx = ceed.QFunctionContext()
1870ef72598Sjeremylt    ctx.set_data(ctx_data)
1880ef72598Sjeremylt    print(ctx)
1890ef72598Sjeremylt
1900ef72598Sjeremylt    stdout, stderr, ref_stdout = check.output(capsys)
1910ef72598Sjeremylt    assert not stderr
1920ef72598Sjeremylt    assert stdout == ref_stdout
1930ef72598Sjeremylt
1940ef72598Sjeremylt# -------------------------------------------------------------------------------
1950ef72598Sjeremylt# Test creation, evaluation, and destruction for qfunction by name
1960ef72598Sjeremylt# -------------------------------------------------------------------------------
1970ef72598Sjeremylt
1980ef72598Sjeremylt
1990ef72598Sjeremyltdef test_410(ceed_resource):
2000ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2010ef72598Sjeremylt
2020ef72598Sjeremylt    qf_setup = ceed.QFunctionByName("Mass1DBuild")
2030ef72598Sjeremylt    qf_mass = ceed.QFunctionByName("MassApply")
2040ef72598Sjeremylt
2050ef72598Sjeremylt    q = 8
2060ef72598Sjeremylt
20780a9ef05SNatalie Beams    j_array = np.zeros(q, dtype=ceed.scalar_type())
20880a9ef05SNatalie Beams    w_array = np.zeros(q, dtype=ceed.scalar_type())
20980a9ef05SNatalie Beams    u_array = np.zeros(q, dtype=ceed.scalar_type())
21080a9ef05SNatalie Beams    v_true = np.zeros(q, dtype=ceed.scalar_type())
2110ef72598Sjeremylt    for i in range(q):
2120ef72598Sjeremylt        x = 2. * i / (q - 1) - 1
2130ef72598Sjeremylt        j_array[i] = 1
2140ef72598Sjeremylt        w_array[i] = 1 - x * x
2150ef72598Sjeremylt        u_array[i] = 2 + 3 * x + 5 * x * x
2160ef72598Sjeremylt        v_true[i] = w_array[i] * u_array[i]
2170ef72598Sjeremylt
2180ef72598Sjeremylt    j = ceed.Vector(q)
2190ef72598Sjeremylt    j.set_array(j_array, cmode=libceed.USE_POINTER)
2200ef72598Sjeremylt    w = ceed.Vector(q)
2210ef72598Sjeremylt    w.set_array(w_array, cmode=libceed.USE_POINTER)
2220ef72598Sjeremylt    u = ceed.Vector(q)
2230ef72598Sjeremylt    u.set_array(u_array, cmode=libceed.USE_POINTER)
2240ef72598Sjeremylt    v = ceed.Vector(q)
2250ef72598Sjeremylt    v.set_value(0)
2260ef72598Sjeremylt    qdata = ceed.Vector(q)
2270ef72598Sjeremylt    qdata.set_value(0)
2280ef72598Sjeremylt
2290ef72598Sjeremylt    inputs = [j, w]
2300ef72598Sjeremylt    outputs = [qdata]
2310ef72598Sjeremylt    qf_setup.apply(q, inputs, outputs)
2320ef72598Sjeremylt
2330ef72598Sjeremylt    inputs = [w, u]
2340ef72598Sjeremylt    outputs = [v]
2350ef72598Sjeremylt    qf_mass.apply(q, inputs, outputs)
2360ef72598Sjeremylt
2370ef72598Sjeremylt    with v.array_read() as v_array:
2380ef72598Sjeremylt        for i in range(q):
2390ef72598Sjeremylt            assert v_array[i] == v_true[i]
2400ef72598Sjeremylt
2410ef72598Sjeremylt# -------------------------------------------------------------------------------
2420ef72598Sjeremylt# Test creation, evaluation, and destruction of identity qfunction
2430ef72598Sjeremylt# -------------------------------------------------------------------------------
2440ef72598Sjeremylt
2450ef72598Sjeremylt
2460ef72598Sjeremyltdef test_411(ceed_resource):
2470ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2480ef72598Sjeremylt
2490ef72598Sjeremylt    qf = ceed.IdentityQFunction(1, libceed.EVAL_INTERP, libceed.EVAL_INTERP)
2500ef72598Sjeremylt
2510ef72598Sjeremylt    q = 8
2520ef72598Sjeremylt
25380a9ef05SNatalie Beams    u_array = np.zeros(q, dtype=ceed.scalar_type())
2540ef72598Sjeremylt    for i in range(q):
2550ef72598Sjeremylt        u_array[i] = i * i
2560ef72598Sjeremylt
2570ef72598Sjeremylt    u = ceed.Vector(q)
2580ef72598Sjeremylt    u.set_array(u_array, cmode=libceed.USE_POINTER)
2590ef72598Sjeremylt    v = ceed.Vector(q)
2600ef72598Sjeremylt    v.set_value(0)
2610ef72598Sjeremylt
2620ef72598Sjeremylt    inputs = [u]
2630ef72598Sjeremylt    outputs = [v]
2640ef72598Sjeremylt    qf.apply(q, inputs, outputs)
2650ef72598Sjeremylt
2660ef72598Sjeremylt    with v.array_read() as v_array:
2670ef72598Sjeremylt        for i in range(q):
2680ef72598Sjeremylt            assert v_array[i] == i * i
2690ef72598Sjeremylt
2700ef72598Sjeremylt# -------------------------------------------------------------------------------
2710ef72598Sjeremylt# Test creation, evaluation, and destruction of identity qfunction with size>1
2720ef72598Sjeremylt# -------------------------------------------------------------------------------
2730ef72598Sjeremylt
2740ef72598Sjeremylt
2750ef72598Sjeremyltdef test_412(ceed_resource):
2760ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
2770ef72598Sjeremylt
2780ef72598Sjeremylt    size = 3
2790ef72598Sjeremylt    qf = ceed.IdentityQFunction(size, libceed.EVAL_INTERP, libceed.EVAL_INTERP)
2800ef72598Sjeremylt
2810ef72598Sjeremylt    q = 8
2820ef72598Sjeremylt
28380a9ef05SNatalie Beams    u_array = np.zeros(q * size, dtype=ceed.scalar_type())
2840ef72598Sjeremylt    for i in range(q * size):
2850ef72598Sjeremylt        u_array[i] = i * i
2860ef72598Sjeremylt
2870ef72598Sjeremylt    u = ceed.Vector(q * size)
2880ef72598Sjeremylt    u.set_array(u_array, cmode=libceed.USE_POINTER)
2890ef72598Sjeremylt    v = ceed.Vector(q * size)
2900ef72598Sjeremylt    v.set_value(0)
2910ef72598Sjeremylt
2920ef72598Sjeremylt    inputs = [u]
2930ef72598Sjeremylt    outputs = [v]
2940ef72598Sjeremylt    qf.apply(q, inputs, outputs)
2950ef72598Sjeremylt
2960ef72598Sjeremylt    with v.array_read() as v_array:
2970ef72598Sjeremylt        for i in range(q * size):
2980ef72598Sjeremylt            assert v_array[i] == i * i
2990ef72598Sjeremylt
3000ef72598Sjeremylt# -------------------------------------------------------------------------------
3010ef72598Sjeremylt# Test viewing of qfunction by name
3020ef72598Sjeremylt# -------------------------------------------------------------------------------
3030ef72598Sjeremylt
3040ef72598Sjeremylt
3050ef72598Sjeremyltdef test_413(ceed_resource, capsys):
3060ef72598Sjeremylt    ceed = libceed.Ceed(ceed_resource)
3070ef72598Sjeremylt
3080ef72598Sjeremylt    qf_setup = ceed.QFunctionByName("Mass1DBuild")
3090ef72598Sjeremylt    qf_mass = ceed.QFunctionByName("MassApply")
3100ef72598Sjeremylt
3110ef72598Sjeremylt    print(qf_setup)
3120ef72598Sjeremylt    print(qf_mass)
3130ef72598Sjeremylt
3140ef72598Sjeremylt    stdout, stderr, ref_stdout = check.output(capsys)
3150ef72598Sjeremylt    assert not stderr
3160ef72598Sjeremylt    assert stdout == ref_stdout
3170ef72598Sjeremylt
3180ef72598Sjeremylt# -------------------------------------------------------------------------------
319