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