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