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