xref: /libCEED/python/ceed_elemrestriction.py (revision c3a5a6094aa370d9b1d225615082a3e1f73f831f) !
1c8e769f6Sjeremylt# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2c8e769f6Sjeremylt# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3c8e769f6Sjeremylt# reserved. See files LICENSE and NOTICE for details.
4c8e769f6Sjeremylt#
5c8e769f6Sjeremylt# This file is part of CEED, a collection of benchmarks, miniapps, software
6c8e769f6Sjeremylt# libraries and APIs for efficient high-order finite element and spectral
7c8e769f6Sjeremylt# element discretizations for exascale applications. For more information and
8c8e769f6Sjeremylt# source code availability see http://github.com/ceed.
9c8e769f6Sjeremylt#
10c8e769f6Sjeremylt# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11c8e769f6Sjeremylt# a collaborative effort of two U.S. Department of Energy organizations (Office
12c8e769f6Sjeremylt# of Science and the National Nuclear Security Administration) responsible for
13c8e769f6Sjeremylt# the planning and preparation of a capable exascale ecosystem, including
14c8e769f6Sjeremylt# software, applications, hardware, advanced system engineering and early
15c8e769f6Sjeremylt# testbed platforms, in support of the nation's exascale computing imperative.
16c8e769f6Sjeremylt
17c8e769f6Sjeremyltfrom _ceed_cffi import ffi, lib
18c8e769f6Sjeremyltimport tempfile
19c8e769f6Sjeremyltimport numpy as np
20c8e769f6Sjeremyltfrom abc import ABC
21187168c7SJeremy L Thompsonfrom .ceed_constants import REQUEST_IMMEDIATE, REQUEST_ORDERED, MEM_HOST, USE_POINTER, COPY_VALUES, TRANSPOSE, NOTRANSPOSE
22c8e769f6Sjeremyltfrom .ceed_vector import _VectorWrap
23c8e769f6Sjeremylt
24c8e769f6Sjeremylt# ------------------------------------------------------------------------------
257a7b0fa3SJed Brown
267a7b0fa3SJed Brown
27c8e769f6Sjeremyltclass _ElemRestrictionBase(ABC):
28c8e769f6Sjeremylt    """Ceed ElemRestriction: restriction from local vectors to elements."""
29c8e769f6Sjeremylt
30c8e769f6Sjeremylt    # Destructor
31c8e769f6Sjeremylt    def __del__(self):
32c8e769f6Sjeremylt        # libCEED call
33477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionDestroy(self._pointer)
34477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
35c8e769f6Sjeremylt
36c8e769f6Sjeremylt    # Representation
37c8e769f6Sjeremylt    def __repr__(self):
38c8e769f6Sjeremylt        return "<CeedElemRestriction instance at " + hex(id(self)) + ">"
39c8e769f6Sjeremylt
40c8e769f6Sjeremylt    # String conversion for print() to stdout
41c8e769f6Sjeremylt    def __str__(self):
42c8e769f6Sjeremylt        """View an ElemRestriction via print()."""
43c8e769f6Sjeremylt
44c8e769f6Sjeremylt        # libCEED call
45c8e769f6Sjeremylt        with tempfile.NamedTemporaryFile() as key_file:
46c8e769f6Sjeremylt            with open(key_file.name, 'r+') as stream_file:
47c8e769f6Sjeremylt                stream = ffi.cast("FILE *", stream_file)
48c8e769f6Sjeremylt
49477729cfSJeremy L Thompson                err_code = lib.CeedElemRestrictionView(self._pointer[0], stream)
50477729cfSJeremy L Thompson                self._ceed._check_error(err_code)
51c8e769f6Sjeremylt
52c8e769f6Sjeremylt                stream_file.seek(0)
53c8e769f6Sjeremylt                out_string = stream_file.read()
54c8e769f6Sjeremylt
55c8e769f6Sjeremylt        return out_string
56c8e769f6Sjeremylt
57c8e769f6Sjeremylt    # Apply CeedElemRestriction
58a8d32208Sjeremylt    def apply(self, u, v, tmode=NOTRANSPOSE, request=REQUEST_IMMEDIATE):
59c8e769f6Sjeremylt        """Restrict a local vector to an element vector or apply its transpose.
60c8e769f6Sjeremylt
61c8e769f6Sjeremylt           Args:
62c8e769f6Sjeremylt             u: input vector
63c8e769f6Sjeremylt             v: output vector
64c8e769f6Sjeremylt             **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE
65c8e769f6Sjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
66c8e769f6Sjeremylt
67c8e769f6Sjeremylt        # libCEED call
68477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionApply(self._pointer[0], tmode, u._pointer[0],
69a8d32208Sjeremylt                                                v._pointer[0], request)
70477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
71c8e769f6Sjeremylt
72c8e769f6Sjeremylt    # Transpose an ElemRestriction
73c8e769f6Sjeremylt    @property
74c8e769f6Sjeremylt    def T(self):
75c8e769f6Sjeremylt        """Transpose an ElemRestriction."""
76c8e769f6Sjeremylt
77c8e769f6Sjeremylt        return TransposeElemRestriction(self)
78c8e769f6Sjeremylt
79c8e769f6Sjeremylt    # Transpose an ElemRestriction
80c8e769f6Sjeremylt    @property
81c8e769f6Sjeremylt    def transpose(self):
82c8e769f6Sjeremylt        """Transpose an ElemRestriction."""
83c8e769f6Sjeremylt
84c8e769f6Sjeremylt        return TransposeElemRestriction(self)
85c8e769f6Sjeremylt
86c8e769f6Sjeremylt    # Create restriction vectors
87c8e769f6Sjeremylt    def create_vector(self, createLvec=True, createEvec=True):
88c8e769f6Sjeremylt        """Create Vectors associated with an ElemRestriction.
89c8e769f6Sjeremylt
90c8e769f6Sjeremylt           Args:
91c8e769f6Sjeremylt             **createLvec: flag to create local vector, default True
92c8e769f6Sjeremylt             **createEvec: flag to create element vector, default True
93c8e769f6Sjeremylt
94c8e769f6Sjeremylt           Returns:
95c8e769f6Sjeremylt             [lvec, evec]: local vector and element vector, or None if flag set to false"""
96c8e769f6Sjeremylt
97c8e769f6Sjeremylt        # Vector pointers
98c8e769f6Sjeremylt        lvecPointer = ffi.new("CeedVector *") if createLvec else ffi.NULL
99c8e769f6Sjeremylt        evecPointer = ffi.new("CeedVector *") if createEvec else ffi.NULL
100c8e769f6Sjeremylt
101c8e769f6Sjeremylt        # libCEED call
102477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionCreateVector(self._pointer[0], lvecPointer,
103c8e769f6Sjeremylt                                                       evecPointer)
104477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
105c8e769f6Sjeremylt
106c8e769f6Sjeremylt        # Return vectors
1077a7b0fa3SJed Brown        lvec = _VectorWrap(
108477729cfSJeremy L Thompson            self._ceed, lvecPointer) if createLvec else None
1097a7b0fa3SJed Brown        evec = _VectorWrap(
110477729cfSJeremy L Thompson            self._ceed, evecPointer) if createEvec else None
111c8e769f6Sjeremylt
112c8e769f6Sjeremylt        # Return
113c8e769f6Sjeremylt        return [lvec, evec]
114c8e769f6Sjeremylt
115c8e769f6Sjeremylt    # Get ElemRestriction multiplicity
116a8d32208Sjeremylt    def get_multiplicity(self):
117c8e769f6Sjeremylt        """Get the multiplicity of nodes in an ElemRestriction.
118c8e769f6Sjeremylt
119c8e769f6Sjeremylt           Returns:
120c8e769f6Sjeremylt             mult: local vector containing multiplicity of nodes in ElemRestriction"""
121c8e769f6Sjeremylt
122c8e769f6Sjeremylt        # Create mult vector
123c8e769f6Sjeremylt        [mult, evec] = self.create_vector(createEvec=False)
124c8e769f6Sjeremylt        mult.set_value(0)
125c8e769f6Sjeremylt
126c8e769f6Sjeremylt        # libCEED call
127477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionGetMultiplicity(
1287a7b0fa3SJed Brown            self._pointer[0], mult._pointer[0])
129477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
130c8e769f6Sjeremylt
131c8e769f6Sjeremylt        # Return
132c8e769f6Sjeremylt        return mult
133c8e769f6Sjeremylt
134*c3a5a609SJeremy L Thompson    # Get ElemRestrition Layout
135*c3a5a609SJeremy L Thompson    def get_layout(self):
136*c3a5a609SJeremy L Thompson        """Get the element vector layout of an ElemRestriction.
137*c3a5a609SJeremy L Thompson
138*c3a5a609SJeremy L Thompson           Returns:
139*c3a5a609SJeremy L Thompson             layout: Vector containing layout array, stored as [nodes, components, elements].
140*c3a5a609SJeremy L Thompson                     The data for node i, component j, element k in the element
141*c3a5a609SJeremy L Thompson                     vector is given by i*layout[0] + j*layout[1] + k*layout[2]."""
142*c3a5a609SJeremy L Thompson
143*c3a5a609SJeremy L Thompson        # Create output array
144*c3a5a609SJeremy L Thompson        layout = np.zeros(3, dtype="int32")
145*c3a5a609SJeremy L Thompson        array_pointer = ffi.cast(
146*c3a5a609SJeremy L Thompson            "CeedInt *",
147*c3a5a609SJeremy L Thompson            layout.__array_interface__['data'][0])
148*c3a5a609SJeremy L Thompson
149*c3a5a609SJeremy L Thompson        # libCEED call
150*c3a5a609SJeremy L Thompson        err_code = lib.CeedElemRestrictionGetELayout(
151*c3a5a609SJeremy L Thompson            self._pointer[0], array_pointer)
152*c3a5a609SJeremy L Thompson        self._ceed._check_error(err_code)
153*c3a5a609SJeremy L Thompson
154*c3a5a609SJeremy L Thompson        # Return
155*c3a5a609SJeremy L Thompson        return layout
156*c3a5a609SJeremy L Thompson
157c8e769f6Sjeremylt# ------------------------------------------------------------------------------
1587a7b0fa3SJed Brown
1597a7b0fa3SJed Brown
160c8e769f6Sjeremyltclass ElemRestriction(_ElemRestrictionBase):
161c8e769f6Sjeremylt    """Ceed ElemRestriction: restriction from local vectors to elements."""
162c8e769f6Sjeremylt
163c8e769f6Sjeremylt    # Constructor
164d979a051Sjeremylt    def __init__(self, ceed, nelem, elemsize, ncomp, compstride, lsize, offsets,
165d979a051Sjeremylt                 memtype=MEM_HOST, cmode=COPY_VALUES):
166c8e769f6Sjeremylt        # CeedVector object
167c8e769f6Sjeremylt        self._pointer = ffi.new("CeedElemRestriction *")
168c8e769f6Sjeremylt
169c8e769f6Sjeremylt        # Reference to Ceed
170c8e769f6Sjeremylt        self._ceed = ceed
171c8e769f6Sjeremylt
172187168c7SJeremy L Thompson        # Store array reference if needed
173187168c7SJeremy L Thompson        if cmode == USE_POINTER:
174187168c7SJeremy L Thompson            self._array_reference = offsets
175187168c7SJeremy L Thompson        else:
176187168c7SJeremy L Thompson            self._array_reference = None
177187168c7SJeremy L Thompson
178c8e769f6Sjeremylt        # Setup the numpy array for the libCEED call
179d979a051Sjeremylt        offsets_pointer = ffi.new("const CeedInt *")
180d979a051Sjeremylt        offsets_pointer = ffi.cast("const CeedInt *",
181d979a051Sjeremylt                                   offsets.__array_interface__['data'][0])
182c8e769f6Sjeremylt
183c8e769f6Sjeremylt        # libCEED call
184477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionCreate(self._ceed._pointer[0], nelem,
185477729cfSJeremy L Thompson                                                 elemsize, ncomp, compstride,
186477729cfSJeremy L Thompson                                                 lsize, memtype, cmode,
187d979a051Sjeremylt                                                 offsets_pointer, self._pointer)
188477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
189c8e769f6Sjeremylt
190c8e769f6Sjeremylt# ------------------------------------------------------------------------------
1917a7b0fa3SJed Brown
1927a7b0fa3SJed Brown
19369a53589Sjeremyltclass StridedElemRestriction(_ElemRestrictionBase):
19469a53589Sjeremylt    """Ceed Strided ElemRestriction: strided restriction from local vectors to elements."""
195c8e769f6Sjeremylt
196c8e769f6Sjeremylt    # Constructor
197d979a051Sjeremylt    def __init__(self, ceed, nelem, elemsize, ncomp, lsize, strides):
198c8e769f6Sjeremylt        # CeedVector object
199c8e769f6Sjeremylt        self._pointer = ffi.new("CeedElemRestriction *")
200c8e769f6Sjeremylt
201c8e769f6Sjeremylt        # Reference to Ceed
202c8e769f6Sjeremylt        self._ceed = ceed
203c8e769f6Sjeremylt
20469a53589Sjeremylt        # Setup the numpy array for the libCEED call
20569a53589Sjeremylt        strides_pointer = ffi.new("const CeedInt *")
20669a53589Sjeremylt        strides_pointer = ffi.cast("const CeedInt *",
20769a53589Sjeremylt                                   strides.__array_interface__['data'][0])
20869a53589Sjeremylt
209c8e769f6Sjeremylt        # libCEED call
210477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionCreateStrided(self._ceed._pointer[0],
211477729cfSJeremy L Thompson                                                        nelem, elemsize, ncomp,
212477729cfSJeremy L Thompson                                                        lsize, strides_pointer,
213477729cfSJeremy L Thompson                                                        self._pointer)
214477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
215c8e769f6Sjeremylt
216c8e769f6Sjeremylt# ------------------------------------------------------------------------------
2177a7b0fa3SJed Brown
2187a7b0fa3SJed Brown
219c8e769f6Sjeremyltclass BlockedElemRestriction(_ElemRestrictionBase):
220c8e769f6Sjeremylt    """Ceed Blocked ElemRestriction: blocked restriction from local vectors to elements."""
221c8e769f6Sjeremylt
222c8e769f6Sjeremylt    # Constructor
223d979a051Sjeremylt    def __init__(self, ceed, nelem, elemsize, blksize, ncomp, compstride, lsize,
224d979a051Sjeremylt                 offsets, memtype=MEM_HOST, cmode=COPY_VALUES):
225c8e769f6Sjeremylt        # CeedVector object
226c8e769f6Sjeremylt        self._pointer = ffi.new("CeedElemRestriction *")
227c8e769f6Sjeremylt
228c8e769f6Sjeremylt        # Reference to Ceed
229c8e769f6Sjeremylt        self._ceed = ceed
230c8e769f6Sjeremylt
231c8e769f6Sjeremylt        # Setup the numpy array for the libCEED call
232d979a051Sjeremylt        offsets_pointer = ffi.new("const CeedInt *")
233d979a051Sjeremylt        offsets_pointer = ffi.cast("const CeedInt *",
234d979a051Sjeremylt                                   offsets.__array_interface__['data'][0])
235c8e769f6Sjeremylt
236c8e769f6Sjeremylt        # libCEED call
237477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionCreateBlocked(self._ceed._pointer[0], nelem,
238d979a051Sjeremylt                                                        elemsize, blksize, ncomp,
239d979a051Sjeremylt                                                        compstride, lsize, memtype, cmode,
240d979a051Sjeremylt                                                        offsets_pointer, self._pointer)
241477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
242c8e769f6Sjeremylt
243c8e769f6Sjeremylt    # Transpose a Blocked ElemRestriction
244c8e769f6Sjeremylt    @property
245c8e769f6Sjeremylt    def T(self):
246c8e769f6Sjeremylt        """Transpose a BlockedElemRestriction."""
247c8e769f6Sjeremylt
248c8e769f6Sjeremylt        return TransposeBlockedElemRestriction(self)
249c8e769f6Sjeremylt
250c8e769f6Sjeremylt    # Transpose a Blocked ElemRestriction
251c8e769f6Sjeremylt    @property
252c8e769f6Sjeremylt    def transpose(self):
253c8e769f6Sjeremylt        """Transpose a BlockedElemRestriction."""
254c8e769f6Sjeremylt
255c8e769f6Sjeremylt        return TransposeBlockedElemRestriction(self)
256c8e769f6Sjeremylt
257c8e769f6Sjeremylt    # Apply CeedElemRestriction to single block
258a8d32208Sjeremylt    def apply_block(self, block, u, v, tmode=NOTRANSPOSE,
259c8e769f6Sjeremylt                    request=REQUEST_IMMEDIATE):
260c8e769f6Sjeremylt        """Restrict a local vector to a block of an element vector or apply its transpose.
261c8e769f6Sjeremylt
262c8e769f6Sjeremylt           Args:
263c8e769f6Sjeremylt             block: block number to restrict to/from, i.e. block=0 will handle
264c8e769f6Sjeremylt                      elements [0 : blksize] and block=3 will handle elements
265c8e769f6Sjeremylt                      [3*blksize : 4*blksize]
266c8e769f6Sjeremylt             u: input vector
267c8e769f6Sjeremylt             v: output vector
268c8e769f6Sjeremylt             **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE
269c8e769f6Sjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
270c8e769f6Sjeremylt
271c8e769f6Sjeremylt        # libCEED call
272477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionApplyBlock(self._pointer[0], block, tmode,
273477729cfSJeremy L Thompson                                                     u._pointer[0], v._pointer[0],
274477729cfSJeremy L Thompson                                                     request)
275477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
276c8e769f6Sjeremylt
277c8e769f6Sjeremylt# ------------------------------------------------------------------------------
2787a7b0fa3SJed Brown
2797a7b0fa3SJed Brown
28069a53589Sjeremyltclass BlockedStridedElemRestriction(BlockedElemRestriction):
28169a53589Sjeremylt    """Ceed Blocked Strided ElemRestriction: strided restriction from local vectors to elements."""
28269a53589Sjeremylt
28369a53589Sjeremylt    # Constructor
284d979a051Sjeremylt    def __init__(self, ceed, nelem, elemsize, blksize, ncomp, lsize, strides):
28569a53589Sjeremylt        # CeedVector object
28669a53589Sjeremylt        self._pointer = ffi.new("CeedElemRestriction *")
28769a53589Sjeremylt
28869a53589Sjeremylt        # Reference to Ceed
28969a53589Sjeremylt        self._ceed = ceed
29069a53589Sjeremylt
29169a53589Sjeremylt        # Setup the numpy array for the libCEED call
29269a53589Sjeremylt        strides_pointer = ffi.new("const CeedInt *")
29369a53589Sjeremylt        strides_pointer = ffi.cast("const CeedInt *",
29469a53589Sjeremylt                                   strides.__array_interface__['data'][0])
29569a53589Sjeremylt
29669a53589Sjeremylt        # libCEED call
297477729cfSJeremy L Thompson        err_code = lib.CeedElemRestrictionCreateBlockedStrided(self._ceed._pointer[0], nelem,
298d979a051Sjeremylt                                                               elemsize, blksize, ncomp,
299d979a051Sjeremylt                                                               lsize, strides_pointer,
30069a53589Sjeremylt                                                               self._pointer)
301477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
30269a53589Sjeremylt
30369a53589Sjeremylt# ------------------------------------------------------------------------------
3047a7b0fa3SJed Brown
3057a7b0fa3SJed Brown
306c8e769f6Sjeremyltclass TransposeElemRestriction():
307c8e769f6Sjeremylt    """Ceed ElemRestriction: transpose restriction from elements to local vectors."""
308c8e769f6Sjeremylt
309c8e769f6Sjeremylt    # Attributes
310c8e769f6Sjeremylt    _elemrestriction = None
311c8e769f6Sjeremylt
312c8e769f6Sjeremylt    # Constructor
313c8e769f6Sjeremylt    def __init__(self, elemrestriction):
314c8e769f6Sjeremylt
315c8e769f6Sjeremylt        # Reference elemrestriction
316c8e769f6Sjeremylt        self._elemrestriction = elemrestriction
317c8e769f6Sjeremylt
318c8e769f6Sjeremylt    # Representation
319c8e769f6Sjeremylt    def __repr__(self):
3207a7b0fa3SJed Brown        return "<Transpose CeedElemRestriction instance at " + \
3217a7b0fa3SJed Brown            hex(id(self)) + ">"
322c8e769f6Sjeremylt
323c8e769f6Sjeremylt    # Apply Transpose CeedElemRestriction
3247a7b0fa3SJed Brown
325a8d32208Sjeremylt    def apply(self, u, v, request=REQUEST_IMMEDIATE):
326c8e769f6Sjeremylt        """Restrict an element vector to a local vector.
327c8e769f6Sjeremylt
328c8e769f6Sjeremylt           Args:
329c8e769f6Sjeremylt             u: input vector
330c8e769f6Sjeremylt             v: output vector
331c8e769f6Sjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
332c8e769f6Sjeremylt
333c8e769f6Sjeremylt        # libCEED call
334a8d32208Sjeremylt        self._elemrestriction.apply(u, v, request=request, tmode=TRANSPOSE)
335c8e769f6Sjeremylt
336c8e769f6Sjeremylt# ------------------------------------------------------------------------------
3377a7b0fa3SJed Brown
3387a7b0fa3SJed Brown
339c8e769f6Sjeremyltclass TransposeBlockedElemRestriction(TransposeElemRestriction):
340c8e769f6Sjeremylt    """Transpose Ceed Blocked ElemRestriction: blocked transpose restriction from elements
341c8e769f6Sjeremylt         to local vectors."""
342c8e769f6Sjeremylt
343c8e769f6Sjeremylt    # Apply Transpose CeedElemRestriction
344a8d32208Sjeremylt    def apply_block(self, block, u, v, request=REQUEST_IMMEDIATE):
345c8e769f6Sjeremylt        """Restrict a block of an element vector to a local vector.
346c8e769f6Sjeremylt
347c8e769f6Sjeremylt           Args:
348c8e769f6Sjeremylt             block: block number to restrict to/from, i.e. block=0 will handle
349c8e769f6Sjeremylt                      elements [0 : blksize] and block=3 will handle elements
350c8e769f6Sjeremylt                      [3*blksize : 4*blksize]
351c8e769f6Sjeremylt             u: input vector
352c8e769f6Sjeremylt             v: output vector
353c8e769f6Sjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
354c8e769f6Sjeremylt
355c8e769f6Sjeremylt        # libCEED call
356a8d32208Sjeremylt        self._elemrestriction.apply_block(block, u, v, request=request,
357c8e769f6Sjeremylt                                          tmode=TRANSPOSE)
358c8e769f6Sjeremylt
359c8e769f6Sjeremylt# ------------------------------------------------------------------------------
360