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