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