xref: /libCEED/python/ceed_vector.py (revision 5fb68f377259d3910de46d787b7c5d1587fd01e1)
13d8e8822SJeremy L Thompson# Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors
23d8e8822SJeremy L Thompson# All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
37def3d77Svaleriabarra#
43d8e8822SJeremy L Thompson# SPDX-License-Identifier: BSD-2-Clause
57def3d77Svaleriabarra#
63d8e8822SJeremy L Thompson# This file is part of CEED:  http://github.com/ceed
77def3d77Svaleriabarra
87def3d77Svaleriabarrafrom _ceed_cffi import ffi, lib
97def3d77Svaleriabarraimport tempfile
107def3d77Svaleriabarraimport numpy as np
11e259ae81SJed Brownimport contextlib
1280a9ef05SNatalie Beamsfrom .ceed_constants import MEM_HOST, USE_POINTER, COPY_VALUES, NORM_2, scalar_types
137def3d77Svaleriabarra
147def3d77Svaleriabarra# ------------------------------------------------------------------------------
157a7b0fa3SJed Brown
167a7b0fa3SJed Brown
177def3d77Svaleriabarraclass Vector():
187def3d77Svaleriabarra    """Ceed Vector: storing and manipulating vectors."""
197def3d77Svaleriabarra
207def3d77Svaleriabarra    # Constructor
217def3d77Svaleriabarra    def __init__(self, ceed, size):
227def3d77Svaleriabarra        # CeedVector object
237def3d77Svaleriabarra        self._pointer = ffi.new("CeedVector *")
247def3d77Svaleriabarra
257def3d77Svaleriabarra        # Reference to Ceed
267def3d77Svaleriabarra        self._ceed = ceed
277def3d77Svaleriabarra
287def3d77Svaleriabarra        # libCEED call
29477729cfSJeremy L Thompson        err_code = lib.CeedVectorCreate(
30477729cfSJeremy L Thompson            self._ceed._pointer[0], size, self._pointer)
31477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
327def3d77Svaleriabarra
337def3d77Svaleriabarra    # Destructor
347def3d77Svaleriabarra    def __del__(self):
357def3d77Svaleriabarra        # libCEED call
36477729cfSJeremy L Thompson        err_code = lib.CeedVectorDestroy(self._pointer)
37477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
387def3d77Svaleriabarra
397def3d77Svaleriabarra    # Representation
407def3d77Svaleriabarra    def __repr__(self):
417def3d77Svaleriabarra        return "<CeedVector instance at " + hex(id(self)) + ">"
427def3d77Svaleriabarra
437def3d77Svaleriabarra    # String conversion for print() to stdout
447def3d77Svaleriabarra    def __str__(self):
457def3d77Svaleriabarra        """View a Vector via print()."""
467def3d77Svaleriabarra
477def3d77Svaleriabarra        # libCEED call
487def3d77Svaleriabarra        fmt = ffi.new("char[]", "%f".encode('ascii'))
497def3d77Svaleriabarra        with tempfile.NamedTemporaryFile() as key_file:
507def3d77Svaleriabarra            with open(key_file.name, 'r+') as stream_file:
517def3d77Svaleriabarra                stream = ffi.cast("FILE *", stream_file)
527def3d77Svaleriabarra
53477729cfSJeremy L Thompson                err_code = lib.CeedVectorView(self._pointer[0], fmt, stream)
54477729cfSJeremy L Thompson                self._ceed._check_error(err_code)
557def3d77Svaleriabarra
567def3d77Svaleriabarra                stream_file.seek(0)
577def3d77Svaleriabarra                out_string = stream_file.read()
587def3d77Svaleriabarra
597def3d77Svaleriabarra        return out_string
607def3d77Svaleriabarra
61*5fb68f37SKaren (Ren) Stengel    # Copy the array from a vector into self
62*5fb68f37SKaren (Ren) Stengel    def copy_from(self, vec_source):
63*5fb68f37SKaren (Ren) Stengel        """Copies the array of vec_source into the array of self.
64*5fb68f37SKaren (Ren) Stengel
65*5fb68f37SKaren (Ren) Stengel           Args:
66*5fb68f37SKaren (Ren) Stengel             *vector: the Vector to copy from"""
67*5fb68f37SKaren (Ren) Stengel
68*5fb68f37SKaren (Ren) Stengel        # libCEED call
69*5fb68f37SKaren (Ren) Stengel        err_code = lib.CeedVectorCopy(vec_source._pointer[0], self._pointer[0])
70*5fb68f37SKaren (Ren) Stengel        self._ceed._check_error(err_code)
71*5fb68f37SKaren (Ren) Stengel
727def3d77Svaleriabarra    # Set Vector's data array
737def3d77Svaleriabarra    def set_array(self, array, memtype=MEM_HOST, cmode=COPY_VALUES):
747def3d77Svaleriabarra        """Set the array used by a Vector, freeing any previously allocated
757def3d77Svaleriabarra           array if applicable.
767def3d77Svaleriabarra
777def3d77Svaleriabarra           Args:
787f1dc7b9SJeremy L Thompson             *array: Numpy or Numba array to be used
797def3d77Svaleriabarra             **memtype: memory type of the array being passed, default CEED_MEM_HOST
807def3d77Svaleriabarra             **cmode: copy mode for the array, default CEED_COPY_VALUES"""
817def3d77Svaleriabarra
82187168c7SJeremy L Thompson        # Store array reference if needed
83187168c7SJeremy L Thompson        if cmode == USE_POINTER:
84187168c7SJeremy L Thompson            self._array_reference = array
85187168c7SJeremy L Thompson        else:
86187168c7SJeremy L Thompson            self._array_reference = None
87187168c7SJeremy L Thompson
887def3d77Svaleriabarra        # Setup the numpy array for the libCEED call
897def3d77Svaleriabarra        array_pointer = ffi.new("CeedScalar *")
907f1dc7b9SJeremy L Thompson        if memtype == MEM_HOST:
917a7b0fa3SJed Brown            array_pointer = ffi.cast(
927a7b0fa3SJed Brown                "CeedScalar *",
937a7b0fa3SJed Brown                array.__array_interface__['data'][0])
947f1dc7b9SJeremy L Thompson        else:
957f1dc7b9SJeremy L Thompson            array_pointer = ffi.cast(
967f1dc7b9SJeremy L Thompson                "CeedScalar *",
977f1dc7b9SJeremy L Thompson                array.__cuda_array_interface__['data'][0])
987def3d77Svaleriabarra
997def3d77Svaleriabarra        # libCEED call
100477729cfSJeremy L Thompson        err_code = lib.CeedVectorSetArray(
101477729cfSJeremy L Thompson            self._pointer[0], memtype, cmode, array_pointer)
102477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
1037def3d77Svaleriabarra
1047def3d77Svaleriabarra    # Get Vector's data array
1057def3d77Svaleriabarra    def get_array(self, memtype=MEM_HOST):
1067def3d77Svaleriabarra        """Get read/write access to a Vector via the specified memory type.
1077def3d77Svaleriabarra
1087def3d77Svaleriabarra           Args:
1097def3d77Svaleriabarra             **memtype: memory type of the array being passed, default CEED_MEM_HOST
1107def3d77Svaleriabarra
1117def3d77Svaleriabarra           Returns:
1127f1dc7b9SJeremy L Thompson             *array: Numpy or Numba array"""
1137def3d77Svaleriabarra
1147def3d77Svaleriabarra        # Retrieve the length of the array
1151f9221feSJeremy L Thompson        length_pointer = ffi.new("CeedSize *")
116477729cfSJeremy L Thompson        err_code = lib.CeedVectorGetLength(self._pointer[0], length_pointer)
117477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
1187def3d77Svaleriabarra
1197def3d77Svaleriabarra        # Setup the pointer's pointer
1207def3d77Svaleriabarra        array_pointer = ffi.new("CeedScalar **")
1217def3d77Svaleriabarra
1227def3d77Svaleriabarra        # libCEED call
123477729cfSJeremy L Thompson        err_code = lib.CeedVectorGetArray(
124477729cfSJeremy L Thompson            self._pointer[0], memtype, array_pointer)
125477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
1267def3d77Svaleriabarra
1277f1dc7b9SJeremy L Thompson        # Return array created from buffer
1287f1dc7b9SJeremy L Thompson        if memtype == MEM_HOST:
1297def3d77Svaleriabarra            # Create buffer object from returned pointer
1307a7b0fa3SJed Brown            buff = ffi.buffer(
1317a7b0fa3SJed Brown                array_pointer[0],
1327a7b0fa3SJed Brown                ffi.sizeof("CeedScalar") *
1337a7b0fa3SJed Brown                length_pointer[0])
1347f1dc7b9SJeremy L Thompson            # return Numpy array
13580a9ef05SNatalie Beams            return np.frombuffer(buff, dtype=scalar_types[lib.CEED_SCALAR_TYPE])
1367f1dc7b9SJeremy L Thompson        else:
1377f1dc7b9SJeremy L Thompson            # CUDA array interface
1387f1dc7b9SJeremy L Thompson            # https://numba.pydata.org/numba-doc/latest/cuda/cuda_array_interface.html
139962dc42dSJeremy L Thompson            import numba.cuda as nbcuda
1407f1dc7b9SJeremy L Thompson            desc = {
1417f1dc7b9SJeremy L Thompson                'shape': (length_pointer[0]),
1427f1dc7b9SJeremy L Thompson                'typestr': '>f8',
1437f1dc7b9SJeremy L Thompson                'data': (int(ffi.cast("intptr_t", array_pointer[0])), False),
1447f1dc7b9SJeremy L Thompson                'version': 2
1457f1dc7b9SJeremy L Thompson            }
1467f1dc7b9SJeremy L Thompson            # return Numba array
1477f1dc7b9SJeremy L Thompson            return nbcuda.from_cuda_array_interface(desc)
1487def3d77Svaleriabarra
1497def3d77Svaleriabarra    # Get Vector's data array in read-only mode
1507def3d77Svaleriabarra    def get_array_read(self, memtype=MEM_HOST):
1517def3d77Svaleriabarra        """Get read-only access to a Vector via the specified memory type.
1527def3d77Svaleriabarra
1537def3d77Svaleriabarra           Args:
1547def3d77Svaleriabarra             **memtype: memory type of the array being passed, default CEED_MEM_HOST
1557def3d77Svaleriabarra
1567def3d77Svaleriabarra           Returns:
1577f1dc7b9SJeremy L Thompson             *array: Numpy or Numba array"""
1587def3d77Svaleriabarra
1597def3d77Svaleriabarra        # Retrieve the length of the array
1601f9221feSJeremy L Thompson        length_pointer = ffi.new("CeedSize *")
161477729cfSJeremy L Thompson        err_code = lib.CeedVectorGetLength(self._pointer[0], length_pointer)
162477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
1637def3d77Svaleriabarra
1647def3d77Svaleriabarra        # Setup the pointer's pointer
1657def3d77Svaleriabarra        array_pointer = ffi.new("CeedScalar **")
1667def3d77Svaleriabarra
1677def3d77Svaleriabarra        # libCEED call
168477729cfSJeremy L Thompson        err_code = lib.CeedVectorGetArrayRead(
169477729cfSJeremy L Thompson            self._pointer[0], memtype, array_pointer)
170477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
1717def3d77Svaleriabarra
1727f1dc7b9SJeremy L Thompson        # Return array created from buffer
1737f1dc7b9SJeremy L Thompson        if memtype == MEM_HOST:
1747def3d77Svaleriabarra            # Create buffer object from returned pointer
1757a7b0fa3SJed Brown            buff = ffi.buffer(
1767a7b0fa3SJed Brown                array_pointer[0],
1777a7b0fa3SJed Brown                ffi.sizeof("CeedScalar") *
1787a7b0fa3SJed Brown                length_pointer[0])
1797f1dc7b9SJeremy L Thompson            # return read only Numpy array
18080a9ef05SNatalie Beams            ret = np.frombuffer(buff, dtype=scalar_types[lib.CEED_SCALAR_TYPE])
1817def3d77Svaleriabarra            ret.flags['WRITEABLE'] = False
1827def3d77Svaleriabarra            return ret
1837f1dc7b9SJeremy L Thompson        else:
1847f1dc7b9SJeremy L Thompson            # CUDA array interface
1857f1dc7b9SJeremy L Thompson            # https://numba.pydata.org/numba-doc/latest/cuda/cuda_array_interface.html
186962dc42dSJeremy L Thompson            import numba.cuda as nbcuda
1877f1dc7b9SJeremy L Thompson            desc = {
1887f1dc7b9SJeremy L Thompson                'shape': (length_pointer[0]),
1897f1dc7b9SJeremy L Thompson                'typestr': '>f8',
1907f1dc7b9SJeremy L Thompson                'data': (int(ffi.cast("intptr_t", array_pointer[0])), False),
1917f1dc7b9SJeremy L Thompson                'version': 2
1927f1dc7b9SJeremy L Thompson            }
1937f1dc7b9SJeremy L Thompson            # return read only Numba array
1947f1dc7b9SJeremy L Thompson            return nbcuda.from_cuda_array_interface(desc)
1957def3d77Svaleriabarra
1969c774eddSJeremy L Thompson    # Get Vector's data array in write-only mode
1979c774eddSJeremy L Thompson    def get_array_write(self, memtype=MEM_HOST):
1989c774eddSJeremy L Thompson        """Get write-only access to a Vector via the specified memory type.
1999c774eddSJeremy L Thompson           All old values should be considered invalid.
2009c774eddSJeremy L Thompson
2019c774eddSJeremy L Thompson           Args:
2029c774eddSJeremy L Thompson             **memtype: memory type of the array being passed, default CEED_MEM_HOST
2039c774eddSJeremy L Thompson
2049c774eddSJeremy L Thompson           Returns:
2059c774eddSJeremy L Thompson             *array: Numpy or Numba array"""
2069c774eddSJeremy L Thompson
2079c774eddSJeremy L Thompson        # Retrieve the length of the array
2081f9221feSJeremy L Thompson        length_pointer = ffi.new("CeedSize *")
2099c774eddSJeremy L Thompson        err_code = lib.CeedVectorGetLength(self._pointer[0], length_pointer)
2109c774eddSJeremy L Thompson        self._ceed._check_error(err_code)
2119c774eddSJeremy L Thompson
2129c774eddSJeremy L Thompson        # Setup the pointer's pointer
2139c774eddSJeremy L Thompson        array_pointer = ffi.new("CeedScalar **")
2149c774eddSJeremy L Thompson
2159c774eddSJeremy L Thompson        # libCEED call
2169c774eddSJeremy L Thompson        err_code = lib.CeedVectorGetArrayWrite(
2179c774eddSJeremy L Thompson            self._pointer[0], memtype, array_pointer)
2189c774eddSJeremy L Thompson        self._ceed._check_error(err_code)
2199c774eddSJeremy L Thompson
2209c774eddSJeremy L Thompson        # Return array created from buffer
2219c774eddSJeremy L Thompson        if memtype == MEM_HOST:
2229c774eddSJeremy L Thompson            # Create buffer object from returned pointer
2239c774eddSJeremy L Thompson            buff = ffi.buffer(
2249c774eddSJeremy L Thompson                array_pointer[0],
2259c774eddSJeremy L Thompson                ffi.sizeof("CeedScalar") *
2269c774eddSJeremy L Thompson                length_pointer[0])
2279c774eddSJeremy L Thompson            # return Numpy array
2289c774eddSJeremy L Thompson            return np.frombuffer(buff, dtype=scalar_types[lib.CEED_SCALAR_TYPE])
2299c774eddSJeremy L Thompson        else:
2309c774eddSJeremy L Thompson            # CUDA array interface
2319c774eddSJeremy L Thompson            # https://numba.pydata.org/numba-doc/latest/cuda/cuda_array_interface.html
2329c774eddSJeremy L Thompson            import numba.cuda as nbcuda
2339c774eddSJeremy L Thompson            desc = {
2349c774eddSJeremy L Thompson                'shape': (length_pointer[0]),
2359c774eddSJeremy L Thompson                'typestr': '>f8',
2369c774eddSJeremy L Thompson                'data': (int(ffi.cast("intptr_t", array_pointer[0])), False),
2379c774eddSJeremy L Thompson                'version': 2
2389c774eddSJeremy L Thompson            }
2399c774eddSJeremy L Thompson            # return Numba array
2409c774eddSJeremy L Thompson            return nbcuda.from_cuda_array_interface(desc)
2419c774eddSJeremy L Thompson
2427def3d77Svaleriabarra    # Restore the Vector's data array
2437def3d77Svaleriabarra    def restore_array(self):
2447def3d77Svaleriabarra        """Restore an array obtained using get_array()."""
2457def3d77Svaleriabarra
2467def3d77Svaleriabarra        # Setup the pointer's pointer
2477def3d77Svaleriabarra        array_pointer = ffi.new("CeedScalar **")
2487def3d77Svaleriabarra
2497def3d77Svaleriabarra        # libCEED call
250477729cfSJeremy L Thompson        err_code = lib.CeedVectorRestoreArray(self._pointer[0], array_pointer)
251477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
2527def3d77Svaleriabarra
2537def3d77Svaleriabarra    # Restore an array obtained using getArrayRead
2547def3d77Svaleriabarra    def restore_array_read(self):
2557def3d77Svaleriabarra        """Restore an array obtained using get_array_read()."""
2567def3d77Svaleriabarra
2577def3d77Svaleriabarra        # Setup the pointer's pointer
2587def3d77Svaleriabarra        array_pointer = ffi.new("CeedScalar **")
2597def3d77Svaleriabarra
2607def3d77Svaleriabarra        # libCEED call
261477729cfSJeremy L Thompson        err_code = lib.CeedVectorRestoreArrayRead(
262477729cfSJeremy L Thompson            self._pointer[0], array_pointer)
263477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
2647def3d77Svaleriabarra
265e259ae81SJed Brown    @contextlib.contextmanager
2667f1dc7b9SJeremy L Thompson    def array(self, *shape, memtype=MEM_HOST):
267e259ae81SJed Brown        """Context manager for array access.
268e259ae81SJed Brown
269e259ae81SJed Brown        Args:
270e259ae81SJed Brown          shape (tuple): shape of returned numpy.array
2717f1dc7b9SJeremy L Thompson          **memtype: memory type of the array being passed, default CEED_MEM_HOST
2727f1dc7b9SJeremy L Thompson
273e259ae81SJed Brown
274e259ae81SJed Brown        Returns:
275e259ae81SJed Brown          np.array: writable view of vector
276e259ae81SJed Brown
277e259ae81SJed Brown        Examples:
278e259ae81SJed Brown          Constructing the identity inside a libceed.Vector:
279e259ae81SJed Brown
280e259ae81SJed Brown          >>> vec = ceed.Vector(16)
281e259ae81SJed Brown          >>> with vec.array(4, 4) as x:
282e259ae81SJed Brown          >>>     x[...] = np.eye(4)
283e259ae81SJed Brown        """
2847f1dc7b9SJeremy L Thompson        x = self.get_array(memtype=memtype)
285e259ae81SJed Brown        if shape:
286e259ae81SJed Brown            x = x.reshape(shape)
287e259ae81SJed Brown        yield x
288e259ae81SJed Brown        self.restore_array()
289e259ae81SJed Brown
290e259ae81SJed Brown    @contextlib.contextmanager
2917f1dc7b9SJeremy L Thompson    def array_read(self, *shape, memtype=MEM_HOST):
292e259ae81SJed Brown        """Context manager for read-only array access.
293e259ae81SJed Brown
294e259ae81SJed Brown        Args:
295e259ae81SJed Brown          shape (tuple): shape of returned numpy.array
2967f1dc7b9SJeremy L Thompson          **memtype: memory type of the array being passed, default CEED_MEM_HOST
297e259ae81SJed Brown
298e259ae81SJed Brown        Returns:
299e259ae81SJed Brown          np.array: read-only view of vector
300e259ae81SJed Brown
301e259ae81SJed Brown        Examples:
302187168c7SJeremy L Thompson          Viewing contents of a reshaped libceed.Vector view:
303e259ae81SJed Brown
304e259ae81SJed Brown          >>> vec = ceed.Vector(6)
305e259ae81SJed Brown          >>> vec.set_value(1.3)
306e259ae81SJed Brown          >>> with vec.array_read(2, 3) as x:
307e259ae81SJed Brown          >>>     print(x)
308e259ae81SJed Brown        """
3097f1dc7b9SJeremy L Thompson        x = self.get_array_read(memtype=memtype)
310e259ae81SJed Brown        if shape:
311e259ae81SJed Brown            x = x.reshape(shape)
312e259ae81SJed Brown        yield x
313e259ae81SJed Brown        self.restore_array_read()
314e259ae81SJed Brown
3159c774eddSJeremy L Thompson    @contextlib.contextmanager
3169c774eddSJeremy L Thompson    def array_write(self, *shape, memtype=MEM_HOST):
3179c774eddSJeremy L Thompson        """Context manager for write-only array access.
3189c774eddSJeremy L Thompson           All old values should be considered invalid.
3199c774eddSJeremy L Thompson
3209c774eddSJeremy L Thompson        Args:
3219c774eddSJeremy L Thompson          shape (tuple): shape of returned numpy.array
3229c774eddSJeremy L Thompson          **memtype: memory type of the array being passed, default CEED_MEM_HOST
3239c774eddSJeremy L Thompson
3249c774eddSJeremy L Thompson        Returns:
3259c774eddSJeremy L Thompson          np.array: write-only view of vector
3269c774eddSJeremy L Thompson
3279c774eddSJeremy L Thompson        Examples:
3289c774eddSJeremy L Thompson          Viewing contents of a reshaped libceed.Vector view:
3299c774eddSJeremy L Thompson
3309c774eddSJeremy L Thompson          >>> vec = ceed.Vector(6)
3319c774eddSJeremy L Thompson          >>> vec.set_value(1.3)
3329c774eddSJeremy L Thompson          >>> with vec.array_read(2, 3) as x:
3339c774eddSJeremy L Thompson          >>>     print(x)
3349c774eddSJeremy L Thompson        """
3359c774eddSJeremy L Thompson        x = self.get_array_write(memtype=memtype)
3369c774eddSJeremy L Thompson        if shape:
3379c774eddSJeremy L Thompson            x = x.reshape(shape)
3389c774eddSJeremy L Thompson        yield x
3399c774eddSJeremy L Thompson        self.restore_array()
3409c774eddSJeremy L Thompson
3417def3d77Svaleriabarra    # Get the length of a Vector
3427def3d77Svaleriabarra    def get_length(self):
3437def3d77Svaleriabarra        """Get the length of a Vector.
3447def3d77Svaleriabarra
3457def3d77Svaleriabarra           Returns:
3467def3d77Svaleriabarra             length: length of the Vector"""
3477def3d77Svaleriabarra
3481f9221feSJeremy L Thompson        length_pointer = ffi.new("CeedSize *")
3497def3d77Svaleriabarra
3507def3d77Svaleriabarra        # libCEED call
351477729cfSJeremy L Thompson        err_code = lib.CeedVectorGetLength(self._pointer[0], length_pointer)
352477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
3537def3d77Svaleriabarra
3547def3d77Svaleriabarra        return length_pointer[0]
3557def3d77Svaleriabarra
3567def3d77Svaleriabarra    # Get the length of a Vector
3577def3d77Svaleriabarra    def __len__(self):
3587def3d77Svaleriabarra        """Get the length of a Vector.
3597def3d77Svaleriabarra
3607def3d77Svaleriabarra           Returns:
3617def3d77Svaleriabarra             length: length of the Vector"""
3627def3d77Svaleriabarra
3631f9221feSJeremy L Thompson        length_pointer = ffi.new("CeedSize *")
3647def3d77Svaleriabarra
3657def3d77Svaleriabarra        # libCEED call
366477729cfSJeremy L Thompson        err_code = lib.CeedVectorGetLength(self._pointer[0], length_pointer)
367477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
3687def3d77Svaleriabarra
3697def3d77Svaleriabarra        return length_pointer[0]
3707def3d77Svaleriabarra
3717def3d77Svaleriabarra    # Set the Vector to a given constant value
3727def3d77Svaleriabarra    def set_value(self, value):
3737def3d77Svaleriabarra        """Set the Vector to a constant value.
3747def3d77Svaleriabarra
3757def3d77Svaleriabarra           Args:
3767def3d77Svaleriabarra             value: value to be used"""
3777def3d77Svaleriabarra
3787def3d77Svaleriabarra        # libCEED call
379477729cfSJeremy L Thompson        err_code = lib.CeedVectorSetValue(self._pointer[0], value)
380477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
3817def3d77Svaleriabarra
3827def3d77Svaleriabarra    # Sync the Vector to a specified memtype
383547d9b97Sjeremylt    def sync_array(self, memtype=MEM_HOST):
3847def3d77Svaleriabarra        """Sync the Vector to a specified memtype.
3857def3d77Svaleriabarra
3867def3d77Svaleriabarra           Args:
3877def3d77Svaleriabarra             **memtype: memtype to be synced"""
3887def3d77Svaleriabarra
3897def3d77Svaleriabarra        # libCEED call
390477729cfSJeremy L Thompson        err_code = lib.CeedVectorSyncArray(self._pointer[0], memtype)
391477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
3927def3d77Svaleriabarra
393547d9b97Sjeremylt    # Compute the norm of a vector
394547d9b97Sjeremylt    def norm(self, normtype=NORM_2):
395547d9b97Sjeremylt        """Get the norm of a Vector.
396547d9b97Sjeremylt
397547d9b97Sjeremylt           Args:
398547d9b97Sjeremylt             **normtype: type of norm to be computed"""
399547d9b97Sjeremylt
400547d9b97Sjeremylt        norm_pointer = ffi.new("CeedScalar *")
401547d9b97Sjeremylt
402547d9b97Sjeremylt        # libCEED call
403477729cfSJeremy L Thompson        err_code = lib.CeedVectorNorm(self._pointer[0], normtype, norm_pointer)
404477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
405547d9b97Sjeremylt
406547d9b97Sjeremylt        return norm_pointer[0]
407547d9b97Sjeremylt
408d99fa3c5SJeremy L Thompson    # Take the reciprocal of a vector
409d99fa3c5SJeremy L Thompson    def reciprocal(self):
410d99fa3c5SJeremy L Thompson        """Take the reciprocal of a Vector."""
411d99fa3c5SJeremy L Thompson
412d99fa3c5SJeremy L Thompson        # libCEED call
413d99fa3c5SJeremy L Thompson        err_code = lib.CeedVectorReciprocal(self._pointer[0])
414d99fa3c5SJeremy L Thompson        self._ceed._check_error(err_code)
415d99fa3c5SJeremy L Thompson
416d99fa3c5SJeremy L Thompson        return self
417d99fa3c5SJeremy L Thompson
418e0dd3b27Sjeremylt    # Compute self = alpha self
419e0dd3b27Sjeremylt    def scale(self, alpha):
420e0dd3b27Sjeremylt        """Compute self = alpha self."""
421e0dd3b27Sjeremylt
422e0dd3b27Sjeremylt        # libCEED call
423e0dd3b27Sjeremylt        err_code = lib.CeedVectorScale(self._pointer[0], alpha)
424e0dd3b27Sjeremylt        self._ceed._check_error(err_code)
425e0dd3b27Sjeremylt
426e0dd3b27Sjeremylt        return self
427e0dd3b27Sjeremylt
4280c1bc3c2Sjeremylt    # Compute self = alpha x + self
4290c1bc3c2Sjeremylt    def axpy(self, alpha, x):
4300c1bc3c2Sjeremylt        """Compute self = alpha x + self."""
4310c1bc3c2Sjeremylt
4320c1bc3c2Sjeremylt        # libCEED call
4330c1bc3c2Sjeremylt        err_code = lib.CeedVectorAXPY(self._pointer[0], alpha, x._pointer[0])
4340c1bc3c2Sjeremylt        self._ceed._check_error(err_code)
4350c1bc3c2Sjeremylt
4360c1bc3c2Sjeremylt        return self
4370c1bc3c2Sjeremylt
438*5fb68f37SKaren (Ren) Stengel    # Compute self = alpha x + beta self
439*5fb68f37SKaren (Ren) Stengel    def axpby(self, alpha, beta, x):
440*5fb68f37SKaren (Ren) Stengel        """Compute self = alpha x + beta self."""
441*5fb68f37SKaren (Ren) Stengel
442*5fb68f37SKaren (Ren) Stengel        # libCEED call
443*5fb68f37SKaren (Ren) Stengel        err_code = lib.CeedVectorAXPBY(
444*5fb68f37SKaren (Ren) Stengel            self._pointer[0], alpha, beta, x._pointer[0])
445*5fb68f37SKaren (Ren) Stengel        self._ceed._check_error(err_code)
446*5fb68f37SKaren (Ren) Stengel
447*5fb68f37SKaren (Ren) Stengel        return self
448*5fb68f37SKaren (Ren) Stengel
4490c1bc3c2Sjeremylt    # Compute the pointwise multiplication self = x .* y
4500c1bc3c2Sjeremylt    def pointwise_mult(self, x, y):
4510c1bc3c2Sjeremylt        """Compute the pointwise multiplication self = x .* y."""
4520c1bc3c2Sjeremylt
4530c1bc3c2Sjeremylt        # libCEED call
4540c1bc3c2Sjeremylt        err_code = lib.CeedVectorPointwiseMult(
4550c1bc3c2Sjeremylt            self._pointer[0], x._pointer[0], y._pointer[0]
4560c1bc3c2Sjeremylt        )
4570c1bc3c2Sjeremylt        self._ceed._check_error(err_code)
4580c1bc3c2Sjeremylt
4590c1bc3c2Sjeremylt        return self
4600c1bc3c2Sjeremylt
46119798369SJed Brown    def _state(self):
46219798369SJed Brown        """Return the modification state of the Vector.
46319798369SJed Brown
46419798369SJed Brown        State is incremented each time the Vector is mutated, and is odd whenever a
46519798369SJed Brown        mutable reference has not been returned.
46619798369SJed Brown        """
46719798369SJed Brown
46819798369SJed Brown        state_pointer = ffi.new("uint64_t *")
46919798369SJed Brown        err_code = lib.CeedVectorGetState(self._pointer[0], state_pointer)
47019798369SJed Brown        self._ceed._check_error(err_code)
47119798369SJed Brown        return state_pointer[0]
47219798369SJed Brown
4737def3d77Svaleriabarra# ------------------------------------------------------------------------------
4747a7b0fa3SJed Brown
4757a7b0fa3SJed Brown
4767def3d77Svaleriabarraclass _VectorWrap(Vector):
4777def3d77Svaleriabarra    """Wrap a CeedVector pointer in a Vector object."""
4787def3d77Svaleriabarra
4797def3d77Svaleriabarra    # Constructor
4807def3d77Svaleriabarra    def __init__(self, ceed, pointer):
4817def3d77Svaleriabarra        # CeedVector object
4827def3d77Svaleriabarra        self._pointer = pointer
4837def3d77Svaleriabarra
4847def3d77Svaleriabarra        # Reference to Ceed
4857def3d77Svaleriabarra        self._ceed = ceed
4867def3d77Svaleriabarra
4877def3d77Svaleriabarra# ------------------------------------------------------------------------------
488