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