xref: /libCEED/python/ceed_vector.py (revision e259ae81ed1076ac958f9800317134b12a1c563b)
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