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 # Destructor 30 def __del__(self): 31 # libCEED call 32 err_code = lib.CeedQFunctionDestroy(self._pointer) 33 self._ceed._check_error(err_code) 34 35 # Representation 36 def __repr__(self): 37 return "<CeedQFunction instance at " + hex(id(self)) + ">" 38 39 # String conversion for print() to stdout 40 def __str__(self): 41 """View a QFunction via print().""" 42 43 # libCEED call 44 with tempfile.NamedTemporaryFile() as key_file: 45 with open(key_file.name, 'r+') as stream_file: 46 stream = ffi.cast("FILE *", stream_file) 47 48 err_code = lib.CeedQFunctionView(self._pointer[0], stream) 49 self._ceed._check_error(err_code) 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 err_code = lib.CeedQFunctionApply(self._pointer[0], q, invecs, outvecs) 75 self._ceed._check_error(err_code) 76 77 # Clean-up 78 ffi.release(invecs) 79 ffi.release(outvecs) 80 81 82# ------------------------------------------------------------------------------ 83class QFunction(_QFunctionBase): 84 """Ceed QFunction: point-wise operation at quadrature points for evaluating 85 volumetric terms.""" 86 87 # Constructor 88 def __init__(self, ceed, vlength, f, source): 89 # libCEED object 90 self._pointer = ffi.new("CeedQFunction *") 91 92 # Reference to Ceed 93 self._ceed = ceed 94 95 # Function pointer 96 fpointer = ffi.cast( 97 "CeedQFunctionUser", ctypes.cast( 98 f, ctypes.c_void_p).value) 99 100 # libCEED call 101 sourceAscii = ffi.new("char[]", source.encode('ascii')) 102 err_code = lib.CeedQFunctionCreateInterior(self._ceed._pointer[0], vlength, 103 fpointer, sourceAscii, self._pointer) 104 self._ceed._check_error(err_code) 105 106 # Set context data 107 def set_context(self, ctx): 108 """Set global context for a QFunction. 109 110 Args: 111 ctx: Ceed User Context object holding context data""" 112 113 # libCEED call 114 err_code = lib.CeedQFunctionSetContext( 115 self._pointer[0], 116 ctx._pointer[0]) 117 self._ceed._check_error(err_code) 118 119 # Add fields to CeedQFunction 120 def add_input(self, fieldname, size, emode): 121 """Add a QFunction input. 122 123 Args: 124 fieldname: name of QFunction field 125 size: size of QFunction field, (ncomp * dim) for CEED_EVAL_GRAD or 126 (ncomp * 1) for CEED_EVAL_NONE and CEED_EVAL_INTERP 127 **emode: CEED_EVAL_NONE to use values directly, 128 CEED_EVAL_INTERP to use interpolated values, 129 CEED_EVAL_GRAD to use gradients.""" 130 131 # libCEED call 132 fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii')) 133 err_code = lib.CeedQFunctionAddInput( 134 self._pointer[0], fieldnameAscii, size, emode) 135 self._ceed._check_error(err_code) 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 err_code = lib.CeedQFunctionAddOutput( 151 self._pointer[0], fieldnameAscii, size, emode) 152 self._ceed._check_error(err_code) 153 154# ------------------------------------------------------------------------------ 155 156 157class QFunctionByName(_QFunctionBase): 158 """Ceed QFunction By Name: point-wise operation at quadrature points 159 from a given gallery, for evaluating volumetric terms.""" 160 161 # Constructor 162 def __init__(self, ceed, name): 163 # libCEED object 164 self._pointer = ffi.new("CeedQFunction *") 165 166 # Reference to Ceed 167 self._ceed = ceed 168 169 # libCEED call 170 nameAscii = ffi.new("char[]", name.encode('ascii')) 171 err_code = lib.CeedQFunctionCreateInteriorByName(self._ceed._pointer[0], 172 nameAscii, self._pointer) 173 self._ceed._check_error(err_code) 174 175# ------------------------------------------------------------------------------ 176 177 178class IdentityQFunction(_QFunctionBase): 179 """Ceed Identity QFunction: identity qfunction operation.""" 180 181 # Constructor 182 def __init__(self, ceed, size, inmode, outmode): 183 # libCEED object 184 self._pointer = ffi.new("CeedQFunction *") 185 186 # Reference to Ceed 187 self._ceed = ceed 188 189 # libCEED call 190 err_code = lib.CeedQFunctionCreateIdentity(self._ceed._pointer[0], size, 191 inmode, outmode, self._pointer) 192 193# ------------------------------------------------------------------------------ 194