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 tempfile 19import numpy as np 20from .ceed_constants import MEM_HOST, COPY_VALUES, NORM_2 21 22# ------------------------------------------------------------------------------ 23class Vector(): 24 """Ceed Vector: storing and manipulating vectors.""" 25 26 # Attributes 27 _ceed = ffi.NULL 28 _pointer = ffi.NULL 29 30 # Constructor 31 def __init__(self, ceed, size): 32 # CeedVector object 33 self._pointer = ffi.new("CeedVector *") 34 35 # Reference to Ceed 36 self._ceed = ceed 37 38 # libCEED call 39 lib.CeedVectorCreate(self._ceed._pointer[0], size, self._pointer) 40 41 # Destructor 42 def __del__(self): 43 # libCEED call 44 lib.CeedVectorDestroy(self._pointer) 45 46 # Representation 47 def __repr__(self): 48 return "<CeedVector instance at " + hex(id(self)) + ">" 49 50 # String conversion for print() to stdout 51 def __str__(self): 52 """View a Vector via print().""" 53 54 # libCEED call 55 fmt = ffi.new("char[]", "%f".encode('ascii')) 56 with tempfile.NamedTemporaryFile() as key_file: 57 with open(key_file.name, 'r+') as stream_file: 58 stream = ffi.cast("FILE *", stream_file) 59 60 lib.CeedVectorView(self._pointer[0], fmt, stream) 61 62 stream_file.seek(0) 63 out_string = stream_file.read() 64 65 return out_string 66 67 # Set Vector's data array 68 def set_array(self, array, memtype=MEM_HOST, cmode=COPY_VALUES): 69 """Set the array used by a Vector, freeing any previously allocated 70 array if applicable. 71 72 Args: 73 *array: Numpy array to be used 74 **memtype: memory type of the array being passed, default CEED_MEM_HOST 75 **cmode: copy mode for the array, default CEED_COPY_VALUES""" 76 77 # Setup the numpy array for the libCEED call 78 array_pointer = ffi.new("CeedScalar *") 79 array_pointer = ffi.cast("CeedScalar *", array.__array_interface__['data'][0]) 80 81 # libCEED call 82 lib.CeedVectorSetArray(self._pointer[0], memtype, cmode, array_pointer) 83 84 # Get Vector's data array 85 def get_array(self, memtype=MEM_HOST): 86 """Get read/write access to a Vector via the specified memory type. 87 88 Args: 89 **memtype: memory type of the array being passed, default CEED_MEM_HOST 90 91 Returns: 92 *array: Numpy array""" 93 94 # Retrieve the length of the array 95 length_pointer = ffi.new("CeedInt *") 96 lib.CeedVectorGetLength(self._pointer[0], length_pointer) 97 98 # Setup the pointer's pointer 99 array_pointer = ffi.new("CeedScalar **") 100 101 # libCEED call 102 lib.CeedVectorGetArray(self._pointer[0], memtype, array_pointer) 103 104 # Create buffer object from returned pointer 105 buff = ffi.buffer(array_pointer[0], ffi.sizeof("CeedScalar") * length_pointer[0]) 106 # Return numpy array created from buffer 107 return np.frombuffer(buff, dtype="float64") 108 109 # Get Vector's data array in read-only mode 110 def get_array_read(self, memtype=MEM_HOST): 111 """Get read-only access to a Vector via the specified memory type. 112 113 Args: 114 **memtype: memory type of the array being passed, default CEED_MEM_HOST 115 116 Returns: 117 *array: Numpy array""" 118 119 # Retrieve the length of the array 120 length_pointer = ffi.new("CeedInt *") 121 lib.CeedVectorGetLength(self._pointer[0], length_pointer) 122 123 # Setup the pointer's pointer 124 array_pointer = ffi.new("CeedScalar **") 125 126 # libCEED call 127 lib.CeedVectorGetArrayRead(self._pointer[0], memtype, array_pointer) 128 129 # Create buffer object from returned pointer 130 buff = ffi.buffer(array_pointer[0], ffi.sizeof("CeedScalar") * length_pointer[0]) 131 # Create numpy array from buffer 132 ret = np.frombuffer(buff, dtype="float64") 133 # Make the numpy array read-only 134 ret.flags['WRITEABLE'] = False 135 return ret 136 137 # Restore the Vector's data array 138 def restore_array(self): 139 """Restore an array obtained using get_array().""" 140 141 # Setup the pointer's pointer 142 array_pointer = ffi.new("CeedScalar **") 143 144 # libCEED call 145 lib.CeedVectorRestoreArray(self._pointer[0], array_pointer) 146 147 # Restore an array obtained using getArrayRead 148 def restore_array_read(self): 149 """Restore an array obtained using get_array_read().""" 150 151 # Setup the pointer's pointer 152 array_pointer = ffi.new("CeedScalar **") 153 154 # libCEED call 155 lib.CeedVectorRestoreArrayRead(self._pointer[0], array_pointer) 156 157 # Get the length of a Vector 158 def get_length(self): 159 """Get the length of a Vector. 160 161 Returns: 162 length: length of the Vector""" 163 164 length_pointer = ffi.new("CeedInt *") 165 166 # libCEED call 167 lib.CeedVectorGetLength(self._pointer[0], length_pointer) 168 169 return length_pointer[0] 170 171 # Get the length of a Vector 172 def __len__(self): 173 """Get the length of a Vector. 174 175 Returns: 176 length: length of the Vector""" 177 178 length_pointer = ffi.new("CeedInt *") 179 180 # libCEED call 181 lib.CeedVectorGetLength(self._pointer[0], length_pointer) 182 183 return length_pointer[0] 184 185 # Set the Vector to a given constant value 186 def set_value(self, value): 187 """Set the Vector to a constant value. 188 189 Args: 190 value: value to be used""" 191 192 # libCEED call 193 lib.CeedVectorSetValue(self._pointer[0], value) 194 195 # Sync the Vector to a specified memtype 196 def sync_array(self, memtype=MEM_HOST): 197 """Sync the Vector to a specified memtype. 198 199 Args: 200 **memtype: memtype to be synced""" 201 202 # libCEED call 203 lib.CeedVectorSyncArray(self._pointer[0], memtype) 204 205 # Compute the norm of a vector 206 def norm(self, normtype=NORM_2): 207 """Get the norm of a Vector. 208 209 Args: 210 **normtype: type of norm to be computed""" 211 212 norm_pointer = ffi.new("CeedScalar *") 213 214 # libCEED call 215 lib.CeedVectorNorm(self._pointer[0], normtype, norm_pointer) 216 217 return norm_pointer[0] 218 219# ------------------------------------------------------------------------------ 220class _VectorWrap(Vector): 221 """Wrap a CeedVector pointer in a Vector object.""" 222 223 # Constructor 224 def __init__(self, ceed, pointer): 225 # CeedVector object 226 self._pointer = pointer 227 228 # Reference to Ceed 229 self._ceed = ceed 230 231# ------------------------------------------------------------------------------ 232