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