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 17from _ceed_cffi import ffi, lib 18import ctypes 19import tempfile 20from abc import ABC 21 22# ------------------------------------------------------------------------------ 23 24 25class _QFunctionBase(ABC): 26 """Ceed QFunction: point-wise operation at quadrature points for evaluating 27 volumetric terms.""" 28 29 # Attributes 30 _ceed = ffi.NULL 31 _pointer = ffi.NULL 32 33 # Destructor 34 def __del__(self): 35 # libCEED call 36 err_code = lib.CeedQFunctionDestroy(self._pointer) 37 self._ceed._check_error(err_code) 38 39 # Representation 40 def __repr__(self): 41 return "<CeedQFunction instance at " + hex(id(self)) + ">" 42 43 # String conversion for print() to stdout 44 def __str__(self): 45 """View a QFunction via print().""" 46 47 # libCEED call 48 with tempfile.NamedTemporaryFile() as key_file: 49 with open(key_file.name, 'r+') as stream_file: 50 stream = ffi.cast("FILE *", stream_file) 51 52 err_code = lib.CeedQFunctionView(self._pointer[0], stream) 53 self._ceed._check_error(err_code) 54 55 stream_file.seek(0) 56 out_string = stream_file.read() 57 58 return out_string 59 60 # Apply CeedQFunction 61 def apply(self, q, inputs, outputs): 62 """Apply the action of a QFunction. 63 64 Args: 65 q: number of quadrature points 66 *inputs: array of input data vectors 67 *outputs: array of output data vectors""" 68 69 # Array of vectors 70 invecs = ffi.new("CeedVector[16]") 71 for i in range(min(16, len(inputs))): 72 invecs[i] = inputs[i]._pointer[0] 73 outvecs = ffi.new("CeedVector[16]") 74 for i in range(min(16, len(outputs))): 75 outvecs[i] = outputs[i]._pointer[0] 76 77 # libCEED call 78 err_code = lib.CeedQFunctionApply(self._pointer[0], q, invecs, outvecs) 79 self._ceed._check_error(err_code) 80 81 # Clean-up 82 ffi.release(invecs) 83 ffi.release(outvecs) 84 85 86# ------------------------------------------------------------------------------ 87class QFunction(_QFunctionBase): 88 """Ceed QFunction: point-wise operation at quadrature points for evaluating 89 volumetric terms.""" 90 91 # Constructor 92 def __init__(self, ceed, vlength, f, source): 93 # libCEED object 94 self._pointer = ffi.new("CeedQFunction *") 95 96 # Reference to Ceed 97 self._ceed = ceed 98 99 # Function pointer 100 fpointer = ffi.cast( 101 "CeedQFunctionUser", ctypes.cast( 102 f, ctypes.c_void_p).value) 103 104 # libCEED call 105 sourceAscii = ffi.new("char[]", source.encode('ascii')) 106 err_code = lib.CeedQFunctionCreateInterior(self._ceed._pointer[0], vlength, 107 fpointer, sourceAscii, self._pointer) 108 self._ceed._check_error(err_code) 109 110 # Set context data 111 def set_context(self, ctx): 112 """Set global context for a QFunction. 113 114 Args: 115 *ctx: Numpy array holding context data to set""" 116 117 # Setup the numpy array for the libCEED call 118 ctx_pointer = ffi.new("CeedScalar *") 119 ctx_pointer = ffi.cast("void *", ctx.__array_interface__['data'][0]) 120 121 # libCEED call 122 err_code = lib.CeedQFunctionSetContext( 123 self._pointer[0], ctx_pointer, len(ctx)) 124 self._ceed._check_error(err_code) 125 126 # Add fields to CeedQFunction 127 def add_input(self, fieldname, size, emode): 128 """Add a QFunction input. 129 130 Args: 131 fieldname: name of QFunction field 132 size: size of QFunction field, (ncomp * dim) for CEED_EVAL_GRAD or 133 (ncomp * 1) for CEED_EVAL_NONE and CEED_EVAL_INTERP 134 **emode: CEED_EVAL_NONE to use values directly, 135 CEED_EVAL_INTERP to use interpolated values, 136 CEED_EVAL_GRAD to use gradients.""" 137 138 # libCEED call 139 fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii')) 140 err_code = lib.CeedQFunctionAddInput( 141 self._pointer[0], fieldnameAscii, size, emode) 142 self._ceed._check_error(err_code) 143 144 def add_output(self, fieldname, size, emode): 145 """Add a QFunction output. 146 147 Args: 148 fieldname: name of QFunction field 149 size: size of QFunction field, (ncomp * dim) for CEED_EVAL_GRAD or 150 (ncomp * 1) for CEED_EVAL_NONE and CEED_EVAL_INTERP 151 **emode: CEED_EVAL_NONE to use values directly, 152 CEED_EVAL_INTERP to use interpolated values, 153 CEED_EVAL_GRAD to use gradients.""" 154 155 # libCEED call 156 fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii')) 157 err_code = lib.CeedQFunctionAddOutput( 158 self._pointer[0], fieldnameAscii, size, emode) 159 self._ceed._check_error(err_code) 160 161# ------------------------------------------------------------------------------ 162 163 164class QFunctionByName(_QFunctionBase): 165 """Ceed QFunction By Name: point-wise operation at quadrature points 166 from a given gallery, for evaluating volumetric terms.""" 167 168 # Constructor 169 def __init__(self, ceed, name): 170 # libCEED object 171 self._pointer = ffi.new("CeedQFunction *") 172 173 # Reference to Ceed 174 self._ceed = ceed 175 176 # libCEED call 177 nameAscii = ffi.new("char[]", name.encode('ascii')) 178 err_code = lib.CeedQFunctionCreateInteriorByName(self._ceed._pointer[0], 179 nameAscii, self._pointer) 180 self._ceed._check_error(err_code) 181 182# ------------------------------------------------------------------------------ 183 184 185class IdentityQFunction(_QFunctionBase): 186 """Ceed Identity QFunction: identity qfunction operation.""" 187 188 # Constructor 189 def __init__(self, ceed, size, inmode, outmode): 190 # libCEED object 191 self._pointer = ffi.new("CeedQFunction *") 192 193 # Reference to Ceed 194 self._ceed = ceed 195 196 # libCEED call 197 err_code = lib.CeedQFunctionCreateIdentity(self._ceed._pointer[0], size, 198 inmode, outmode, self._pointer) 199 200# ------------------------------------------------------------------------------ 201