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