xref: /libCEED/python/ceed_elemrestriction.py (revision 97f7f81f82948b1314e7ca6473cb444b1d0cfe2f)
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 abc import ABC
21from .ceed_constants import REQUEST_IMMEDIATE, REQUEST_ORDERED, MEM_HOST, COPY_VALUES, TRANSPOSE, NOTRANSPOSE, INTERLACED, NONINTERLACED
22from .ceed_vector import _VectorWrap
23
24# ------------------------------------------------------------------------------
25class _ElemRestrictionBase(ABC):
26  """Ceed ElemRestriction: restriction from local vectors to elements."""
27
28  # Attributes
29  _ceed = ffi.NULL
30  _pointer = ffi.NULL
31
32  # Destructor
33  def __del__(self):
34    # libCEED call
35    lib.CeedElemRestrictionDestroy(self._pointer)
36
37  # Representation
38  def __repr__(self):
39    return "<CeedElemRestriction instance at " + hex(id(self)) + ">"
40
41  # String conversion for print() to stdout
42  def __str__(self):
43    """View an ElemRestriction via print()."""
44
45    # libCEED call
46    with tempfile.NamedTemporaryFile() as key_file:
47      with open(key_file.name, 'r+') as stream_file:
48        stream = ffi.cast("FILE *", stream_file)
49
50        lib.CeedElemRestrictionView(self._pointer[0], stream)
51
52        stream_file.seek(0)
53        out_string = stream_file.read()
54
55    return out_string
56
57  # Apply CeedElemRestriction
58  def apply(self, u, v, tmode=NOTRANSPOSE, request=REQUEST_IMMEDIATE):
59    """Restrict a local vector to an element vector or apply its transpose.
60
61       Args:
62         u: input vector
63         v: output vector
64         **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE
65         **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
66
67    # libCEED call
68    lib.CeedElemRestrictionApply(self._pointer[0], tmode, u._pointer[0],
69                                 v._pointer[0], request)
70
71  # Transpose an ElemRestriction
72  @property
73  def T(self):
74    """Transpose an ElemRestriction."""
75
76    return TransposeElemRestriction(self)
77
78  # Transpose an ElemRestriction
79  @property
80  def transpose(self):
81    """Transpose an ElemRestriction."""
82
83    return TransposeElemRestriction(self)
84
85  # Create restriction vectors
86  def create_vector(self, createLvec = True, createEvec = True):
87    """Create Vectors associated with an ElemRestriction.
88
89       Args:
90         **createLvec: flag to create local vector, default True
91         **createEvec: flag to create element vector, default True
92
93       Returns:
94         [lvec, evec]: local vector and element vector, or None if flag set to false"""
95
96    # Vector pointers
97    lvecPointer = ffi.new("CeedVector *") if createLvec else ffi.NULL
98    evecPointer = ffi.new("CeedVector *") if createEvec else ffi.NULL
99
100    # libCEED call
101    lib.CeedElemRestrictionCreateVector(self._pointer[0], lvecPointer,
102                                        evecPointer)
103
104    # Return vectors
105    lvec = _VectorWrap(self._ceed._pointer, lvecPointer) if createLvec else None
106    evec = _VectorWrap(self._ceed._pointer, evecPointer) if createEvec else None
107
108    # Return
109    return [lvec, evec]
110
111  # Get ElemRestriction multiplicity
112  def get_multiplicity(self):
113    """Get the multiplicity of nodes in an ElemRestriction.
114
115       Returns:
116         mult: local vector containing multiplicity of nodes in ElemRestriction"""
117
118    # Create mult vector
119    [mult, evec] = self.create_vector(createEvec = False)
120    mult.set_value(0)
121
122    # libCEED call
123    lib.CeedElemRestrictionGetMultiplicity(self._pointer[0], mult._pointer[0])
124
125    # Return
126    return mult
127
128# ------------------------------------------------------------------------------
129class ElemRestriction(_ElemRestrictionBase):
130  """Ceed ElemRestriction: restriction from local vectors to elements."""
131
132  # Constructor
133  def __init__(self, ceed, nelem, elemsize, nnodes, ncomp, indices,
134               memtype=MEM_HOST, cmode=COPY_VALUES, imode=NONINTERLACED):
135    # CeedVector object
136    self._pointer = ffi.new("CeedElemRestriction *")
137
138    # Reference to Ceed
139    self._ceed = ceed
140
141    # Setup the numpy array for the libCEED call
142    indices_pointer = ffi.new("const CeedInt *")
143    indices_pointer = ffi.cast("const CeedInt *",
144                               indices.__array_interface__['data'][0])
145
146    # libCEED call
147    lib.CeedElemRestrictionCreate(self._ceed._pointer[0], imode, nelem,
148                                  elemsize, nnodes, ncomp, memtype, cmode,
149                                  indices_pointer, self._pointer)
150
151# ------------------------------------------------------------------------------
152class StridedElemRestriction(_ElemRestrictionBase):
153  """Ceed Strided ElemRestriction: strided restriction from local vectors to elements."""
154
155  # Constructor
156  def __init__(self, ceed, nelem, elemsize, nnodes, ncomp, strides):
157    # CeedVector object
158    self._pointer = ffi.new("CeedElemRestriction *")
159
160    # Reference to Ceed
161    self._ceed = ceed
162
163    # Setup the numpy array for the libCEED call
164    strides_pointer = ffi.new("const CeedInt *")
165    strides_pointer = ffi.cast("const CeedInt *",
166                               strides.__array_interface__['data'][0])
167
168    # libCEED call
169    lib.CeedElemRestrictionCreateStrided(self._ceed._pointer[0], nelem,
170                                         elemsize, nnodes, ncomp,
171                                         strides_pointer, self._pointer)
172
173# ------------------------------------------------------------------------------
174class BlockedElemRestriction(_ElemRestrictionBase):
175  """Ceed Blocked ElemRestriction: blocked restriction from local vectors to elements."""
176
177  # Constructor
178  def __init__(self, ceed, nelem, elemsize, blksize, nnodes, ncomp, indices,
179               memtype=MEM_HOST, cmode=COPY_VALUES, imode=NONINTERLACED):
180    # CeedVector object
181    self._pointer = ffi.new("CeedElemRestriction *")
182
183    # Reference to Ceed
184    self._ceed = ceed
185
186    # Setup the numpy array for the libCEED call
187    indices_pointer = ffi.new("const CeedInt *")
188    indices_pointer = ffi.cast("const CeedInt *",
189                               indices.__array_interface__['data'][0])
190
191    # libCEED call
192    lib.CeedElemRestrictionCreateBlocked(self._ceed._pointer[0], imode, nelem,
193                                         elemsize, blksize, nnodes, ncomp,
194                                         memtype, cmode, indices_pointer,
195                                         self._pointer)
196
197  # Transpose a Blocked ElemRestriction
198  @property
199  def T(self):
200    """Transpose a BlockedElemRestriction."""
201
202    return TransposeBlockedElemRestriction(self)
203
204  # Transpose a Blocked ElemRestriction
205  @property
206  def transpose(self):
207    """Transpose a BlockedElemRestriction."""
208
209    return TransposeBlockedElemRestriction(self)
210
211  # Apply CeedElemRestriction to single block
212  def apply_block(self, block, u, v, tmode=NOTRANSPOSE,
213                  request=REQUEST_IMMEDIATE):
214    """Restrict a local vector to a block of an element vector or apply its transpose.
215
216       Args:
217         block: block number to restrict to/from, i.e. block=0 will handle
218                  elements [0 : blksize] and block=3 will handle elements
219                  [3*blksize : 4*blksize]
220         u: input vector
221         v: output vector
222         **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE
223         **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
224
225    # libCEED call
226    lib.CeedElemRestrictionApplyBlock(self._pointer[0], block, tmode,
227                                      u._pointer[0], v._pointer[0], request)
228
229# ------------------------------------------------------------------------------
230class BlockedStridedElemRestriction(BlockedElemRestriction):
231  """Ceed Blocked Strided ElemRestriction: strided restriction from local vectors to elements."""
232
233  # Constructor
234  def __init__(self, ceed, nelem, elemsize, blksize, nnodes, ncomp, strides):
235    # CeedVector object
236    self._pointer = ffi.new("CeedElemRestriction *")
237
238    # Reference to Ceed
239    self._ceed = ceed
240
241    # Setup the numpy array for the libCEED call
242    strides_pointer = ffi.new("const CeedInt *")
243    strides_pointer = ffi.cast("const CeedInt *",
244                               strides.__array_interface__['data'][0])
245
246    # libCEED call
247    lib.CeedElemRestrictionCreateBlockedStrided(self._ceed._pointer[0], nelem,
248                                                elemsize, blksize, nnodes,
249                                                ncomp, strides_pointer,
250                                                self._pointer)
251
252# ------------------------------------------------------------------------------
253class TransposeElemRestriction():
254  """Ceed ElemRestriction: transpose restriction from elements to local vectors."""
255
256  # Attributes
257  _elemrestriction = None
258
259  # Constructor
260  def __init__(self, elemrestriction):
261
262    # Reference elemrestriction
263    self._elemrestriction = elemrestriction
264
265  # Representation
266  def __repr__(self):
267    return "<Transpose CeedElemRestriction instance at " + hex(id(self)) + ">"
268
269
270  # Apply Transpose CeedElemRestriction
271  def apply(self, u, v, request=REQUEST_IMMEDIATE):
272    """Restrict an element vector to a local vector.
273
274       Args:
275         u: input vector
276         v: output vector
277         **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
278
279    # libCEED call
280    self._elemrestriction.apply(u, v, request=request, tmode=TRANSPOSE)
281
282# ------------------------------------------------------------------------------
283class TransposeBlockedElemRestriction(TransposeElemRestriction):
284  """Transpose Ceed Blocked ElemRestriction: blocked transpose restriction from elements
285       to local vectors."""
286
287  # Apply Transpose CeedElemRestriction
288  def apply_block(self, block, u, v, request=REQUEST_IMMEDIATE):
289    """Restrict a block of an element vector to a local vector.
290
291       Args:
292         block: block number to restrict to/from, i.e. block=0 will handle
293                  elements [0 : blksize] and block=3 will handle elements
294                  [3*blksize : 4*blksize]
295         u: input vector
296         v: output vector
297         **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
298
299    # libCEED call
300    self._elemrestriction.apply_block(block, u, v, request=request,
301                                      tmode=TRANSPOSE)
302
303# ------------------------------------------------------------------------------
304