1777ff853SJeremy L Thompson# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2777ff853SJeremy L Thompson# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3777ff853SJeremy L Thompson# reserved. See files LICENSE and NOTICE for details. 4777ff853SJeremy L Thompson# 5777ff853SJeremy L Thompson# This file is part of CEED, a collection of benchmarks, miniapps, software 6777ff853SJeremy L Thompson# libraries and APIs for efficient high-order finite element and spectral 7777ff853SJeremy L Thompson# element discretizations for exascale applications. For more information and 8777ff853SJeremy L Thompson# source code availability see http://github.com/ceed. 9777ff853SJeremy L Thompson# 10777ff853SJeremy L Thompson# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11777ff853SJeremy L Thompson# a collaborative effort of two U.S. Department of Energy organizations (Office 12777ff853SJeremy L Thompson# of Science and the National Nuclear Security Administration) responsible for 13777ff853SJeremy L Thompson# the planning and preparation of a capable exascale ecosystem, including 14777ff853SJeremy L Thompson# software, applications, hardware, advanced system engineering and early 15777ff853SJeremy L Thompson# testbed platforms, in support of the nation's exascale computing imperative. 16777ff853SJeremy L Thompson 17777ff853SJeremy L Thompsonfrom _ceed_cffi import ffi, lib 18777ff853SJeremy L Thompsonimport tempfile 19777ff853SJeremy L Thompsonimport numpy as np 20777ff853SJeremy L Thompsonimport contextlib 21*80a9ef05SNatalie Beamsfrom .ceed_constants import MEM_HOST, USE_POINTER, COPY_VALUES, scalar_types 22777ff853SJeremy L Thompson 23777ff853SJeremy L Thompson# ------------------------------------------------------------------------------ 24777ff853SJeremy L Thompson 25777ff853SJeremy L Thompson 26777ff853SJeremy L Thompsonclass QFunctionContext(): 27777ff853SJeremy L Thompson """Ceed QFunction Context: stores Ceed QFunction user context data.""" 28777ff853SJeremy L Thompson 29777ff853SJeremy L Thompson # Constructor 30777ff853SJeremy L Thompson def __init__(self, ceed): 31777ff853SJeremy L Thompson # CeedQFunctionContext object 32777ff853SJeremy L Thompson self._pointer = ffi.new("CeedQFunctionContext *") 33777ff853SJeremy L Thompson 34777ff853SJeremy L Thompson # Reference to Ceed 35777ff853SJeremy L Thompson self._ceed = ceed 36777ff853SJeremy L Thompson 37777ff853SJeremy L Thompson # libCEED call 38777ff853SJeremy L Thompson err_code = lib.CeedQFunctionContextCreate( 39777ff853SJeremy L Thompson self._ceed._pointer[0], self._pointer) 40777ff853SJeremy L Thompson self._ceed._check_error(err_code) 41777ff853SJeremy L Thompson 42777ff853SJeremy L Thompson # Destructor 43777ff853SJeremy L Thompson def __del__(self): 44777ff853SJeremy L Thompson # libCEED call 45777ff853SJeremy L Thompson err_code = lib.CeedQFunctionContextDestroy(self._pointer) 46777ff853SJeremy L Thompson self._ceed._check_error(err_code) 47777ff853SJeremy L Thompson 48777ff853SJeremy L Thompson # Representation 49777ff853SJeremy L Thompson def __repr__(self): 50777ff853SJeremy L Thompson return "<CeedQFunctionContext instance at " + hex(id(self)) + ">" 51777ff853SJeremy L Thompson 52777ff853SJeremy L Thompson # String conversion for print() to stdout 53777ff853SJeremy L Thompson def __str__(self): 54777ff853SJeremy L Thompson """View a QFunction Context via print().""" 55777ff853SJeremy L Thompson 56777ff853SJeremy L Thompson # libCEED call 57777ff853SJeremy L Thompson fmt = ffi.new("char[]", "%f".encode('ascii')) 58777ff853SJeremy L Thompson with tempfile.NamedTemporaryFile() as key_file: 59777ff853SJeremy L Thompson with open(key_file.name, 'r+') as stream_file: 60777ff853SJeremy L Thompson stream = ffi.cast("FILE *", stream_file) 61777ff853SJeremy L Thompson 62777ff853SJeremy L Thompson err_code = lib.CeedQFunctionContextView( 63777ff853SJeremy L Thompson self._pointer[0], stream) 64777ff853SJeremy L Thompson self._ceed._check_error(err_code) 65777ff853SJeremy L Thompson 66777ff853SJeremy L Thompson stream_file.seek(0) 67777ff853SJeremy L Thompson out_string = stream_file.read() 68777ff853SJeremy L Thompson 69777ff853SJeremy L Thompson return out_string 70777ff853SJeremy L Thompson 71777ff853SJeremy L Thompson # Set QFunction Context's data 72777ff853SJeremy L Thompson def set_data(self, data, memtype=MEM_HOST, cmode=COPY_VALUES): 73777ff853SJeremy L Thompson """Set the data used by a QFunction Context, freeing any previously allocated 74777ff853SJeremy L Thompson data if applicable. 75777ff853SJeremy L Thompson 76777ff853SJeremy L Thompson Args: 77777ff853SJeremy L Thompson *data: Numpy or Numba array to be used 78777ff853SJeremy L Thompson **memtype: memory type of the array being passed, default CEED_MEM_HOST 79777ff853SJeremy L Thompson **cmode: copy mode for the array, default CEED_COPY_VALUES""" 80777ff853SJeremy L Thompson 81187168c7SJeremy L Thompson # Store array reference if needed 82187168c7SJeremy L Thompson if cmode == USE_POINTER: 83187168c7SJeremy L Thompson self._array_reference = data 84187168c7SJeremy L Thompson else: 85187168c7SJeremy L Thompson self._array_reference = None 86187168c7SJeremy L Thompson 87777ff853SJeremy L Thompson # Setup the numpy array for the libCEED call 88777ff853SJeremy L Thompson data_pointer = ffi.new("CeedScalar *") 89777ff853SJeremy L Thompson if memtype == MEM_HOST: 90777ff853SJeremy L Thompson data_pointer = ffi.cast( 91777ff853SJeremy L Thompson "void *", 92777ff853SJeremy L Thompson data.__array_interface__['data'][0]) 93777ff853SJeremy L Thompson else: 94777ff853SJeremy L Thompson array_pointer = ffi.cast( 95777ff853SJeremy L Thompson "void *", 96777ff853SJeremy L Thompson data.__cuda_array_interface__['data'][0]) 97777ff853SJeremy L Thompson 98777ff853SJeremy L Thompson # libCEED call 99777ff853SJeremy L Thompson err_code = lib.CeedQFunctionContextSetData( 100777ff853SJeremy L Thompson self._pointer[0], 101777ff853SJeremy L Thompson memtype, 102777ff853SJeremy L Thompson cmode, 103777ff853SJeremy L Thompson len(data) * ffi.sizeof("CeedScalar"), 104777ff853SJeremy L Thompson data_pointer) 105777ff853SJeremy L Thompson self._ceed._check_error(err_code) 106777ff853SJeremy L Thompson 107777ff853SJeremy L Thompson # Get QFunction Context's data 108777ff853SJeremy L Thompson def get_data(self, memtype=MEM_HOST): 109777ff853SJeremy L Thompson """Get read/write access to a QFunction Context via the specified memory type. 110777ff853SJeremy L Thompson 111777ff853SJeremy L Thompson Args: 112777ff853SJeremy L Thompson **memtype: memory type of the array being passed, default CEED_MEM_HOST 113777ff853SJeremy L Thompson 114777ff853SJeremy L Thompson Returns: 115777ff853SJeremy L Thompson *data: Numpy or Numba array""" 116777ff853SJeremy L Thompson 117777ff853SJeremy L Thompson # Retrieve the length of the array 118*80a9ef05SNatalie Beams size_pointer = ffi.new("size_t *") 119777ff853SJeremy L Thompson err_code = lib.CeedQFunctionContextGetContextSize( 120777ff853SJeremy L Thompson self._pointer[0], size_pointer) 121777ff853SJeremy L Thompson self._ceed._check_error(err_code) 122777ff853SJeremy L Thompson 123777ff853SJeremy L Thompson # Setup the pointer's pointer 124777ff853SJeremy L Thompson data_pointer = ffi.new("CeedScalar **") 125777ff853SJeremy L Thompson 126777ff853SJeremy L Thompson # libCEED call 127777ff853SJeremy L Thompson err_code = lib.CeedQFunctionContextGetData( 128777ff853SJeremy L Thompson self._pointer[0], memtype, data_pointer) 129777ff853SJeremy L Thompson self._ceed._check_error(err_code) 130777ff853SJeremy L Thompson 131777ff853SJeremy L Thompson # Return array created from buffer 132777ff853SJeremy L Thompson if memtype == MEM_HOST: 133777ff853SJeremy L Thompson # Create buffer object from returned pointer 134777ff853SJeremy L Thompson buff = ffi.buffer( 135777ff853SJeremy L Thompson data_pointer[0], 136*80a9ef05SNatalie Beams size_pointer[0]) 137777ff853SJeremy L Thompson # return Numpy array 138*80a9ef05SNatalie Beams return np.frombuffer(buff, dtype=scalar_types[lib.CEED_SCALAR_TYPE]) 139777ff853SJeremy L Thompson else: 140777ff853SJeremy L Thompson # CUDA array interface 141777ff853SJeremy L Thompson # https://numba.pydata.org/numba-doc/latest/cuda/cuda_array_interface.html 142777ff853SJeremy L Thompson import numba.cuda as nbcuda 143*80a9ef05SNatalie Beams if lib.CEED_SCALAR_TYPE == lib.CEED_SCALAR_FP32: 144*80a9ef05SNatalie Beams scalar_type_str = '>f4' 145*80a9ef05SNatalie Beams else: 146*80a9ef05SNatalie Beams scalar_type_str = '>f8' 147777ff853SJeremy L Thompson desc = { 148*80a9ef05SNatalie Beams 'shape': (size_pointer[0] / ffi.sizeof("CeedScalar")), 149*80a9ef05SNatalie Beams 'typestr': scalar_type_str, 150777ff853SJeremy L Thompson 'data': (int(ffi.cast("intptr_t", data_pointer[0])), False), 151777ff853SJeremy L Thompson 'version': 2 152777ff853SJeremy L Thompson } 153777ff853SJeremy L Thompson # return Numba array 154777ff853SJeremy L Thompson return nbcuda.from_cuda_array_interface(desc) 155777ff853SJeremy L Thompson 156777ff853SJeremy L Thompson # Restore the QFunction Context's data 157777ff853SJeremy L Thompson def restore_data(self): 158777ff853SJeremy L Thompson """Restore an array obtained using get_data().""" 159777ff853SJeremy L Thompson 160777ff853SJeremy L Thompson # Setup the pointer's pointer 161777ff853SJeremy L Thompson data_pointer = ffi.new("CeedScalar **") 162777ff853SJeremy L Thompson 163777ff853SJeremy L Thompson # libCEED call 1649647a07eSDavid Medina err_code = lib.CeedQFunctionDataRestoreData( 1659647a07eSDavid Medina self._pointer[0], data_pointer) 166777ff853SJeremy L Thompson self._ceed._check_error(err_code) 167777ff853SJeremy L Thompson 168777ff853SJeremy L Thompson @contextlib.contextmanager 169777ff853SJeremy L Thompson def data(self, *shape, memtype=MEM_HOST): 170777ff853SJeremy L Thompson """Context manager for array access. 171777ff853SJeremy L Thompson 172777ff853SJeremy L Thompson Args: 173777ff853SJeremy L Thompson shape (tuple): shape of returned numpy.array 174777ff853SJeremy L Thompson **memtype: memory type of the data being passed, default CEED_MEM_HOST 175777ff853SJeremy L Thompson 176777ff853SJeremy L Thompson 177777ff853SJeremy L Thompson Returns: 178777ff853SJeremy L Thompson np.array: writable view of QFunction Context 179777ff853SJeremy L Thompson """ 180777ff853SJeremy L Thompson x = self.get_data(memtype=memtype) 181777ff853SJeremy L Thompson if shape: 182777ff853SJeremy L Thompson x = x.reshape(shape) 183777ff853SJeremy L Thompson yield x 184777ff853SJeremy L Thompson self.restore_data() 185777ff853SJeremy L Thompson 186777ff853SJeremy L Thompson# ------------------------------------------------------------------------------ 187