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