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