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