xref: /libCEED/python/ceed_vector.py (revision 7a7b0fa3029ed576dc3d3fb37afaf50f3689b395)
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
20e259ae81SJed Brownimport contextlib
21547d9b97Sjeremyltfrom .ceed_constants import MEM_HOST, COPY_VALUES, NORM_2
227def3d77Svaleriabarra
237def3d77Svaleriabarra# ------------------------------------------------------------------------------
24*7a7b0fa3SJed Brown
25*7a7b0fa3SJed Brown
267def3d77Svaleriabarraclass Vector():
277def3d77Svaleriabarra    """Ceed Vector: storing and manipulating vectors."""
287def3d77Svaleriabarra
297def3d77Svaleriabarra    # Attributes
307def3d77Svaleriabarra    _ceed = ffi.NULL
317def3d77Svaleriabarra    _pointer = ffi.NULL
327def3d77Svaleriabarra
337def3d77Svaleriabarra    # Constructor
347def3d77Svaleriabarra    def __init__(self, ceed, size):
357def3d77Svaleriabarra        # CeedVector object
367def3d77Svaleriabarra        self._pointer = ffi.new("CeedVector *")
377def3d77Svaleriabarra
387def3d77Svaleriabarra        # Reference to Ceed
397def3d77Svaleriabarra        self._ceed = ceed
407def3d77Svaleriabarra
417def3d77Svaleriabarra        # libCEED call
427def3d77Svaleriabarra        lib.CeedVectorCreate(self._ceed._pointer[0], size, self._pointer)
437def3d77Svaleriabarra
447def3d77Svaleriabarra    # Destructor
457def3d77Svaleriabarra    def __del__(self):
467def3d77Svaleriabarra        # libCEED call
477def3d77Svaleriabarra        lib.CeedVectorDestroy(self._pointer)
487def3d77Svaleriabarra
497def3d77Svaleriabarra    # Representation
507def3d77Svaleriabarra    def __repr__(self):
517def3d77Svaleriabarra        return "<CeedVector instance at " + hex(id(self)) + ">"
527def3d77Svaleriabarra
537def3d77Svaleriabarra    # String conversion for print() to stdout
547def3d77Svaleriabarra    def __str__(self):
557def3d77Svaleriabarra        """View a Vector via print()."""
567def3d77Svaleriabarra
577def3d77Svaleriabarra        # libCEED call
587def3d77Svaleriabarra        fmt = ffi.new("char[]", "%f".encode('ascii'))
597def3d77Svaleriabarra        with tempfile.NamedTemporaryFile() as key_file:
607def3d77Svaleriabarra            with open(key_file.name, 'r+') as stream_file:
617def3d77Svaleriabarra                stream = ffi.cast("FILE *", stream_file)
627def3d77Svaleriabarra
637def3d77Svaleriabarra                lib.CeedVectorView(self._pointer[0], fmt, stream)
647def3d77Svaleriabarra
657def3d77Svaleriabarra                stream_file.seek(0)
667def3d77Svaleriabarra                out_string = stream_file.read()
677def3d77Svaleriabarra
687def3d77Svaleriabarra        return out_string
697def3d77Svaleriabarra
707def3d77Svaleriabarra    # Set Vector's data array
717def3d77Svaleriabarra    def set_array(self, array, memtype=MEM_HOST, cmode=COPY_VALUES):
727def3d77Svaleriabarra        """Set the array used by a Vector, freeing any previously allocated
737def3d77Svaleriabarra           array if applicable.
747def3d77Svaleriabarra
757def3d77Svaleriabarra           Args:
767def3d77Svaleriabarra             *array: Numpy array to be used
777def3d77Svaleriabarra             **memtype: memory type of the array being passed, default CEED_MEM_HOST
787def3d77Svaleriabarra             **cmode: copy mode for the array, default CEED_COPY_VALUES"""
797def3d77Svaleriabarra
807def3d77Svaleriabarra        # Setup the numpy array for the libCEED call
817def3d77Svaleriabarra        array_pointer = ffi.new("CeedScalar *")
82*7a7b0fa3SJed Brown        array_pointer = ffi.cast(
83*7a7b0fa3SJed Brown            "CeedScalar *",
84*7a7b0fa3SJed Brown            array.__array_interface__['data'][0])
857def3d77Svaleriabarra
867def3d77Svaleriabarra        # libCEED call
877def3d77Svaleriabarra        lib.CeedVectorSetArray(self._pointer[0], memtype, cmode, array_pointer)
887def3d77Svaleriabarra
897def3d77Svaleriabarra    # Get Vector's data array
907def3d77Svaleriabarra    def get_array(self, memtype=MEM_HOST):
917def3d77Svaleriabarra        """Get read/write access to a Vector via the specified memory type.
927def3d77Svaleriabarra
937def3d77Svaleriabarra           Args:
947def3d77Svaleriabarra             **memtype: memory type of the array being passed, default CEED_MEM_HOST
957def3d77Svaleriabarra
967def3d77Svaleriabarra           Returns:
977def3d77Svaleriabarra             *array: Numpy array"""
987def3d77Svaleriabarra
997def3d77Svaleriabarra        # Retrieve the length of the array
1007def3d77Svaleriabarra        length_pointer = ffi.new("CeedInt *")
1017def3d77Svaleriabarra        lib.CeedVectorGetLength(self._pointer[0], length_pointer)
1027def3d77Svaleriabarra
1037def3d77Svaleriabarra        # Setup the pointer's pointer
1047def3d77Svaleriabarra        array_pointer = ffi.new("CeedScalar **")
1057def3d77Svaleriabarra
1067def3d77Svaleriabarra        # libCEED call
1077def3d77Svaleriabarra        lib.CeedVectorGetArray(self._pointer[0], memtype, array_pointer)
1087def3d77Svaleriabarra
1097def3d77Svaleriabarra        # Create buffer object from returned pointer
110*7a7b0fa3SJed Brown        buff = ffi.buffer(
111*7a7b0fa3SJed Brown            array_pointer[0],
112*7a7b0fa3SJed Brown            ffi.sizeof("CeedScalar") *
113*7a7b0fa3SJed Brown            length_pointer[0])
1147def3d77Svaleriabarra        # Return numpy array created from buffer
1157def3d77Svaleriabarra        return np.frombuffer(buff, dtype="float64")
1167def3d77Svaleriabarra
1177def3d77Svaleriabarra    # Get Vector's data array in read-only mode
1187def3d77Svaleriabarra    def get_array_read(self, memtype=MEM_HOST):
1197def3d77Svaleriabarra        """Get read-only access to a Vector via the specified memory type.
1207def3d77Svaleriabarra
1217def3d77Svaleriabarra           Args:
1227def3d77Svaleriabarra             **memtype: memory type of the array being passed, default CEED_MEM_HOST
1237def3d77Svaleriabarra
1247def3d77Svaleriabarra           Returns:
1257def3d77Svaleriabarra             *array: Numpy array"""
1267def3d77Svaleriabarra
1277def3d77Svaleriabarra        # Retrieve the length of the array
1287def3d77Svaleriabarra        length_pointer = ffi.new("CeedInt *")
1297def3d77Svaleriabarra        lib.CeedVectorGetLength(self._pointer[0], length_pointer)
1307def3d77Svaleriabarra
1317def3d77Svaleriabarra        # Setup the pointer's pointer
1327def3d77Svaleriabarra        array_pointer = ffi.new("CeedScalar **")
1337def3d77Svaleriabarra
1347def3d77Svaleriabarra        # libCEED call
1357def3d77Svaleriabarra        lib.CeedVectorGetArrayRead(self._pointer[0], memtype, array_pointer)
1367def3d77Svaleriabarra
1377def3d77Svaleriabarra        # Create buffer object from returned pointer
138*7a7b0fa3SJed Brown        buff = ffi.buffer(
139*7a7b0fa3SJed Brown            array_pointer[0],
140*7a7b0fa3SJed Brown            ffi.sizeof("CeedScalar") *
141*7a7b0fa3SJed Brown            length_pointer[0])
1427def3d77Svaleriabarra        # Create numpy array from buffer
1437def3d77Svaleriabarra        ret = np.frombuffer(buff, dtype="float64")
1447def3d77Svaleriabarra        # Make the numpy array read-only
1457def3d77Svaleriabarra        ret.flags['WRITEABLE'] = False
1467def3d77Svaleriabarra        return ret
1477def3d77Svaleriabarra
1487def3d77Svaleriabarra    # Restore the Vector's data array
1497def3d77Svaleriabarra    def restore_array(self):
1507def3d77Svaleriabarra        """Restore an array obtained using get_array()."""
1517def3d77Svaleriabarra
1527def3d77Svaleriabarra        # Setup the pointer's pointer
1537def3d77Svaleriabarra        array_pointer = ffi.new("CeedScalar **")
1547def3d77Svaleriabarra
1557def3d77Svaleriabarra        # libCEED call
1567def3d77Svaleriabarra        lib.CeedVectorRestoreArray(self._pointer[0], array_pointer)
1577def3d77Svaleriabarra
1587def3d77Svaleriabarra    # Restore an array obtained using getArrayRead
1597def3d77Svaleriabarra    def restore_array_read(self):
1607def3d77Svaleriabarra        """Restore an array obtained using get_array_read()."""
1617def3d77Svaleriabarra
1627def3d77Svaleriabarra        # Setup the pointer's pointer
1637def3d77Svaleriabarra        array_pointer = ffi.new("CeedScalar **")
1647def3d77Svaleriabarra
1657def3d77Svaleriabarra        # libCEED call
1667def3d77Svaleriabarra        lib.CeedVectorRestoreArrayRead(self._pointer[0], array_pointer)
1677def3d77Svaleriabarra
168e259ae81SJed Brown    @contextlib.contextmanager
169e259ae81SJed Brown    def array(self, *shape):
170e259ae81SJed Brown        """Context manager for array access.
171e259ae81SJed Brown
172e259ae81SJed Brown        Args:
173e259ae81SJed Brown          shape (tuple): shape of returned numpy.array
174e259ae81SJed Brown
175e259ae81SJed Brown        Returns:
176e259ae81SJed Brown          np.array: writable view of vector
177e259ae81SJed Brown
178e259ae81SJed Brown        Examples:
179e259ae81SJed Brown          Constructing the identity inside a libceed.Vector:
180e259ae81SJed Brown
181e259ae81SJed Brown          >>> vec = ceed.Vector(16)
182e259ae81SJed Brown          >>> with vec.array(4, 4) as x:
183e259ae81SJed Brown          >>>     x[...] = np.eye(4)
184e259ae81SJed Brown        """
185e259ae81SJed Brown        x = self.get_array()
186e259ae81SJed Brown        if shape:
187e259ae81SJed Brown            x = x.reshape(shape)
188e259ae81SJed Brown        yield x
189e259ae81SJed Brown        self.restore_array()
190e259ae81SJed Brown
191e259ae81SJed Brown    @contextlib.contextmanager
192e259ae81SJed Brown    def array_read(self, *shape):
193e259ae81SJed Brown        """Context manager for read-only array access.
194e259ae81SJed Brown
195e259ae81SJed Brown        Args:
196e259ae81SJed Brown          shape (tuple): shape of returned numpy.array
197e259ae81SJed Brown
198e259ae81SJed Brown        Returns:
199e259ae81SJed Brown          np.array: read-only view of vector
200e259ae81SJed Brown
201e259ae81SJed Brown        Examples:
202e259ae81SJed Brown          Constructing the identity inside a libceed.Vector:
203e259ae81SJed Brown
204e259ae81SJed Brown          >>> vec = ceed.Vector(6)
205e259ae81SJed Brown          >>> vec.set_value(1.3)
206e259ae81SJed Brown          >>> with vec.array_read(2, 3) as x:
207e259ae81SJed Brown          >>>     print(x)
208e259ae81SJed Brown        """
209e259ae81SJed Brown        x = self.get_array_read()
210e259ae81SJed Brown        if shape:
211e259ae81SJed Brown            x = x.reshape(shape)
212e259ae81SJed Brown        yield x
213e259ae81SJed Brown        self.restore_array_read()
214e259ae81SJed Brown
2157def3d77Svaleriabarra    # Get the length of a Vector
2167def3d77Svaleriabarra    def get_length(self):
2177def3d77Svaleriabarra        """Get the length of a Vector.
2187def3d77Svaleriabarra
2197def3d77Svaleriabarra           Returns:
2207def3d77Svaleriabarra             length: length of the Vector"""
2217def3d77Svaleriabarra
2227def3d77Svaleriabarra        length_pointer = ffi.new("CeedInt *")
2237def3d77Svaleriabarra
2247def3d77Svaleriabarra        # libCEED call
2257def3d77Svaleriabarra        lib.CeedVectorGetLength(self._pointer[0], length_pointer)
2267def3d77Svaleriabarra
2277def3d77Svaleriabarra        return length_pointer[0]
2287def3d77Svaleriabarra
2297def3d77Svaleriabarra    # Get the length of a Vector
2307def3d77Svaleriabarra    def __len__(self):
2317def3d77Svaleriabarra        """Get the length of a Vector.
2327def3d77Svaleriabarra
2337def3d77Svaleriabarra           Returns:
2347def3d77Svaleriabarra             length: length of the Vector"""
2357def3d77Svaleriabarra
2367def3d77Svaleriabarra        length_pointer = ffi.new("CeedInt *")
2377def3d77Svaleriabarra
2387def3d77Svaleriabarra        # libCEED call
2397def3d77Svaleriabarra        lib.CeedVectorGetLength(self._pointer[0], length_pointer)
2407def3d77Svaleriabarra
2417def3d77Svaleriabarra        return length_pointer[0]
2427def3d77Svaleriabarra
2437def3d77Svaleriabarra    # Set the Vector to a given constant value
2447def3d77Svaleriabarra    def set_value(self, value):
2457def3d77Svaleriabarra        """Set the Vector to a constant value.
2467def3d77Svaleriabarra
2477def3d77Svaleriabarra           Args:
2487def3d77Svaleriabarra             value: value to be used"""
2497def3d77Svaleriabarra
2507def3d77Svaleriabarra        # libCEED call
2517def3d77Svaleriabarra        lib.CeedVectorSetValue(self._pointer[0], value)
2527def3d77Svaleriabarra
2537def3d77Svaleriabarra    # Sync the Vector to a specified memtype
254547d9b97Sjeremylt    def sync_array(self, memtype=MEM_HOST):
2557def3d77Svaleriabarra        """Sync the Vector to a specified memtype.
2567def3d77Svaleriabarra
2577def3d77Svaleriabarra           Args:
2587def3d77Svaleriabarra             **memtype: memtype to be synced"""
2597def3d77Svaleriabarra
2607def3d77Svaleriabarra        # libCEED call
2617def3d77Svaleriabarra        lib.CeedVectorSyncArray(self._pointer[0], memtype)
2627def3d77Svaleriabarra
263547d9b97Sjeremylt    # Compute the norm of a vector
264547d9b97Sjeremylt    def norm(self, normtype=NORM_2):
265547d9b97Sjeremylt        """Get the norm of a Vector.
266547d9b97Sjeremylt
267547d9b97Sjeremylt           Args:
268547d9b97Sjeremylt             **normtype: type of norm to be computed"""
269547d9b97Sjeremylt
270547d9b97Sjeremylt        norm_pointer = ffi.new("CeedScalar *")
271547d9b97Sjeremylt
272547d9b97Sjeremylt        # libCEED call
273547d9b97Sjeremylt        lib.CeedVectorNorm(self._pointer[0], normtype, norm_pointer)
274547d9b97Sjeremylt
275547d9b97Sjeremylt        return norm_pointer[0]
276547d9b97Sjeremylt
2777def3d77Svaleriabarra# ------------------------------------------------------------------------------
278*7a7b0fa3SJed Brown
279*7a7b0fa3SJed Brown
2807def3d77Svaleriabarraclass _VectorWrap(Vector):
2817def3d77Svaleriabarra    """Wrap a CeedVector pointer in a Vector object."""
2827def3d77Svaleriabarra
2837def3d77Svaleriabarra    # Constructor
2847def3d77Svaleriabarra    def __init__(self, ceed, pointer):
2857def3d77Svaleriabarra        # CeedVector object
2867def3d77Svaleriabarra        self._pointer = pointer
2877def3d77Svaleriabarra
2887def3d77Svaleriabarra        # Reference to Ceed
2897def3d77Svaleriabarra        self._ceed = ceed
2907def3d77Svaleriabarra
2917def3d77Svaleriabarra# ------------------------------------------------------------------------------
292