xref: /libCEED/python/ceed_elemrestriction.py (revision c8e769f67f4493280f2a48c57050cdc5cf0cf15e)
1*c8e769f6Sjeremylt# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2*c8e769f6Sjeremylt# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3*c8e769f6Sjeremylt# reserved. See files LICENSE and NOTICE for details.
4*c8e769f6Sjeremylt#
5*c8e769f6Sjeremylt# This file is part of CEED, a collection of benchmarks, miniapps, software
6*c8e769f6Sjeremylt# libraries and APIs for efficient high-order finite element and spectral
7*c8e769f6Sjeremylt# element discretizations for exascale applications. For more information and
8*c8e769f6Sjeremylt# source code availability see http://github.com/ceed.
9*c8e769f6Sjeremylt#
10*c8e769f6Sjeremylt# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11*c8e769f6Sjeremylt# a collaborative effort of two U.S. Department of Energy organizations (Office
12*c8e769f6Sjeremylt# of Science and the National Nuclear Security Administration) responsible for
13*c8e769f6Sjeremylt# the planning and preparation of a capable exascale ecosystem, including
14*c8e769f6Sjeremylt# software, applications, hardware, advanced system engineering and early
15*c8e769f6Sjeremylt# testbed platforms, in support of the nation's exascale computing imperative.
16*c8e769f6Sjeremylt
17*c8e769f6Sjeremyltfrom _ceed_cffi import ffi, lib
18*c8e769f6Sjeremyltimport tempfile
19*c8e769f6Sjeremyltimport numpy as np
20*c8e769f6Sjeremyltfrom abc import ABC
21*c8e769f6Sjeremyltfrom .ceed_constants import REQUEST_IMMEDIATE, REQUEST_ORDERED, MEM_HOST, COPY_VALUES, TRANSPOSE, NOTRANSPOSE
22*c8e769f6Sjeremyltfrom .ceed_vector import _VectorWrap
23*c8e769f6Sjeremylt
24*c8e769f6Sjeremylt# ------------------------------------------------------------------------------
25*c8e769f6Sjeremyltclass _ElemRestrictionBase(ABC):
26*c8e769f6Sjeremylt  """Ceed ElemRestriction: restriction from local vectors to elements."""
27*c8e769f6Sjeremylt
28*c8e769f6Sjeremylt  # Attributes
29*c8e769f6Sjeremylt  _ceed = ffi.NULL
30*c8e769f6Sjeremylt  _pointer = ffi.NULL
31*c8e769f6Sjeremylt
32*c8e769f6Sjeremylt  # Destructor
33*c8e769f6Sjeremylt  def __del__(self):
34*c8e769f6Sjeremylt    # libCEED call
35*c8e769f6Sjeremylt    lib.CeedElemRestrictionDestroy(self._pointer)
36*c8e769f6Sjeremylt
37*c8e769f6Sjeremylt  # Representation
38*c8e769f6Sjeremylt  def __repr__(self):
39*c8e769f6Sjeremylt    return "<CeedElemRestriction instance at " + hex(id(self)) + ">"
40*c8e769f6Sjeremylt
41*c8e769f6Sjeremylt  # String conversion for print() to stdout
42*c8e769f6Sjeremylt  def __str__(self):
43*c8e769f6Sjeremylt    """View an ElemRestriction via print()."""
44*c8e769f6Sjeremylt
45*c8e769f6Sjeremylt    # libCEED call
46*c8e769f6Sjeremylt    with tempfile.NamedTemporaryFile() as key_file:
47*c8e769f6Sjeremylt      with open(key_file.name, 'r+') as stream_file:
48*c8e769f6Sjeremylt        stream = ffi.cast("FILE *", stream_file)
49*c8e769f6Sjeremylt
50*c8e769f6Sjeremylt        lib.CeedElemRestrictionView(self._pointer[0], stream)
51*c8e769f6Sjeremylt
52*c8e769f6Sjeremylt        stream_file.seek(0)
53*c8e769f6Sjeremylt        out_string = stream_file.read()
54*c8e769f6Sjeremylt
55*c8e769f6Sjeremylt    return out_string
56*c8e769f6Sjeremylt
57*c8e769f6Sjeremylt  # Apply CeedElemRestriction
58*c8e769f6Sjeremylt  def apply(self, u, v, tmode=NOTRANSPOSE, lmode=NOTRANSPOSE,
59*c8e769f6Sjeremylt            request=REQUEST_IMMEDIATE):
60*c8e769f6Sjeremylt    """Restrict a local vector to an element vector or apply its transpose.
61*c8e769f6Sjeremylt
62*c8e769f6Sjeremylt       Args:
63*c8e769f6Sjeremylt         u: input vector
64*c8e769f6Sjeremylt         v: output vector
65*c8e769f6Sjeremylt         **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE
66*c8e769f6Sjeremylt         **lmode: ordering of the ncomp components, i.e. it specifies
67*c8e769f6Sjeremylt                    the ordering of the components of the local vector used
68*c8e769f6Sjeremylt                    by this CeedElemRestriction. CEED_NOTRANSPOSE indicates
69*c8e769f6Sjeremylt                    the component is the outermost index and CEED_TRANSPOSE
70*c8e769f6Sjeremylt                    indicates the component is the innermost index in
71*c8e769f6Sjeremylt                    ordering of the local vector, default CEED_NOTRANSPOSE
72*c8e769f6Sjeremylt         **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
73*c8e769f6Sjeremylt
74*c8e769f6Sjeremylt    # libCEED call
75*c8e769f6Sjeremylt    lib.CeedElemRestrictionApply(self._pointer[0], tmode, lmode,
76*c8e769f6Sjeremylt                                 u._pointer[0], v._pointer[0], request)
77*c8e769f6Sjeremylt
78*c8e769f6Sjeremylt  # Transpose an ElemRestriction
79*c8e769f6Sjeremylt  @property
80*c8e769f6Sjeremylt  def T(self):
81*c8e769f6Sjeremylt    """Transpose an ElemRestriction."""
82*c8e769f6Sjeremylt
83*c8e769f6Sjeremylt    return TransposeElemRestriction(self)
84*c8e769f6Sjeremylt
85*c8e769f6Sjeremylt  # Transpose an ElemRestriction
86*c8e769f6Sjeremylt  @property
87*c8e769f6Sjeremylt  def transpose(self):
88*c8e769f6Sjeremylt    """Transpose an ElemRestriction."""
89*c8e769f6Sjeremylt
90*c8e769f6Sjeremylt    return TransposeElemRestriction(self)
91*c8e769f6Sjeremylt
92*c8e769f6Sjeremylt  # Create restriction vectors
93*c8e769f6Sjeremylt  def create_vector(self, createLvec = True, createEvec = True):
94*c8e769f6Sjeremylt    """Create Vectors associated with an ElemRestriction.
95*c8e769f6Sjeremylt
96*c8e769f6Sjeremylt       Args:
97*c8e769f6Sjeremylt         **createLvec: flag to create local vector, default True
98*c8e769f6Sjeremylt         **createEvec: flag to create element vector, default True
99*c8e769f6Sjeremylt
100*c8e769f6Sjeremylt       Returns:
101*c8e769f6Sjeremylt         [lvec, evec]: local vector and element vector, or None if flag set to false"""
102*c8e769f6Sjeremylt
103*c8e769f6Sjeremylt    # Vector pointers
104*c8e769f6Sjeremylt    lvecPointer = ffi.new("CeedVector *") if createLvec else ffi.NULL
105*c8e769f6Sjeremylt    evecPointer = ffi.new("CeedVector *") if createEvec else ffi.NULL
106*c8e769f6Sjeremylt
107*c8e769f6Sjeremylt    # libCEED call
108*c8e769f6Sjeremylt    lib.CeedElemRestrictionCreateVector(self._pointer[0], lvecPointer,
109*c8e769f6Sjeremylt                                        evecPointer)
110*c8e769f6Sjeremylt
111*c8e769f6Sjeremylt    # Return vectors
112*c8e769f6Sjeremylt    lvec = _VectorWrap(self._ceed._pointer, lvecPointer) if createLvec else None
113*c8e769f6Sjeremylt    evec = _VectorWrap(self._ceed._pointer, evecPointer) if createEvec else None
114*c8e769f6Sjeremylt
115*c8e769f6Sjeremylt    # Return
116*c8e769f6Sjeremylt    return [lvec, evec]
117*c8e769f6Sjeremylt
118*c8e769f6Sjeremylt  # Get ElemRestriction multiplicity
119*c8e769f6Sjeremylt  def get_multiplicity(self):
120*c8e769f6Sjeremylt    """Get the multiplicity of nodes in an ElemRestriction.
121*c8e769f6Sjeremylt
122*c8e769f6Sjeremylt       Returns:
123*c8e769f6Sjeremylt         mult: local vector containing multiplicity of nodes in ElemRestriction"""
124*c8e769f6Sjeremylt
125*c8e769f6Sjeremylt    # Create mult vector
126*c8e769f6Sjeremylt    [mult, evec] = self.create_vector(createEvec = False)
127*c8e769f6Sjeremylt    mult.set_value(0)
128*c8e769f6Sjeremylt
129*c8e769f6Sjeremylt    # libCEED call
130*c8e769f6Sjeremylt    lib.CeedElemRestrictionGetMultiplicity(self._pointer[0], mult._pointer[0])
131*c8e769f6Sjeremylt
132*c8e769f6Sjeremylt    # Return
133*c8e769f6Sjeremylt    return mult
134*c8e769f6Sjeremylt
135*c8e769f6Sjeremylt# ------------------------------------------------------------------------------
136*c8e769f6Sjeremyltclass ElemRestriction(_ElemRestrictionBase):
137*c8e769f6Sjeremylt  """Ceed ElemRestriction: restriction from local vectors to elements."""
138*c8e769f6Sjeremylt
139*c8e769f6Sjeremylt  # Constructor
140*c8e769f6Sjeremylt  def __init__(self, ceed, nelem, elemsize, nnodes, ncomp, indices,
141*c8e769f6Sjeremylt               memtype=MEM_HOST, cmode=COPY_VALUES):
142*c8e769f6Sjeremylt    # CeedVector object
143*c8e769f6Sjeremylt    self._pointer = ffi.new("CeedElemRestriction *")
144*c8e769f6Sjeremylt
145*c8e769f6Sjeremylt    # Reference to Ceed
146*c8e769f6Sjeremylt    self._ceed = ceed
147*c8e769f6Sjeremylt
148*c8e769f6Sjeremylt    # Setup the numpy array for the libCEED call
149*c8e769f6Sjeremylt    indices_pointer = ffi.new("const CeedInt *")
150*c8e769f6Sjeremylt    indices_pointer = ffi.cast("const CeedInt *",
151*c8e769f6Sjeremylt                               indices.__array_interface__['data'][0])
152*c8e769f6Sjeremylt
153*c8e769f6Sjeremylt    # libCEED call
154*c8e769f6Sjeremylt    lib.CeedElemRestrictionCreate(self._ceed._pointer[0], nelem, elemsize,
155*c8e769f6Sjeremylt                                  nnodes, ncomp, memtype, cmode,
156*c8e769f6Sjeremylt                                  indices_pointer, self._pointer)
157*c8e769f6Sjeremylt
158*c8e769f6Sjeremylt# ------------------------------------------------------------------------------
159*c8e769f6Sjeremyltclass IdentityElemRestriction(_ElemRestrictionBase):
160*c8e769f6Sjeremylt  """Ceed Identity ElemRestriction: identity restriction from local vectors to elements."""
161*c8e769f6Sjeremylt
162*c8e769f6Sjeremylt  # Constructor
163*c8e769f6Sjeremylt  def __init__(self, ceed, nelem, elemsize, nnodes, ncomp):
164*c8e769f6Sjeremylt    # CeedVector object
165*c8e769f6Sjeremylt    self._pointer = ffi.new("CeedElemRestriction *")
166*c8e769f6Sjeremylt
167*c8e769f6Sjeremylt    # Reference to Ceed
168*c8e769f6Sjeremylt    self._ceed = ceed
169*c8e769f6Sjeremylt
170*c8e769f6Sjeremylt    # libCEED call
171*c8e769f6Sjeremylt    lib.CeedElemRestrictionCreateIdentity(self._ceed._pointer[0], nelem,
172*c8e769f6Sjeremylt                                          elemsize, nnodes, ncomp,
173*c8e769f6Sjeremylt                                          self._pointer)
174*c8e769f6Sjeremylt
175*c8e769f6Sjeremylt# ------------------------------------------------------------------------------
176*c8e769f6Sjeremyltclass BlockedElemRestriction(_ElemRestrictionBase):
177*c8e769f6Sjeremylt  """Ceed Blocked ElemRestriction: blocked restriction from local vectors to elements."""
178*c8e769f6Sjeremylt
179*c8e769f6Sjeremylt  # Constructor
180*c8e769f6Sjeremylt  def __init__(self, ceed, nelem, elemsize, blksize, nnodes, ncomp, indices,
181*c8e769f6Sjeremylt               memtype=MEM_HOST, cmode=COPY_VALUES):
182*c8e769f6Sjeremylt    # CeedVector object
183*c8e769f6Sjeremylt    self._pointer = ffi.new("CeedElemRestriction *")
184*c8e769f6Sjeremylt
185*c8e769f6Sjeremylt    # Reference to Ceed
186*c8e769f6Sjeremylt    self._ceed = ceed
187*c8e769f6Sjeremylt
188*c8e769f6Sjeremylt    # Setup the numpy array for the libCEED call
189*c8e769f6Sjeremylt    indices_pointer = ffi.new("const CeedInt *")
190*c8e769f6Sjeremylt    indices_pointer = ffi.cast("const CeedInt *",
191*c8e769f6Sjeremylt                               indices.__array_interface__['data'][0])
192*c8e769f6Sjeremylt
193*c8e769f6Sjeremylt    # libCEED call
194*c8e769f6Sjeremylt    lib.CeedElemRestrictionCreateBlocked(self._ceed._pointer[0], nelem,
195*c8e769f6Sjeremylt                                         elemsize, blksize, nnodes, ncomp,
196*c8e769f6Sjeremylt                                         memtype, cmode, indices_pointer,
197*c8e769f6Sjeremylt                                         self._pointer)
198*c8e769f6Sjeremylt
199*c8e769f6Sjeremylt  # Transpose a Blocked ElemRestriction
200*c8e769f6Sjeremylt  @property
201*c8e769f6Sjeremylt  def T(self):
202*c8e769f6Sjeremylt    """Transpose a BlockedElemRestriction."""
203*c8e769f6Sjeremylt
204*c8e769f6Sjeremylt    return TransposeBlockedElemRestriction(self)
205*c8e769f6Sjeremylt
206*c8e769f6Sjeremylt  # Transpose a Blocked ElemRestriction
207*c8e769f6Sjeremylt  @property
208*c8e769f6Sjeremylt  def transpose(self):
209*c8e769f6Sjeremylt    """Transpose a BlockedElemRestriction."""
210*c8e769f6Sjeremylt
211*c8e769f6Sjeremylt    return TransposeBlockedElemRestriction(self)
212*c8e769f6Sjeremylt
213*c8e769f6Sjeremylt  # Apply CeedElemRestriction to single block
214*c8e769f6Sjeremylt  def apply_block(self, block, u, v, tmode=NOTRANSPOSE, lmode=NOTRANSPOSE,
215*c8e769f6Sjeremylt                  request=REQUEST_IMMEDIATE):
216*c8e769f6Sjeremylt    """Restrict a local vector to a block of an element vector or apply its transpose.
217*c8e769f6Sjeremylt
218*c8e769f6Sjeremylt       Args:
219*c8e769f6Sjeremylt         block: block number to restrict to/from, i.e. block=0 will handle
220*c8e769f6Sjeremylt                  elements [0 : blksize] and block=3 will handle elements
221*c8e769f6Sjeremylt                  [3*blksize : 4*blksize]
222*c8e769f6Sjeremylt         u: input vector
223*c8e769f6Sjeremylt         v: output vector
224*c8e769f6Sjeremylt         **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE
225*c8e769f6Sjeremylt         **lmode: ordering of the ncomp components, i.e. it specifies
226*c8e769f6Sjeremylt                    the ordering of the components of the l-vector used
227*c8e769f6Sjeremylt                    by this CeedElemRestriction. CEED_NOTRANSPOSE indicates
228*c8e769f6Sjeremylt                    the component is the outermost index and CEED_TRANSPOSE
229*c8e769f6Sjeremylt                    indicates the component is the innermost index in
230*c8e769f6Sjeremylt                    ordering of the local vector tmode=CEED_NOTRANSPOSE;
231*c8e769f6Sjeremylt                    default CEED_NOTRANSPOSE
232*c8e769f6Sjeremylt         **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
233*c8e769f6Sjeremylt
234*c8e769f6Sjeremylt    # libCEED call
235*c8e769f6Sjeremylt    lib.CeedElemRestrictionApplyBlock(self._pointer[0], block, tmode,
236*c8e769f6Sjeremylt                                      lmode, u._pointer[0], v._pointer[0],
237*c8e769f6Sjeremylt                                      request)
238*c8e769f6Sjeremylt
239*c8e769f6Sjeremylt# ------------------------------------------------------------------------------
240*c8e769f6Sjeremyltclass TransposeElemRestriction():
241*c8e769f6Sjeremylt  """Ceed ElemRestriction: transpose restriction from elements to local vectors."""
242*c8e769f6Sjeremylt
243*c8e769f6Sjeremylt  # Attributes
244*c8e769f6Sjeremylt  _elemrestriction = None
245*c8e769f6Sjeremylt
246*c8e769f6Sjeremylt  # Constructor
247*c8e769f6Sjeremylt  def __init__(self, elemrestriction):
248*c8e769f6Sjeremylt
249*c8e769f6Sjeremylt    # Reference elemrestriction
250*c8e769f6Sjeremylt    self._elemrestriction = elemrestriction
251*c8e769f6Sjeremylt
252*c8e769f6Sjeremylt  # Representation
253*c8e769f6Sjeremylt  def __repr__(self):
254*c8e769f6Sjeremylt    return "<Transpose CeedElemRestriction instance at " + hex(id(self)) + ">"
255*c8e769f6Sjeremylt
256*c8e769f6Sjeremylt
257*c8e769f6Sjeremylt  # Apply Transpose CeedElemRestriction
258*c8e769f6Sjeremylt  def apply(self, u, v, request=REQUEST_IMMEDIATE, lmode=NOTRANSPOSE):
259*c8e769f6Sjeremylt    """Restrict an element vector to a local vector.
260*c8e769f6Sjeremylt
261*c8e769f6Sjeremylt       Args:
262*c8e769f6Sjeremylt         u: input vector
263*c8e769f6Sjeremylt         v: output vector
264*c8e769f6Sjeremylt         **lmode: ordering of the ncomp components, i.e. it specifies
265*c8e769f6Sjeremylt                   the ordering of the components of the local vector used
266*c8e769f6Sjeremylt                   by this CeedElemRestriction. CEED_NOTRANSPOSE indicates
267*c8e769f6Sjeremylt                   the component is the outermost index and CEED_TRANSPOSE
268*c8e769f6Sjeremylt                   indicates the component is the innermost index in
269*c8e769f6Sjeremylt                   ordering of the local vector, default CEED_NOTRANSPOSE
270*c8e769f6Sjeremylt         **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
271*c8e769f6Sjeremylt
272*c8e769f6Sjeremylt    # libCEED call
273*c8e769f6Sjeremylt    self._elemrestriction.apply(u, v, request=request, lmode=lmode,
274*c8e769f6Sjeremylt                                tmode=TRANSPOSE)
275*c8e769f6Sjeremylt
276*c8e769f6Sjeremylt# ------------------------------------------------------------------------------
277*c8e769f6Sjeremyltclass TransposeBlockedElemRestriction(TransposeElemRestriction):
278*c8e769f6Sjeremylt  """Transpose Ceed Blocked ElemRestriction: blocked transpose restriction from elements
279*c8e769f6Sjeremylt       to local vectors."""
280*c8e769f6Sjeremylt
281*c8e769f6Sjeremylt  # Apply Transpose CeedElemRestriction
282*c8e769f6Sjeremylt  def apply_block(self, block, u, v, request=REQUEST_IMMEDIATE,
283*c8e769f6Sjeremylt                  lmode=NOTRANSPOSE):
284*c8e769f6Sjeremylt    """Restrict a block of an element vector to a local vector.
285*c8e769f6Sjeremylt
286*c8e769f6Sjeremylt       Args:
287*c8e769f6Sjeremylt         block: block number to restrict to/from, i.e. block=0 will handle
288*c8e769f6Sjeremylt                  elements [0 : blksize] and block=3 will handle elements
289*c8e769f6Sjeremylt                  [3*blksize : 4*blksize]
290*c8e769f6Sjeremylt         u: input vector
291*c8e769f6Sjeremylt         v: output vector
292*c8e769f6Sjeremylt         **lmode: ordering of the ncomp components, i.e. it specifies
293*c8e769f6Sjeremylt                    the ordering of the components of the l-vector used
294*c8e769f6Sjeremylt                    by this CeedElemRestriction. CEED_NOTRANSPOSE indicates
295*c8e769f6Sjeremylt                    the component is the outermost index and CEED_TRANSPOSE
296*c8e769f6Sjeremylt                    indicates the component is the innermost index in
297*c8e769f6Sjeremylt                    ordering of the local vector tmode=CEED_NOTRANSPOSE),
298*c8e769f6Sjeremylt                    default CEED_NOTRANSPOSE
299*c8e769f6Sjeremylt         **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
300*c8e769f6Sjeremylt
301*c8e769f6Sjeremylt    # libCEED call
302*c8e769f6Sjeremylt    self._elemrestriction.apply_block(block, u, v, request=request, lmode=lmode,
303*c8e769f6Sjeremylt                                tmode=TRANSPOSE)
304*c8e769f6Sjeremylt
305*c8e769f6Sjeremylt# ------------------------------------------------------------------------------
306