xref: /libCEED/python/ceed_elemrestriction.py (revision 3d8e882215d238700cdceb37404f76ca7fa24eaa)
1*3d8e8822SJeremy L Thompson# Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors
2*3d8e8822SJeremy L Thompson# All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3c8e769f6Sjeremylt#
4*3d8e8822SJeremy L Thompson# SPDX-License-Identifier: BSD-2-Clause
5c8e769f6Sjeremylt#
6*3d8e8822SJeremy L Thompson# This file is part of CEED:  http://github.com/ceed
7c8e769f6Sjeremylt
8c8e769f6Sjeremyltfrom _ceed_cffi import ffi, lib
9c8e769f6Sjeremyltimport tempfile
10c8e769f6Sjeremyltimport numpy as np
11c8e769f6Sjeremyltfrom abc import ABC
12187168c7SJeremy L Thompsonfrom .ceed_constants import REQUEST_IMMEDIATE, REQUEST_ORDERED, MEM_HOST, USE_POINTER, COPY_VALUES, TRANSPOSE, NOTRANSPOSE
13c8e769f6Sjeremyltfrom .ceed_vector import _VectorWrap
14c8e769f6Sjeremylt
15c8e769f6Sjeremylt# ------------------------------------------------------------------------------
167a7b0fa3SJed Brown
177a7b0fa3SJed Brown
18c8e769f6Sjeremyltclass _ElemRestrictionBase(ABC):
19c8e769f6Sjeremylt    """Ceed ElemRestriction: restriction from local vectors to elements."""
20c8e769f6Sjeremylt
21c8e769f6Sjeremylt    # Destructor
22c8e769f6Sjeremylt    def __del__(self):
23c8e769f6Sjeremylt        # libCEED call
24477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionDestroy(self._pointer)
25477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
26c8e769f6Sjeremylt
27c8e769f6Sjeremylt    # Representation
28c8e769f6Sjeremylt    def __repr__(self):
29c8e769f6Sjeremylt        return "<CeedElemRestriction instance at " + hex(id(self)) + ">"
30c8e769f6Sjeremylt
31c8e769f6Sjeremylt    # String conversion for print() to stdout
32c8e769f6Sjeremylt    def __str__(self):
33c8e769f6Sjeremylt        """View an ElemRestriction via print()."""
34c8e769f6Sjeremylt
35c8e769f6Sjeremylt        # libCEED call
36c8e769f6Sjeremylt        with tempfile.NamedTemporaryFile() as key_file:
37c8e769f6Sjeremylt            with open(key_file.name, 'r+') as stream_file:
38c8e769f6Sjeremylt                stream = ffi.cast("FILE *", stream_file)
39c8e769f6Sjeremylt
40477729cfSJeremy L Thompson                err_code = lib.CeedElemRestrictionView(self._pointer[0], stream)
41477729cfSJeremy L Thompson                self._ceed._check_error(err_code)
42c8e769f6Sjeremylt
43c8e769f6Sjeremylt                stream_file.seek(0)
44c8e769f6Sjeremylt                out_string = stream_file.read()
45c8e769f6Sjeremylt
46c8e769f6Sjeremylt        return out_string
47c8e769f6Sjeremylt
48c8e769f6Sjeremylt    # Apply CeedElemRestriction
49a8d32208Sjeremylt    def apply(self, u, v, tmode=NOTRANSPOSE, request=REQUEST_IMMEDIATE):
50c8e769f6Sjeremylt        """Restrict a local vector to an element vector or apply its transpose.
51c8e769f6Sjeremylt
52c8e769f6Sjeremylt           Args:
53c8e769f6Sjeremylt             u: input vector
54c8e769f6Sjeremylt             v: output vector
55c8e769f6Sjeremylt             **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE
56c8e769f6Sjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
57c8e769f6Sjeremylt
58c8e769f6Sjeremylt        # libCEED call
59477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionApply(self._pointer[0], tmode, u._pointer[0],
60a8d32208Sjeremylt                                                v._pointer[0], request)
61477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
62c8e769f6Sjeremylt
63c8e769f6Sjeremylt    # Transpose an ElemRestriction
64c8e769f6Sjeremylt    @property
65c8e769f6Sjeremylt    def T(self):
66c8e769f6Sjeremylt        """Transpose an ElemRestriction."""
67c8e769f6Sjeremylt
68c8e769f6Sjeremylt        return TransposeElemRestriction(self)
69c8e769f6Sjeremylt
70c8e769f6Sjeremylt    # Transpose an ElemRestriction
71c8e769f6Sjeremylt    @property
72c8e769f6Sjeremylt    def transpose(self):
73c8e769f6Sjeremylt        """Transpose an ElemRestriction."""
74c8e769f6Sjeremylt
75c8e769f6Sjeremylt        return TransposeElemRestriction(self)
76c8e769f6Sjeremylt
77c8e769f6Sjeremylt    # Create restriction vectors
78c8e769f6Sjeremylt    def create_vector(self, createLvec=True, createEvec=True):
79c8e769f6Sjeremylt        """Create Vectors associated with an ElemRestriction.
80c8e769f6Sjeremylt
81c8e769f6Sjeremylt           Args:
82c8e769f6Sjeremylt             **createLvec: flag to create local vector, default True
83c8e769f6Sjeremylt             **createEvec: flag to create element vector, default True
84c8e769f6Sjeremylt
85c8e769f6Sjeremylt           Returns:
86c8e769f6Sjeremylt             [lvec, evec]: local vector and element vector, or None if flag set to false"""
87c8e769f6Sjeremylt
88c8e769f6Sjeremylt        # Vector pointers
89c8e769f6Sjeremylt        lvecPointer = ffi.new("CeedVector *") if createLvec else ffi.NULL
90c8e769f6Sjeremylt        evecPointer = ffi.new("CeedVector *") if createEvec else ffi.NULL
91c8e769f6Sjeremylt
92c8e769f6Sjeremylt        # libCEED call
93477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionCreateVector(self._pointer[0], lvecPointer,
94c8e769f6Sjeremylt                                                       evecPointer)
95477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
96c8e769f6Sjeremylt
97c8e769f6Sjeremylt        # Return vectors
987a7b0fa3SJed Brown        lvec = _VectorWrap(
99477729cfSJeremy L Thompson            self._ceed, lvecPointer) if createLvec else None
1007a7b0fa3SJed Brown        evec = _VectorWrap(
101477729cfSJeremy L Thompson            self._ceed, evecPointer) if createEvec else None
102c8e769f6Sjeremylt
103c8e769f6Sjeremylt        # Return
104c8e769f6Sjeremylt        return [lvec, evec]
105c8e769f6Sjeremylt
106c8e769f6Sjeremylt    # Get ElemRestriction multiplicity
107a8d32208Sjeremylt    def get_multiplicity(self):
108c8e769f6Sjeremylt        """Get the multiplicity of nodes in an ElemRestriction.
109c8e769f6Sjeremylt
110c8e769f6Sjeremylt           Returns:
111c8e769f6Sjeremylt             mult: local vector containing multiplicity of nodes in ElemRestriction"""
112c8e769f6Sjeremylt
113c8e769f6Sjeremylt        # Create mult vector
114c8e769f6Sjeremylt        [mult, evec] = self.create_vector(createEvec=False)
115c8e769f6Sjeremylt        mult.set_value(0)
116c8e769f6Sjeremylt
117c8e769f6Sjeremylt        # libCEED call
118477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionGetMultiplicity(
1197a7b0fa3SJed Brown            self._pointer[0], mult._pointer[0])
120477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
121c8e769f6Sjeremylt
122c8e769f6Sjeremylt        # Return
123c8e769f6Sjeremylt        return mult
124c8e769f6Sjeremylt
125c3a5a609SJeremy L Thompson    # Get ElemRestrition Layout
126c3a5a609SJeremy L Thompson    def get_layout(self):
127c3a5a609SJeremy L Thompson        """Get the element vector layout of an ElemRestriction.
128c3a5a609SJeremy L Thompson
129c3a5a609SJeremy L Thompson           Returns:
130c3a5a609SJeremy L Thompson             layout: Vector containing layout array, stored as [nodes, components, elements].
131c3a5a609SJeremy L Thompson                     The data for node i, component j, element k in the element
132c3a5a609SJeremy L Thompson                     vector is given by i*layout[0] + j*layout[1] + k*layout[2]."""
133c3a5a609SJeremy L Thompson
134c3a5a609SJeremy L Thompson        # Create output array
135c3a5a609SJeremy L Thompson        layout = np.zeros(3, dtype="int32")
136c3a5a609SJeremy L Thompson        array_pointer = ffi.cast(
137c3a5a609SJeremy L Thompson            "CeedInt *",
138c3a5a609SJeremy L Thompson            layout.__array_interface__['data'][0])
139c3a5a609SJeremy L Thompson
140c3a5a609SJeremy L Thompson        # libCEED call
141c3a5a609SJeremy L Thompson        err_code = lib.CeedElemRestrictionGetELayout(
142c3a5a609SJeremy L Thompson            self._pointer[0], array_pointer)
143c3a5a609SJeremy L Thompson        self._ceed._check_error(err_code)
144c3a5a609SJeremy L Thompson
145c3a5a609SJeremy L Thompson        # Return
146c3a5a609SJeremy L Thompson        return layout
147c3a5a609SJeremy L Thompson
148c8e769f6Sjeremylt# ------------------------------------------------------------------------------
1497a7b0fa3SJed Brown
1507a7b0fa3SJed Brown
151c8e769f6Sjeremyltclass ElemRestriction(_ElemRestrictionBase):
152c8e769f6Sjeremylt    """Ceed ElemRestriction: restriction from local vectors to elements."""
153c8e769f6Sjeremylt
154c8e769f6Sjeremylt    # Constructor
155d979a051Sjeremylt    def __init__(self, ceed, nelem, elemsize, ncomp, compstride, lsize, offsets,
156d979a051Sjeremylt                 memtype=MEM_HOST, cmode=COPY_VALUES):
157c8e769f6Sjeremylt        # CeedVector object
158c8e769f6Sjeremylt        self._pointer = ffi.new("CeedElemRestriction *")
159c8e769f6Sjeremylt
160c8e769f6Sjeremylt        # Reference to Ceed
161c8e769f6Sjeremylt        self._ceed = ceed
162c8e769f6Sjeremylt
163187168c7SJeremy L Thompson        # Store array reference if needed
164187168c7SJeremy L Thompson        if cmode == USE_POINTER:
165187168c7SJeremy L Thompson            self._array_reference = offsets
166187168c7SJeremy L Thompson        else:
167187168c7SJeremy L Thompson            self._array_reference = None
168187168c7SJeremy L Thompson
169c8e769f6Sjeremylt        # Setup the numpy array for the libCEED call
170d979a051Sjeremylt        offsets_pointer = ffi.new("const CeedInt *")
171d979a051Sjeremylt        offsets_pointer = ffi.cast("const CeedInt *",
172d979a051Sjeremylt                                   offsets.__array_interface__['data'][0])
173c8e769f6Sjeremylt
174c8e769f6Sjeremylt        # libCEED call
175477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionCreate(self._ceed._pointer[0], nelem,
176477729cfSJeremy L Thompson                                                 elemsize, ncomp, compstride,
177477729cfSJeremy L Thompson                                                 lsize, memtype, cmode,
178d979a051Sjeremylt                                                 offsets_pointer, self._pointer)
179477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
180c8e769f6Sjeremylt
181c8e769f6Sjeremylt# ------------------------------------------------------------------------------
1827a7b0fa3SJed Brown
1837a7b0fa3SJed Brown
18469a53589Sjeremyltclass StridedElemRestriction(_ElemRestrictionBase):
18569a53589Sjeremylt    """Ceed Strided ElemRestriction: strided restriction from local vectors to elements."""
186c8e769f6Sjeremylt
187c8e769f6Sjeremylt    # Constructor
188d979a051Sjeremylt    def __init__(self, ceed, nelem, elemsize, ncomp, lsize, strides):
189c8e769f6Sjeremylt        # CeedVector object
190c8e769f6Sjeremylt        self._pointer = ffi.new("CeedElemRestriction *")
191c8e769f6Sjeremylt
192c8e769f6Sjeremylt        # Reference to Ceed
193c8e769f6Sjeremylt        self._ceed = ceed
194c8e769f6Sjeremylt
19569a53589Sjeremylt        # Setup the numpy array for the libCEED call
19669a53589Sjeremylt        strides_pointer = ffi.new("const CeedInt *")
19769a53589Sjeremylt        strides_pointer = ffi.cast("const CeedInt *",
19869a53589Sjeremylt                                   strides.__array_interface__['data'][0])
19969a53589Sjeremylt
200c8e769f6Sjeremylt        # libCEED call
201477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionCreateStrided(self._ceed._pointer[0],
202477729cfSJeremy L Thompson                                                        nelem, elemsize, ncomp,
203477729cfSJeremy L Thompson                                                        lsize, strides_pointer,
204477729cfSJeremy L Thompson                                                        self._pointer)
205477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
206c8e769f6Sjeremylt
207c8e769f6Sjeremylt# ------------------------------------------------------------------------------
2087a7b0fa3SJed Brown
2097a7b0fa3SJed Brown
210c8e769f6Sjeremyltclass BlockedElemRestriction(_ElemRestrictionBase):
211c8e769f6Sjeremylt    """Ceed Blocked ElemRestriction: blocked restriction from local vectors to elements."""
212c8e769f6Sjeremylt
213c8e769f6Sjeremylt    # Constructor
214d979a051Sjeremylt    def __init__(self, ceed, nelem, elemsize, blksize, ncomp, compstride, lsize,
215d979a051Sjeremylt                 offsets, memtype=MEM_HOST, cmode=COPY_VALUES):
216c8e769f6Sjeremylt        # CeedVector object
217c8e769f6Sjeremylt        self._pointer = ffi.new("CeedElemRestriction *")
218c8e769f6Sjeremylt
219c8e769f6Sjeremylt        # Reference to Ceed
220c8e769f6Sjeremylt        self._ceed = ceed
221c8e769f6Sjeremylt
222c8e769f6Sjeremylt        # Setup the numpy array for the libCEED call
223d979a051Sjeremylt        offsets_pointer = ffi.new("const CeedInt *")
224d979a051Sjeremylt        offsets_pointer = ffi.cast("const CeedInt *",
225d979a051Sjeremylt                                   offsets.__array_interface__['data'][0])
226c8e769f6Sjeremylt
227c8e769f6Sjeremylt        # libCEED call
228477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionCreateBlocked(self._ceed._pointer[0], nelem,
229d979a051Sjeremylt                                                        elemsize, blksize, ncomp,
230d979a051Sjeremylt                                                        compstride, lsize, memtype, cmode,
231d979a051Sjeremylt                                                        offsets_pointer, self._pointer)
232477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
233c8e769f6Sjeremylt
234c8e769f6Sjeremylt    # Transpose a Blocked ElemRestriction
235c8e769f6Sjeremylt    @property
236c8e769f6Sjeremylt    def T(self):
237c8e769f6Sjeremylt        """Transpose a BlockedElemRestriction."""
238c8e769f6Sjeremylt
239c8e769f6Sjeremylt        return TransposeBlockedElemRestriction(self)
240c8e769f6Sjeremylt
241c8e769f6Sjeremylt    # Transpose a Blocked ElemRestriction
242c8e769f6Sjeremylt    @property
243c8e769f6Sjeremylt    def transpose(self):
244c8e769f6Sjeremylt        """Transpose a BlockedElemRestriction."""
245c8e769f6Sjeremylt
246c8e769f6Sjeremylt        return TransposeBlockedElemRestriction(self)
247c8e769f6Sjeremylt
248c8e769f6Sjeremylt    # Apply CeedElemRestriction to single block
249a8d32208Sjeremylt    def apply_block(self, block, u, v, tmode=NOTRANSPOSE,
250c8e769f6Sjeremylt                    request=REQUEST_IMMEDIATE):
251c8e769f6Sjeremylt        """Restrict a local vector to a block of an element vector or apply its transpose.
252c8e769f6Sjeremylt
253c8e769f6Sjeremylt           Args:
254c8e769f6Sjeremylt             block: block number to restrict to/from, i.e. block=0 will handle
255c8e769f6Sjeremylt                      elements [0 : blksize] and block=3 will handle elements
256c8e769f6Sjeremylt                      [3*blksize : 4*blksize]
257c8e769f6Sjeremylt             u: input vector
258c8e769f6Sjeremylt             v: output vector
259c8e769f6Sjeremylt             **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE
260c8e769f6Sjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
261c8e769f6Sjeremylt
262c8e769f6Sjeremylt        # libCEED call
263477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionApplyBlock(self._pointer[0], block, tmode,
264477729cfSJeremy L Thompson                                                     u._pointer[0], v._pointer[0],
265477729cfSJeremy L Thompson                                                     request)
266477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
267c8e769f6Sjeremylt
268c8e769f6Sjeremylt# ------------------------------------------------------------------------------
2697a7b0fa3SJed Brown
2707a7b0fa3SJed Brown
27169a53589Sjeremyltclass BlockedStridedElemRestriction(BlockedElemRestriction):
27269a53589Sjeremylt    """Ceed Blocked Strided ElemRestriction: strided restriction from local vectors to elements."""
27369a53589Sjeremylt
27469a53589Sjeremylt    # Constructor
275d979a051Sjeremylt    def __init__(self, ceed, nelem, elemsize, blksize, ncomp, lsize, strides):
27669a53589Sjeremylt        # CeedVector object
27769a53589Sjeremylt        self._pointer = ffi.new("CeedElemRestriction *")
27869a53589Sjeremylt
27969a53589Sjeremylt        # Reference to Ceed
28069a53589Sjeremylt        self._ceed = ceed
28169a53589Sjeremylt
28269a53589Sjeremylt        # Setup the numpy array for the libCEED call
28369a53589Sjeremylt        strides_pointer = ffi.new("const CeedInt *")
28469a53589Sjeremylt        strides_pointer = ffi.cast("const CeedInt *",
28569a53589Sjeremylt                                   strides.__array_interface__['data'][0])
28669a53589Sjeremylt
28769a53589Sjeremylt        # libCEED call
288477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionCreateBlockedStrided(self._ceed._pointer[0], nelem,
289d979a051Sjeremylt                                                               elemsize, blksize, ncomp,
290d979a051Sjeremylt                                                               lsize, strides_pointer,
29169a53589Sjeremylt                                                               self._pointer)
292477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
29369a53589Sjeremylt
29469a53589Sjeremylt# ------------------------------------------------------------------------------
2957a7b0fa3SJed Brown
2967a7b0fa3SJed Brown
297c8e769f6Sjeremyltclass TransposeElemRestriction():
298c8e769f6Sjeremylt    """Ceed ElemRestriction: transpose restriction from elements to local vectors."""
299c8e769f6Sjeremylt
300c8e769f6Sjeremylt    # Attributes
301c8e769f6Sjeremylt    _elemrestriction = None
302c8e769f6Sjeremylt
303c8e769f6Sjeremylt    # Constructor
304c8e769f6Sjeremylt    def __init__(self, elemrestriction):
305c8e769f6Sjeremylt
306c8e769f6Sjeremylt        # Reference elemrestriction
307c8e769f6Sjeremylt        self._elemrestriction = elemrestriction
308c8e769f6Sjeremylt
309c8e769f6Sjeremylt    # Representation
310c8e769f6Sjeremylt    def __repr__(self):
3117a7b0fa3SJed Brown        return "<Transpose CeedElemRestriction instance at " + \
3127a7b0fa3SJed Brown            hex(id(self)) + ">"
313c8e769f6Sjeremylt
314c8e769f6Sjeremylt    # Apply Transpose CeedElemRestriction
3157a7b0fa3SJed Brown
316a8d32208Sjeremylt    def apply(self, u, v, request=REQUEST_IMMEDIATE):
317c8e769f6Sjeremylt        """Restrict an element vector to a local vector.
318c8e769f6Sjeremylt
319c8e769f6Sjeremylt           Args:
320c8e769f6Sjeremylt             u: input vector
321c8e769f6Sjeremylt             v: output vector
322c8e769f6Sjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
323c8e769f6Sjeremylt
324c8e769f6Sjeremylt        # libCEED call
325a8d32208Sjeremylt        self._elemrestriction.apply(u, v, request=request, tmode=TRANSPOSE)
326c8e769f6Sjeremylt
327c8e769f6Sjeremylt# ------------------------------------------------------------------------------
3287a7b0fa3SJed Brown
3297a7b0fa3SJed Brown
330c8e769f6Sjeremyltclass TransposeBlockedElemRestriction(TransposeElemRestriction):
331c8e769f6Sjeremylt    """Transpose Ceed Blocked ElemRestriction: blocked transpose restriction from elements
332c8e769f6Sjeremylt         to local vectors."""
333c8e769f6Sjeremylt
334c8e769f6Sjeremylt    # Apply Transpose CeedElemRestriction
335a8d32208Sjeremylt    def apply_block(self, block, u, v, request=REQUEST_IMMEDIATE):
336c8e769f6Sjeremylt        """Restrict a block of an element vector to a local vector.
337c8e769f6Sjeremylt
338c8e769f6Sjeremylt           Args:
339c8e769f6Sjeremylt             block: block number to restrict to/from, i.e. block=0 will handle
340c8e769f6Sjeremylt                      elements [0 : blksize] and block=3 will handle elements
341c8e769f6Sjeremylt                      [3*blksize : 4*blksize]
342c8e769f6Sjeremylt             u: input vector
343c8e769f6Sjeremylt             v: output vector
344c8e769f6Sjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
345c8e769f6Sjeremylt
346c8e769f6Sjeremylt        # libCEED call
347a8d32208Sjeremylt        self._elemrestriction.apply_block(block, u, v, request=request,
348c8e769f6Sjeremylt                                          tmode=TRANSPOSE)
349c8e769f6Sjeremylt
350c8e769f6Sjeremylt# ------------------------------------------------------------------------------
351