17def3d77Svaleriabarra# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 27def3d77Svaleriabarra# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 37def3d77Svaleriabarra# reserved. See files LICENSE and NOTICE for details. 47def3d77Svaleriabarra# 57def3d77Svaleriabarra# This file is part of CEED, a collection of benchmarks, miniapps, software 67def3d77Svaleriabarra# libraries and APIs for efficient high-order finite element and spectral 77def3d77Svaleriabarra# element discretizations for exascale applications. For more information and 87def3d77Svaleriabarra# source code availability see http://github.com/ceed. 97def3d77Svaleriabarra# 107def3d77Svaleriabarra# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 117def3d77Svaleriabarra# a collaborative effort of two U.S. Department of Energy organizations (Office 127def3d77Svaleriabarra# of Science and the National Nuclear Security Administration) responsible for 137def3d77Svaleriabarra# the planning and preparation of a capable exascale ecosystem, including 147def3d77Svaleriabarra# software, applications, hardware, advanced system engineering and early 157def3d77Svaleriabarra# testbed platforms, in support of the nation's exascale computing imperative. 167def3d77Svaleriabarra 177def3d77Svaleriabarrafrom _ceed_cffi import ffi, lib 187def3d77Svaleriabarraimport tempfile 197def3d77Svaleriabarraimport numpy as np 20*e259ae81SJed Brownimport contextlib 21547d9b97Sjeremyltfrom .ceed_constants import MEM_HOST, COPY_VALUES, NORM_2 227def3d77Svaleriabarra 237def3d77Svaleriabarra# ------------------------------------------------------------------------------ 247def3d77Svaleriabarraclass Vector(): 257def3d77Svaleriabarra """Ceed Vector: storing and manipulating vectors.""" 267def3d77Svaleriabarra 277def3d77Svaleriabarra # Attributes 287def3d77Svaleriabarra _ceed = ffi.NULL 297def3d77Svaleriabarra _pointer = ffi.NULL 307def3d77Svaleriabarra 317def3d77Svaleriabarra # Constructor 327def3d77Svaleriabarra def __init__(self, ceed, size): 337def3d77Svaleriabarra # CeedVector object 347def3d77Svaleriabarra self._pointer = ffi.new("CeedVector *") 357def3d77Svaleriabarra 367def3d77Svaleriabarra # Reference to Ceed 377def3d77Svaleriabarra self._ceed = ceed 387def3d77Svaleriabarra 397def3d77Svaleriabarra # libCEED call 407def3d77Svaleriabarra lib.CeedVectorCreate(self._ceed._pointer[0], size, self._pointer) 417def3d77Svaleriabarra 427def3d77Svaleriabarra # Destructor 437def3d77Svaleriabarra def __del__(self): 447def3d77Svaleriabarra # libCEED call 457def3d77Svaleriabarra lib.CeedVectorDestroy(self._pointer) 467def3d77Svaleriabarra 477def3d77Svaleriabarra # Representation 487def3d77Svaleriabarra def __repr__(self): 497def3d77Svaleriabarra return "<CeedVector instance at " + hex(id(self)) + ">" 507def3d77Svaleriabarra 517def3d77Svaleriabarra # String conversion for print() to stdout 527def3d77Svaleriabarra def __str__(self): 537def3d77Svaleriabarra """View a Vector via print().""" 547def3d77Svaleriabarra 557def3d77Svaleriabarra # libCEED call 567def3d77Svaleriabarra fmt = ffi.new("char[]", "%f".encode('ascii')) 577def3d77Svaleriabarra with tempfile.NamedTemporaryFile() as key_file: 587def3d77Svaleriabarra with open(key_file.name, 'r+') as stream_file: 597def3d77Svaleriabarra stream = ffi.cast("FILE *", stream_file) 607def3d77Svaleriabarra 617def3d77Svaleriabarra lib.CeedVectorView(self._pointer[0], fmt, stream) 627def3d77Svaleriabarra 637def3d77Svaleriabarra stream_file.seek(0) 647def3d77Svaleriabarra out_string = stream_file.read() 657def3d77Svaleriabarra 667def3d77Svaleriabarra return out_string 677def3d77Svaleriabarra 687def3d77Svaleriabarra # Set Vector's data array 697def3d77Svaleriabarra def set_array(self, array, memtype=MEM_HOST, cmode=COPY_VALUES): 707def3d77Svaleriabarra """Set the array used by a Vector, freeing any previously allocated 717def3d77Svaleriabarra array if applicable. 727def3d77Svaleriabarra 737def3d77Svaleriabarra Args: 747def3d77Svaleriabarra *array: Numpy array to be used 757def3d77Svaleriabarra **memtype: memory type of the array being passed, default CEED_MEM_HOST 767def3d77Svaleriabarra **cmode: copy mode for the array, default CEED_COPY_VALUES""" 777def3d77Svaleriabarra 787def3d77Svaleriabarra # Setup the numpy array for the libCEED call 797def3d77Svaleriabarra array_pointer = ffi.new("CeedScalar *") 807def3d77Svaleriabarra array_pointer = ffi.cast("CeedScalar *", array.__array_interface__['data'][0]) 817def3d77Svaleriabarra 827def3d77Svaleriabarra # libCEED call 837def3d77Svaleriabarra lib.CeedVectorSetArray(self._pointer[0], memtype, cmode, array_pointer) 847def3d77Svaleriabarra 857def3d77Svaleriabarra # Get Vector's data array 867def3d77Svaleriabarra def get_array(self, memtype=MEM_HOST): 877def3d77Svaleriabarra """Get read/write access to a Vector via the specified memory type. 887def3d77Svaleriabarra 897def3d77Svaleriabarra Args: 907def3d77Svaleriabarra **memtype: memory type of the array being passed, default CEED_MEM_HOST 917def3d77Svaleriabarra 927def3d77Svaleriabarra Returns: 937def3d77Svaleriabarra *array: Numpy array""" 947def3d77Svaleriabarra 957def3d77Svaleriabarra # Retrieve the length of the array 967def3d77Svaleriabarra length_pointer = ffi.new("CeedInt *") 977def3d77Svaleriabarra lib.CeedVectorGetLength(self._pointer[0], length_pointer) 987def3d77Svaleriabarra 997def3d77Svaleriabarra # Setup the pointer's pointer 1007def3d77Svaleriabarra array_pointer = ffi.new("CeedScalar **") 1017def3d77Svaleriabarra 1027def3d77Svaleriabarra # libCEED call 1037def3d77Svaleriabarra lib.CeedVectorGetArray(self._pointer[0], memtype, array_pointer) 1047def3d77Svaleriabarra 1057def3d77Svaleriabarra # Create buffer object from returned pointer 1067def3d77Svaleriabarra buff = ffi.buffer(array_pointer[0], ffi.sizeof("CeedScalar") * length_pointer[0]) 1077def3d77Svaleriabarra # Return numpy array created from buffer 1087def3d77Svaleriabarra return np.frombuffer(buff, dtype="float64") 1097def3d77Svaleriabarra 1107def3d77Svaleriabarra # Get Vector's data array in read-only mode 1117def3d77Svaleriabarra def get_array_read(self, memtype=MEM_HOST): 1127def3d77Svaleriabarra """Get read-only access to a Vector via the specified memory type. 1137def3d77Svaleriabarra 1147def3d77Svaleriabarra Args: 1157def3d77Svaleriabarra **memtype: memory type of the array being passed, default CEED_MEM_HOST 1167def3d77Svaleriabarra 1177def3d77Svaleriabarra Returns: 1187def3d77Svaleriabarra *array: Numpy array""" 1197def3d77Svaleriabarra 1207def3d77Svaleriabarra # Retrieve the length of the array 1217def3d77Svaleriabarra length_pointer = ffi.new("CeedInt *") 1227def3d77Svaleriabarra lib.CeedVectorGetLength(self._pointer[0], length_pointer) 1237def3d77Svaleriabarra 1247def3d77Svaleriabarra # Setup the pointer's pointer 1257def3d77Svaleriabarra array_pointer = ffi.new("CeedScalar **") 1267def3d77Svaleriabarra 1277def3d77Svaleriabarra # libCEED call 1287def3d77Svaleriabarra lib.CeedVectorGetArrayRead(self._pointer[0], memtype, array_pointer) 1297def3d77Svaleriabarra 1307def3d77Svaleriabarra # Create buffer object from returned pointer 1317def3d77Svaleriabarra buff = ffi.buffer(array_pointer[0], ffi.sizeof("CeedScalar") * length_pointer[0]) 1327def3d77Svaleriabarra # Create numpy array from buffer 1337def3d77Svaleriabarra ret = np.frombuffer(buff, dtype="float64") 1347def3d77Svaleriabarra # Make the numpy array read-only 1357def3d77Svaleriabarra ret.flags['WRITEABLE'] = False 1367def3d77Svaleriabarra return ret 1377def3d77Svaleriabarra 1387def3d77Svaleriabarra # Restore the Vector's data array 1397def3d77Svaleriabarra def restore_array(self): 1407def3d77Svaleriabarra """Restore an array obtained using get_array().""" 1417def3d77Svaleriabarra 1427def3d77Svaleriabarra # Setup the pointer's pointer 1437def3d77Svaleriabarra array_pointer = ffi.new("CeedScalar **") 1447def3d77Svaleriabarra 1457def3d77Svaleriabarra # libCEED call 1467def3d77Svaleriabarra lib.CeedVectorRestoreArray(self._pointer[0], array_pointer) 1477def3d77Svaleriabarra 1487def3d77Svaleriabarra # Restore an array obtained using getArrayRead 1497def3d77Svaleriabarra def restore_array_read(self): 1507def3d77Svaleriabarra """Restore an array obtained using get_array_read().""" 1517def3d77Svaleriabarra 1527def3d77Svaleriabarra # Setup the pointer's pointer 1537def3d77Svaleriabarra array_pointer = ffi.new("CeedScalar **") 1547def3d77Svaleriabarra 1557def3d77Svaleriabarra # libCEED call 1567def3d77Svaleriabarra lib.CeedVectorRestoreArrayRead(self._pointer[0], array_pointer) 1577def3d77Svaleriabarra 158*e259ae81SJed Brown @contextlib.contextmanager 159*e259ae81SJed Brown def array(self, *shape): 160*e259ae81SJed Brown """Context manager for array access. 161*e259ae81SJed Brown 162*e259ae81SJed Brown Args: 163*e259ae81SJed Brown shape (tuple): shape of returned numpy.array 164*e259ae81SJed Brown 165*e259ae81SJed Brown Returns: 166*e259ae81SJed Brown np.array: writable view of vector 167*e259ae81SJed Brown 168*e259ae81SJed Brown Examples: 169*e259ae81SJed Brown Constructing the identity inside a libceed.Vector: 170*e259ae81SJed Brown 171*e259ae81SJed Brown >>> vec = ceed.Vector(16) 172*e259ae81SJed Brown >>> with vec.array(4, 4) as x: 173*e259ae81SJed Brown >>> x[...] = np.eye(4) 174*e259ae81SJed Brown """ 175*e259ae81SJed Brown x = self.get_array() 176*e259ae81SJed Brown if shape: 177*e259ae81SJed Brown x = x.reshape(shape) 178*e259ae81SJed Brown yield x 179*e259ae81SJed Brown self.restore_array() 180*e259ae81SJed Brown 181*e259ae81SJed Brown @contextlib.contextmanager 182*e259ae81SJed Brown def array_read(self, *shape): 183*e259ae81SJed Brown """Context manager for read-only array access. 184*e259ae81SJed Brown 185*e259ae81SJed Brown Args: 186*e259ae81SJed Brown shape (tuple): shape of returned numpy.array 187*e259ae81SJed Brown 188*e259ae81SJed Brown Returns: 189*e259ae81SJed Brown np.array: read-only view of vector 190*e259ae81SJed Brown 191*e259ae81SJed Brown Examples: 192*e259ae81SJed Brown Constructing the identity inside a libceed.Vector: 193*e259ae81SJed Brown 194*e259ae81SJed Brown >>> vec = ceed.Vector(6) 195*e259ae81SJed Brown >>> vec.set_value(1.3) 196*e259ae81SJed Brown >>> with vec.array_read(2, 3) as x: 197*e259ae81SJed Brown >>> print(x) 198*e259ae81SJed Brown """ 199*e259ae81SJed Brown x = self.get_array_read() 200*e259ae81SJed Brown if shape: 201*e259ae81SJed Brown x = x.reshape(shape) 202*e259ae81SJed Brown yield x 203*e259ae81SJed Brown self.restore_array_read() 204*e259ae81SJed Brown 2057def3d77Svaleriabarra # Get the length of a Vector 2067def3d77Svaleriabarra def get_length(self): 2077def3d77Svaleriabarra """Get the length of a Vector. 2087def3d77Svaleriabarra 2097def3d77Svaleriabarra Returns: 2107def3d77Svaleriabarra length: length of the Vector""" 2117def3d77Svaleriabarra 2127def3d77Svaleriabarra length_pointer = ffi.new("CeedInt *") 2137def3d77Svaleriabarra 2147def3d77Svaleriabarra # libCEED call 2157def3d77Svaleriabarra lib.CeedVectorGetLength(self._pointer[0], length_pointer) 2167def3d77Svaleriabarra 2177def3d77Svaleriabarra return length_pointer[0] 2187def3d77Svaleriabarra 2197def3d77Svaleriabarra # Get the length of a Vector 2207def3d77Svaleriabarra def __len__(self): 2217def3d77Svaleriabarra """Get the length of a Vector. 2227def3d77Svaleriabarra 2237def3d77Svaleriabarra Returns: 2247def3d77Svaleriabarra length: length of the Vector""" 2257def3d77Svaleriabarra 2267def3d77Svaleriabarra length_pointer = ffi.new("CeedInt *") 2277def3d77Svaleriabarra 2287def3d77Svaleriabarra # libCEED call 2297def3d77Svaleriabarra lib.CeedVectorGetLength(self._pointer[0], length_pointer) 2307def3d77Svaleriabarra 2317def3d77Svaleriabarra return length_pointer[0] 2327def3d77Svaleriabarra 2337def3d77Svaleriabarra # Set the Vector to a given constant value 2347def3d77Svaleriabarra def set_value(self, value): 2357def3d77Svaleriabarra """Set the Vector to a constant value. 2367def3d77Svaleriabarra 2377def3d77Svaleriabarra Args: 2387def3d77Svaleriabarra value: value to be used""" 2397def3d77Svaleriabarra 2407def3d77Svaleriabarra # libCEED call 2417def3d77Svaleriabarra lib.CeedVectorSetValue(self._pointer[0], value) 2427def3d77Svaleriabarra 2437def3d77Svaleriabarra # Sync the Vector to a specified memtype 244547d9b97Sjeremylt def sync_array(self, memtype=MEM_HOST): 2457def3d77Svaleriabarra """Sync the Vector to a specified memtype. 2467def3d77Svaleriabarra 2477def3d77Svaleriabarra Args: 2487def3d77Svaleriabarra **memtype: memtype to be synced""" 2497def3d77Svaleriabarra 2507def3d77Svaleriabarra # libCEED call 2517def3d77Svaleriabarra lib.CeedVectorSyncArray(self._pointer[0], memtype) 2527def3d77Svaleriabarra 253547d9b97Sjeremylt # Compute the norm of a vector 254547d9b97Sjeremylt def norm(self, normtype=NORM_2): 255547d9b97Sjeremylt """Get the norm of a Vector. 256547d9b97Sjeremylt 257547d9b97Sjeremylt Args: 258547d9b97Sjeremylt **normtype: type of norm to be computed""" 259547d9b97Sjeremylt 260547d9b97Sjeremylt norm_pointer = ffi.new("CeedScalar *") 261547d9b97Sjeremylt 262547d9b97Sjeremylt # libCEED call 263547d9b97Sjeremylt lib.CeedVectorNorm(self._pointer[0], normtype, norm_pointer) 264547d9b97Sjeremylt 265547d9b97Sjeremylt return norm_pointer[0] 266547d9b97Sjeremylt 2677def3d77Svaleriabarra# ------------------------------------------------------------------------------ 2687def3d77Svaleriabarraclass _VectorWrap(Vector): 2697def3d77Svaleriabarra """Wrap a CeedVector pointer in a Vector object.""" 2707def3d77Svaleriabarra 2717def3d77Svaleriabarra # Constructor 2727def3d77Svaleriabarra def __init__(self, ceed, pointer): 2737def3d77Svaleriabarra # CeedVector object 2747def3d77Svaleriabarra self._pointer = pointer 2757def3d77Svaleriabarra 2767def3d77Svaleriabarra # Reference to Ceed 2777def3d77Svaleriabarra self._ceed = ceed 2787def3d77Svaleriabarra 2797def3d77Svaleriabarra# ------------------------------------------------------------------------------ 280