xref: /libCEED/python/ceed_elemrestriction.py (revision efc78312550893c11c7921bf7c4699a3e027cc68)
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):
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], mult._pointer[0])
131
132    # Return
133    return mult
134
135# ------------------------------------------------------------------------------
136class ElemRestriction(_ElemRestrictionBase):
137  """Ceed ElemRestriction: restriction from local vectors to elements."""
138
139  # Constructor
140  def __init__(self, ceed, nelem, elemsize, nnodes, ncomp, indices,
141               memtype=MEM_HOST, cmode=COPY_VALUES):
142    # CeedVector object
143    self._pointer = ffi.new("CeedElemRestriction *")
144
145    # Reference to Ceed
146    self._ceed = ceed
147
148    # Setup the numpy array for the libCEED call
149    indices_pointer = ffi.new("const CeedInt *")
150    indices_pointer = ffi.cast("const CeedInt *",
151                               indices.__array_interface__['data'][0])
152
153    # libCEED call
154    lib.CeedElemRestrictionCreate(self._ceed._pointer[0], nelem, elemsize,
155                                  nnodes, ncomp, memtype, cmode,
156                                  indices_pointer, self._pointer)
157
158# ------------------------------------------------------------------------------
159class IdentityElemRestriction(_ElemRestrictionBase):
160  """Ceed Identity ElemRestriction: identity restriction from local vectors to elements."""
161
162  # Constructor
163  def __init__(self, ceed, nelem, elemsize, nnodes, ncomp):
164    # CeedVector object
165    self._pointer = ffi.new("CeedElemRestriction *")
166
167    # Reference to Ceed
168    self._ceed = ceed
169
170    # libCEED call
171    lib.CeedElemRestrictionCreateIdentity(self._ceed._pointer[0], nelem,
172                                          elemsize, nnodes, ncomp,
173                                          self._pointer)
174
175# ------------------------------------------------------------------------------
176class BlockedElemRestriction(_ElemRestrictionBase):
177  """Ceed Blocked ElemRestriction: blocked restriction from local vectors to elements."""
178
179  # Constructor
180  def __init__(self, ceed, nelem, elemsize, blksize, nnodes, ncomp, indices,
181               memtype=MEM_HOST, cmode=COPY_VALUES):
182    # CeedVector object
183    self._pointer = ffi.new("CeedElemRestriction *")
184
185    # Reference to Ceed
186    self._ceed = ceed
187
188    # Setup the numpy array for the libCEED call
189    indices_pointer = ffi.new("const CeedInt *")
190    indices_pointer = ffi.cast("const CeedInt *",
191                               indices.__array_interface__['data'][0])
192
193    # libCEED call
194    lib.CeedElemRestrictionCreateBlocked(self._ceed._pointer[0], nelem,
195                                         elemsize, blksize, nnodes, ncomp,
196                                         memtype, cmode, indices_pointer,
197                                         self._pointer)
198
199  # Transpose a Blocked ElemRestriction
200  @property
201  def T(self):
202    """Transpose a BlockedElemRestriction."""
203
204    return TransposeBlockedElemRestriction(self)
205
206  # Transpose a Blocked ElemRestriction
207  @property
208  def transpose(self):
209    """Transpose a BlockedElemRestriction."""
210
211    return TransposeBlockedElemRestriction(self)
212
213  # Apply CeedElemRestriction to single block
214  def apply_block(self, block, u, v, tmode=NOTRANSPOSE, lmode=NOTRANSPOSE,
215                  request=REQUEST_IMMEDIATE):
216    """Restrict a local vector to a block of an element vector or apply its transpose.
217
218       Args:
219         block: block number to restrict to/from, i.e. block=0 will handle
220                  elements [0 : blksize] and block=3 will handle elements
221                  [3*blksize : 4*blksize]
222         u: input vector
223         v: output vector
224         **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE
225         **lmode: ordering of the ncomp components, i.e. it specifies
226                    the ordering of the components of the l-vector used
227                    by this CeedElemRestriction. CEED_NOTRANSPOSE indicates
228                    the component is the outermost index and CEED_TRANSPOSE
229                    indicates the component is the innermost index in
230                    ordering of the local vector tmode=CEED_NOTRANSPOSE;
231                    default CEED_NOTRANSPOSE
232         **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
233
234    # libCEED call
235    lib.CeedElemRestrictionApplyBlock(self._pointer[0], block, tmode,
236                                      lmode, u._pointer[0], v._pointer[0],
237                                      request)
238
239# ------------------------------------------------------------------------------
240class TransposeElemRestriction():
241  """Ceed ElemRestriction: transpose restriction from elements to local vectors."""
242
243  # Attributes
244  _elemrestriction = None
245
246  # Constructor
247  def __init__(self, elemrestriction):
248
249    # Reference elemrestriction
250    self._elemrestriction = elemrestriction
251
252  # Representation
253  def __repr__(self):
254    return "<Transpose CeedElemRestriction instance at " + hex(id(self)) + ">"
255
256
257  # Apply Transpose CeedElemRestriction
258  def apply(self, u, v, request=REQUEST_IMMEDIATE, lmode=NOTRANSPOSE):
259    """Restrict an element vector to a local vector.
260
261       Args:
262         u: input vector
263         v: output vector
264         **lmode: ordering of the ncomp components, i.e. it specifies
265                   the ordering of the components of the local vector used
266                   by this CeedElemRestriction. CEED_NOTRANSPOSE indicates
267                   the component is the outermost index and CEED_TRANSPOSE
268                   indicates the component is the innermost index in
269                   ordering of the local vector, default CEED_NOTRANSPOSE
270         **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
271
272    # libCEED call
273    self._elemrestriction.apply(u, v, request=request, lmode=lmode,
274                                tmode=TRANSPOSE)
275
276# ------------------------------------------------------------------------------
277class TransposeBlockedElemRestriction(TransposeElemRestriction):
278  """Transpose Ceed Blocked ElemRestriction: blocked transpose restriction from elements
279       to local vectors."""
280
281  # Apply Transpose CeedElemRestriction
282  def apply_block(self, block, u, v, request=REQUEST_IMMEDIATE,
283                  lmode=NOTRANSPOSE):
284    """Restrict a block of an element vector to a local vector.
285
286       Args:
287         block: block number to restrict to/from, i.e. block=0 will handle
288                  elements [0 : blksize] and block=3 will handle elements
289                  [3*blksize : 4*blksize]
290         u: input vector
291         v: output vector
292         **lmode: ordering of the ncomp components, i.e. it specifies
293                    the ordering of the components of the l-vector used
294                    by this CeedElemRestriction. CEED_NOTRANSPOSE indicates
295                    the component is the outermost index and CEED_TRANSPOSE
296                    indicates the component is the innermost index in
297                    ordering of the local vector tmode=CEED_NOTRANSPOSE),
298                    default CEED_NOTRANSPOSE
299         **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
300
301    # libCEED call
302    self._elemrestriction.apply_block(block, u, v, request=request, lmode=lmode,
303                                tmode=TRANSPOSE)
304
305# ------------------------------------------------------------------------------
306