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