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