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