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