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