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 25TOL = libceed.EPSILON * 256 26 27# ------------------------------------------------------------------------------- 28# Utility 29# ------------------------------------------------------------------------------- 30 31 32def load_qfs_so(): 33 from distutils.sysconfig import get_config_var 34 import ctypes 35 36 file_dir = os.path.dirname(os.path.abspath(__file__)) 37 qfs_so = os.path.join( 38 file_dir, 39 "libceed_qfunctions" + get_config_var("EXT_SUFFIX")) 40 41 # Load library 42 return ctypes.cdll.LoadLibrary(qfs_so) 43 44# ------------------------------------------------------------------------------- 45# Test creation, evaluation, and destruction for qfunction 46# ------------------------------------------------------------------------------- 47 48 49def test_400(ceed_resource): 50 ceed = libceed.Ceed(ceed_resource) 51 52 file_dir = os.path.dirname(os.path.abspath(__file__)) 53 qfs = load_qfs_so() 54 55 qf_setup = ceed.QFunction(1, qfs.setup_mass, 56 os.path.join(file_dir, "test-qfunctions.h:setup_mass")) 57 qf_setup.add_input("w", 1, libceed.EVAL_WEIGHT) 58 qf_setup.add_input("dx", 1, libceed.EVAL_GRAD) 59 qf_setup.add_output("qdata", 1, libceed.EVAL_NONE) 60 61 qf_mass = ceed.QFunction(1, qfs.apply_mass, 62 os.path.join(file_dir, "test-qfunctions.h:apply_mass")) 63 qf_mass.add_input("qdata", 1, libceed.EVAL_NONE) 64 qf_mass.add_input("u", 1, libceed.EVAL_INTERP) 65 qf_mass.add_output("v", 1, libceed.EVAL_INTERP) 66 67 q = 8 68 69 w_array = np.zeros(q, dtype=ceed.scalar_type()) 70 u_array = np.zeros(q, dtype=ceed.scalar_type()) 71 v_true = np.zeros(q, dtype=ceed.scalar_type()) 72 for i in range(q): 73 x = 2. * i / (q - 1) - 1 74 w_array[i] = 1 - x * x 75 u_array[i] = 2 + 3 * x + 5 * x * x 76 v_true[i] = w_array[i] * u_array[i] 77 78 dx = ceed.Vector(q) 79 dx.set_value(1) 80 w = ceed.Vector(q) 81 w.set_array(w_array, cmode=libceed.USE_POINTER) 82 u = ceed.Vector(q) 83 u.set_array(u_array, cmode=libceed.USE_POINTER) 84 v = ceed.Vector(q) 85 v.set_value(0) 86 qdata = ceed.Vector(q) 87 qdata.set_value(0) 88 89 inputs = [dx, w] 90 outputs = [qdata] 91 qf_setup.apply(q, inputs, outputs) 92 93 inputs = [qdata, u] 94 outputs = [v] 95 qf_mass.apply(q, inputs, outputs) 96 97 with v.array_read() as v_array: 98 for i in range(q): 99 assert v_array[i] == v_true[i] 100 101# ------------------------------------------------------------------------------- 102# Test creation, evaluation, and destruction for qfunction 103# ------------------------------------------------------------------------------- 104 105 106def test_401(ceed_resource): 107 ceed = libceed.Ceed(ceed_resource) 108 109 file_dir = os.path.dirname(os.path.abspath(__file__)) 110 qfs = load_qfs_so() 111 112 qf_setup = ceed.QFunction(1, qfs.setup_mass, 113 os.path.join(file_dir, "test-qfunctions.h:setup_mass")) 114 qf_setup.add_input("w", 1, libceed.EVAL_WEIGHT) 115 qf_setup.add_input("dx", 1, libceed.EVAL_GRAD) 116 qf_setup.add_output("qdata", 1, libceed.EVAL_NONE) 117 118 qf_mass = ceed.QFunction(1, qfs.apply_mass, 119 os.path.join(file_dir, "test-qfunctions.h:apply_mass")) 120 qf_mass.add_input("qdata", 1, libceed.EVAL_NONE) 121 qf_mass.add_input("u", 1, libceed.EVAL_INTERP) 122 qf_mass.add_output("v", 1, libceed.EVAL_INTERP) 123 124 ctx_data = np.array([1., 2., 3., 4., 5.], dtype=ceed.scalar_type()) 125 ctx = ceed.QFunctionContext() 126 ctx.set_data(ctx_data) 127 qf_mass.set_context(ctx) 128 129 q = 8 130 131 w_array = np.zeros(q, dtype=ceed.scalar_type()) 132 u_array = np.zeros(q, dtype=ceed.scalar_type()) 133 v_true = np.zeros(q, dtype=ceed.scalar_type()) 134 for i in range(q): 135 x = 2. * i / (q - 1) - 1 136 w_array[i] = 1 - x * x 137 u_array[i] = 2 + 3 * x + 5 * x * x 138 v_true[i] = 5 * w_array[i] * u_array[i] 139 140 dx = ceed.Vector(q) 141 dx.set_value(1) 142 w = ceed.Vector(q) 143 w.set_array(w_array, cmode=libceed.USE_POINTER) 144 u = ceed.Vector(q) 145 u.set_array(u_array, cmode=libceed.USE_POINTER) 146 v = ceed.Vector(q) 147 v.set_value(0) 148 qdata = ceed.Vector(q) 149 qdata.set_value(0) 150 151 inputs = [dx, w] 152 outputs = [qdata] 153 qf_setup.apply(q, inputs, outputs) 154 155 inputs = [qdata, u] 156 outputs = [v] 157 qf_mass.apply(q, inputs, outputs) 158 159 with v.array_read() as v_array: 160 for i in range(q): 161 assert abs(v_array[i] - v_true[i]) < TOL 162 163# ------------------------------------------------------------------------------- 164# Test viewing of qfunction 165# ------------------------------------------------------------------------------- 166 167 168def test_402(ceed_resource, capsys): 169 ceed = libceed.Ceed(ceed_resource) 170 171 file_dir = os.path.dirname(os.path.abspath(__file__)) 172 qfs = load_qfs_so() 173 174 qf_setup = ceed.QFunction(1, qfs.setup_mass, 175 os.path.join(file_dir, "test-qfunctions.h:setup_mass")) 176 qf_setup.add_input("w", 1, libceed.EVAL_WEIGHT) 177 qf_setup.add_input("dx", 1, libceed.EVAL_GRAD) 178 qf_setup.add_output("qdata", 1, libceed.EVAL_NONE) 179 180 qf_mass = ceed.QFunction(1, qfs.apply_mass, 181 os.path.join(file_dir, "test-qfunctions.h:apply_mass")) 182 qf_mass.add_input("qdata", 1, libceed.EVAL_NONE) 183 qf_mass.add_input("u", 1, libceed.EVAL_INTERP) 184 qf_mass.add_output("v", 1, libceed.EVAL_INTERP) 185 186 print(qf_setup) 187 print(qf_mass) 188 189 if libceed.lib.CEED_SCALAR_TYPE == libceed.SCALAR_FP64: 190 ctx_data = np.array([1., 2., 3., 4., 5.], dtype="float64") 191 # Make ctx twice as long in fp32, so size will be the same as fp64 output 192 else: 193 ctx_data = np.array([1., 2., 3., 4., 5., 1., 2., 3., 4., 5.], 194 dtype="float32") 195 ctx = ceed.QFunctionContext() 196 ctx.set_data(ctx_data) 197 print(ctx) 198 199 stdout, stderr, ref_stdout = check.output(capsys) 200 assert not stderr 201 assert stdout == ref_stdout 202 203# ------------------------------------------------------------------------------- 204# Test creation, evaluation, and destruction for qfunction by name 205# ------------------------------------------------------------------------------- 206 207 208def test_410(ceed_resource): 209 ceed = libceed.Ceed(ceed_resource) 210 211 qf_setup = ceed.QFunctionByName("Mass1DBuild") 212 qf_mass = ceed.QFunctionByName("MassApply") 213 214 q = 8 215 216 j_array = np.zeros(q, dtype=ceed.scalar_type()) 217 w_array = np.zeros(q, dtype=ceed.scalar_type()) 218 u_array = np.zeros(q, dtype=ceed.scalar_type()) 219 v_true = np.zeros(q, dtype=ceed.scalar_type()) 220 for i in range(q): 221 x = 2. * i / (q - 1) - 1 222 j_array[i] = 1 223 w_array[i] = 1 - x * x 224 u_array[i] = 2 + 3 * x + 5 * x * x 225 v_true[i] = w_array[i] * u_array[i] 226 227 j = ceed.Vector(q) 228 j.set_array(j_array, cmode=libceed.USE_POINTER) 229 w = ceed.Vector(q) 230 w.set_array(w_array, cmode=libceed.USE_POINTER) 231 u = ceed.Vector(q) 232 u.set_array(u_array, cmode=libceed.USE_POINTER) 233 v = ceed.Vector(q) 234 v.set_value(0) 235 qdata = ceed.Vector(q) 236 qdata.set_value(0) 237 238 inputs = [j, w] 239 outputs = [qdata] 240 qf_setup.apply(q, inputs, outputs) 241 242 inputs = [w, u] 243 outputs = [v] 244 qf_mass.apply(q, inputs, outputs) 245 246 with v.array_read() as v_array: 247 for i in range(q): 248 assert v_array[i] == v_true[i] 249 250# ------------------------------------------------------------------------------- 251# Test creation, evaluation, and destruction of identity qfunction 252# ------------------------------------------------------------------------------- 253 254 255def test_411(ceed_resource): 256 ceed = libceed.Ceed(ceed_resource) 257 258 qf = ceed.IdentityQFunction(1, libceed.EVAL_INTERP, libceed.EVAL_INTERP) 259 260 q = 8 261 262 u_array = np.zeros(q, dtype=ceed.scalar_type()) 263 for i in range(q): 264 u_array[i] = i * i 265 266 u = ceed.Vector(q) 267 u.set_array(u_array, cmode=libceed.USE_POINTER) 268 v = ceed.Vector(q) 269 v.set_value(0) 270 271 inputs = [u] 272 outputs = [v] 273 qf.apply(q, inputs, outputs) 274 275 with v.array_read() as v_array: 276 for i in range(q): 277 assert v_array[i] == i * i 278 279# ------------------------------------------------------------------------------- 280# Test creation, evaluation, and destruction of identity qfunction with size>1 281# ------------------------------------------------------------------------------- 282 283 284def test_412(ceed_resource): 285 ceed = libceed.Ceed(ceed_resource) 286 287 size = 3 288 qf = ceed.IdentityQFunction(size, libceed.EVAL_INTERP, libceed.EVAL_INTERP) 289 290 q = 8 291 292 u_array = np.zeros(q * size, dtype=ceed.scalar_type()) 293 for i in range(q * size): 294 u_array[i] = i * i 295 296 u = ceed.Vector(q * size) 297 u.set_array(u_array, cmode=libceed.USE_POINTER) 298 v = ceed.Vector(q * size) 299 v.set_value(0) 300 301 inputs = [u] 302 outputs = [v] 303 qf.apply(q, inputs, outputs) 304 305 with v.array_read() as v_array: 306 for i in range(q * size): 307 assert v_array[i] == i * i 308 309# ------------------------------------------------------------------------------- 310# Test viewing of qfunction by name 311# ------------------------------------------------------------------------------- 312 313 314def test_413(ceed_resource, capsys): 315 ceed = libceed.Ceed(ceed_resource) 316 317 qf_setup = ceed.QFunctionByName("Mass1DBuild") 318 qf_mass = ceed.QFunctionByName("MassApply") 319 320 print(qf_setup) 321 print(qf_mass) 322 323 stdout, stderr, ref_stdout = check.output(capsys) 324 assert not stderr 325 assert stdout == ref_stdout 326 327# ------------------------------------------------------------------------------- 328