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