1*c8e769f6Sjeremylt# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2*c8e769f6Sjeremylt# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3*c8e769f6Sjeremylt# reserved. See files LICENSE and NOTICE for details. 4*c8e769f6Sjeremylt# 5*c8e769f6Sjeremylt# This file is part of CEED, a collection of benchmarks, miniapps, software 6*c8e769f6Sjeremylt# libraries and APIs for efficient high-order finite element and spectral 7*c8e769f6Sjeremylt# element discretizations for exascale applications. For more information and 8*c8e769f6Sjeremylt# source code availability see http://github.com/ceed. 9*c8e769f6Sjeremylt# 10*c8e769f6Sjeremylt# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11*c8e769f6Sjeremylt# a collaborative effort of two U.S. Department of Energy organizations (Office 12*c8e769f6Sjeremylt# of Science and the National Nuclear Security Administration) responsible for 13*c8e769f6Sjeremylt# the planning and preparation of a capable exascale ecosystem, including 14*c8e769f6Sjeremylt# software, applications, hardware, advanced system engineering and early 15*c8e769f6Sjeremylt# testbed platforms, in support of the nation's exascale computing imperative. 16*c8e769f6Sjeremylt 17*c8e769f6Sjeremyltfrom _ceed_cffi import ffi, lib 18*c8e769f6Sjeremyltimport tempfile 19*c8e769f6Sjeremyltimport numpy as np 20*c8e769f6Sjeremyltfrom abc import ABC 21*c8e769f6Sjeremyltfrom .ceed_constants import REQUEST_IMMEDIATE, REQUEST_ORDERED, MEM_HOST, COPY_VALUES, TRANSPOSE, NOTRANSPOSE 22*c8e769f6Sjeremyltfrom .ceed_vector import _VectorWrap 23*c8e769f6Sjeremylt 24*c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 25*c8e769f6Sjeremyltclass _ElemRestrictionBase(ABC): 26*c8e769f6Sjeremylt """Ceed ElemRestriction: restriction from local vectors to elements.""" 27*c8e769f6Sjeremylt 28*c8e769f6Sjeremylt # Attributes 29*c8e769f6Sjeremylt _ceed = ffi.NULL 30*c8e769f6Sjeremylt _pointer = ffi.NULL 31*c8e769f6Sjeremylt 32*c8e769f6Sjeremylt # Destructor 33*c8e769f6Sjeremylt def __del__(self): 34*c8e769f6Sjeremylt # libCEED call 35*c8e769f6Sjeremylt lib.CeedElemRestrictionDestroy(self._pointer) 36*c8e769f6Sjeremylt 37*c8e769f6Sjeremylt # Representation 38*c8e769f6Sjeremylt def __repr__(self): 39*c8e769f6Sjeremylt return "<CeedElemRestriction instance at " + hex(id(self)) + ">" 40*c8e769f6Sjeremylt 41*c8e769f6Sjeremylt # String conversion for print() to stdout 42*c8e769f6Sjeremylt def __str__(self): 43*c8e769f6Sjeremylt """View an ElemRestriction via print().""" 44*c8e769f6Sjeremylt 45*c8e769f6Sjeremylt # libCEED call 46*c8e769f6Sjeremylt with tempfile.NamedTemporaryFile() as key_file: 47*c8e769f6Sjeremylt with open(key_file.name, 'r+') as stream_file: 48*c8e769f6Sjeremylt stream = ffi.cast("FILE *", stream_file) 49*c8e769f6Sjeremylt 50*c8e769f6Sjeremylt lib.CeedElemRestrictionView(self._pointer[0], stream) 51*c8e769f6Sjeremylt 52*c8e769f6Sjeremylt stream_file.seek(0) 53*c8e769f6Sjeremylt out_string = stream_file.read() 54*c8e769f6Sjeremylt 55*c8e769f6Sjeremylt return out_string 56*c8e769f6Sjeremylt 57*c8e769f6Sjeremylt # Apply CeedElemRestriction 58*c8e769f6Sjeremylt def apply(self, u, v, tmode=NOTRANSPOSE, lmode=NOTRANSPOSE, 59*c8e769f6Sjeremylt request=REQUEST_IMMEDIATE): 60*c8e769f6Sjeremylt """Restrict a local vector to an element vector or apply its transpose. 61*c8e769f6Sjeremylt 62*c8e769f6Sjeremylt Args: 63*c8e769f6Sjeremylt u: input vector 64*c8e769f6Sjeremylt v: output vector 65*c8e769f6Sjeremylt **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE 66*c8e769f6Sjeremylt **lmode: ordering of the ncomp components, i.e. it specifies 67*c8e769f6Sjeremylt the ordering of the components of the local vector used 68*c8e769f6Sjeremylt by this CeedElemRestriction. CEED_NOTRANSPOSE indicates 69*c8e769f6Sjeremylt the component is the outermost index and CEED_TRANSPOSE 70*c8e769f6Sjeremylt indicates the component is the innermost index in 71*c8e769f6Sjeremylt ordering of the local vector, default CEED_NOTRANSPOSE 72*c8e769f6Sjeremylt **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 73*c8e769f6Sjeremylt 74*c8e769f6Sjeremylt # libCEED call 75*c8e769f6Sjeremylt lib.CeedElemRestrictionApply(self._pointer[0], tmode, lmode, 76*c8e769f6Sjeremylt u._pointer[0], v._pointer[0], request) 77*c8e769f6Sjeremylt 78*c8e769f6Sjeremylt # Transpose an ElemRestriction 79*c8e769f6Sjeremylt @property 80*c8e769f6Sjeremylt def T(self): 81*c8e769f6Sjeremylt """Transpose an ElemRestriction.""" 82*c8e769f6Sjeremylt 83*c8e769f6Sjeremylt return TransposeElemRestriction(self) 84*c8e769f6Sjeremylt 85*c8e769f6Sjeremylt # Transpose an ElemRestriction 86*c8e769f6Sjeremylt @property 87*c8e769f6Sjeremylt def transpose(self): 88*c8e769f6Sjeremylt """Transpose an ElemRestriction.""" 89*c8e769f6Sjeremylt 90*c8e769f6Sjeremylt return TransposeElemRestriction(self) 91*c8e769f6Sjeremylt 92*c8e769f6Sjeremylt # Create restriction vectors 93*c8e769f6Sjeremylt def create_vector(self, createLvec = True, createEvec = True): 94*c8e769f6Sjeremylt """Create Vectors associated with an ElemRestriction. 95*c8e769f6Sjeremylt 96*c8e769f6Sjeremylt Args: 97*c8e769f6Sjeremylt **createLvec: flag to create local vector, default True 98*c8e769f6Sjeremylt **createEvec: flag to create element vector, default True 99*c8e769f6Sjeremylt 100*c8e769f6Sjeremylt Returns: 101*c8e769f6Sjeremylt [lvec, evec]: local vector and element vector, or None if flag set to false""" 102*c8e769f6Sjeremylt 103*c8e769f6Sjeremylt # Vector pointers 104*c8e769f6Sjeremylt lvecPointer = ffi.new("CeedVector *") if createLvec else ffi.NULL 105*c8e769f6Sjeremylt evecPointer = ffi.new("CeedVector *") if createEvec else ffi.NULL 106*c8e769f6Sjeremylt 107*c8e769f6Sjeremylt # libCEED call 108*c8e769f6Sjeremylt lib.CeedElemRestrictionCreateVector(self._pointer[0], lvecPointer, 109*c8e769f6Sjeremylt evecPointer) 110*c8e769f6Sjeremylt 111*c8e769f6Sjeremylt # Return vectors 112*c8e769f6Sjeremylt lvec = _VectorWrap(self._ceed._pointer, lvecPointer) if createLvec else None 113*c8e769f6Sjeremylt evec = _VectorWrap(self._ceed._pointer, evecPointer) if createEvec else None 114*c8e769f6Sjeremylt 115*c8e769f6Sjeremylt # Return 116*c8e769f6Sjeremylt return [lvec, evec] 117*c8e769f6Sjeremylt 118*c8e769f6Sjeremylt # Get ElemRestriction multiplicity 119*c8e769f6Sjeremylt def get_multiplicity(self): 120*c8e769f6Sjeremylt """Get the multiplicity of nodes in an ElemRestriction. 121*c8e769f6Sjeremylt 122*c8e769f6Sjeremylt Returns: 123*c8e769f6Sjeremylt mult: local vector containing multiplicity of nodes in ElemRestriction""" 124*c8e769f6Sjeremylt 125*c8e769f6Sjeremylt # Create mult vector 126*c8e769f6Sjeremylt [mult, evec] = self.create_vector(createEvec = False) 127*c8e769f6Sjeremylt mult.set_value(0) 128*c8e769f6Sjeremylt 129*c8e769f6Sjeremylt # libCEED call 130*c8e769f6Sjeremylt lib.CeedElemRestrictionGetMultiplicity(self._pointer[0], mult._pointer[0]) 131*c8e769f6Sjeremylt 132*c8e769f6Sjeremylt # Return 133*c8e769f6Sjeremylt return mult 134*c8e769f6Sjeremylt 135*c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 136*c8e769f6Sjeremyltclass ElemRestriction(_ElemRestrictionBase): 137*c8e769f6Sjeremylt """Ceed ElemRestriction: restriction from local vectors to elements.""" 138*c8e769f6Sjeremylt 139*c8e769f6Sjeremylt # Constructor 140*c8e769f6Sjeremylt def __init__(self, ceed, nelem, elemsize, nnodes, ncomp, indices, 141*c8e769f6Sjeremylt memtype=MEM_HOST, cmode=COPY_VALUES): 142*c8e769f6Sjeremylt # CeedVector object 143*c8e769f6Sjeremylt self._pointer = ffi.new("CeedElemRestriction *") 144*c8e769f6Sjeremylt 145*c8e769f6Sjeremylt # Reference to Ceed 146*c8e769f6Sjeremylt self._ceed = ceed 147*c8e769f6Sjeremylt 148*c8e769f6Sjeremylt # Setup the numpy array for the libCEED call 149*c8e769f6Sjeremylt indices_pointer = ffi.new("const CeedInt *") 150*c8e769f6Sjeremylt indices_pointer = ffi.cast("const CeedInt *", 151*c8e769f6Sjeremylt indices.__array_interface__['data'][0]) 152*c8e769f6Sjeremylt 153*c8e769f6Sjeremylt # libCEED call 154*c8e769f6Sjeremylt lib.CeedElemRestrictionCreate(self._ceed._pointer[0], nelem, elemsize, 155*c8e769f6Sjeremylt nnodes, ncomp, memtype, cmode, 156*c8e769f6Sjeremylt indices_pointer, self._pointer) 157*c8e769f6Sjeremylt 158*c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 159*c8e769f6Sjeremyltclass IdentityElemRestriction(_ElemRestrictionBase): 160*c8e769f6Sjeremylt """Ceed Identity ElemRestriction: identity restriction from local vectors to elements.""" 161*c8e769f6Sjeremylt 162*c8e769f6Sjeremylt # Constructor 163*c8e769f6Sjeremylt def __init__(self, ceed, nelem, elemsize, nnodes, ncomp): 164*c8e769f6Sjeremylt # CeedVector object 165*c8e769f6Sjeremylt self._pointer = ffi.new("CeedElemRestriction *") 166*c8e769f6Sjeremylt 167*c8e769f6Sjeremylt # Reference to Ceed 168*c8e769f6Sjeremylt self._ceed = ceed 169*c8e769f6Sjeremylt 170*c8e769f6Sjeremylt # libCEED call 171*c8e769f6Sjeremylt lib.CeedElemRestrictionCreateIdentity(self._ceed._pointer[0], nelem, 172*c8e769f6Sjeremylt elemsize, nnodes, ncomp, 173*c8e769f6Sjeremylt self._pointer) 174*c8e769f6Sjeremylt 175*c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 176*c8e769f6Sjeremyltclass BlockedElemRestriction(_ElemRestrictionBase): 177*c8e769f6Sjeremylt """Ceed Blocked ElemRestriction: blocked restriction from local vectors to elements.""" 178*c8e769f6Sjeremylt 179*c8e769f6Sjeremylt # Constructor 180*c8e769f6Sjeremylt def __init__(self, ceed, nelem, elemsize, blksize, nnodes, ncomp, indices, 181*c8e769f6Sjeremylt memtype=MEM_HOST, cmode=COPY_VALUES): 182*c8e769f6Sjeremylt # CeedVector object 183*c8e769f6Sjeremylt self._pointer = ffi.new("CeedElemRestriction *") 184*c8e769f6Sjeremylt 185*c8e769f6Sjeremylt # Reference to Ceed 186*c8e769f6Sjeremylt self._ceed = ceed 187*c8e769f6Sjeremylt 188*c8e769f6Sjeremylt # Setup the numpy array for the libCEED call 189*c8e769f6Sjeremylt indices_pointer = ffi.new("const CeedInt *") 190*c8e769f6Sjeremylt indices_pointer = ffi.cast("const CeedInt *", 191*c8e769f6Sjeremylt indices.__array_interface__['data'][0]) 192*c8e769f6Sjeremylt 193*c8e769f6Sjeremylt # libCEED call 194*c8e769f6Sjeremylt lib.CeedElemRestrictionCreateBlocked(self._ceed._pointer[0], nelem, 195*c8e769f6Sjeremylt elemsize, blksize, nnodes, ncomp, 196*c8e769f6Sjeremylt memtype, cmode, indices_pointer, 197*c8e769f6Sjeremylt self._pointer) 198*c8e769f6Sjeremylt 199*c8e769f6Sjeremylt # Transpose a Blocked ElemRestriction 200*c8e769f6Sjeremylt @property 201*c8e769f6Sjeremylt def T(self): 202*c8e769f6Sjeremylt """Transpose a BlockedElemRestriction.""" 203*c8e769f6Sjeremylt 204*c8e769f6Sjeremylt return TransposeBlockedElemRestriction(self) 205*c8e769f6Sjeremylt 206*c8e769f6Sjeremylt # Transpose a Blocked ElemRestriction 207*c8e769f6Sjeremylt @property 208*c8e769f6Sjeremylt def transpose(self): 209*c8e769f6Sjeremylt """Transpose a BlockedElemRestriction.""" 210*c8e769f6Sjeremylt 211*c8e769f6Sjeremylt return TransposeBlockedElemRestriction(self) 212*c8e769f6Sjeremylt 213*c8e769f6Sjeremylt # Apply CeedElemRestriction to single block 214*c8e769f6Sjeremylt def apply_block(self, block, u, v, tmode=NOTRANSPOSE, lmode=NOTRANSPOSE, 215*c8e769f6Sjeremylt request=REQUEST_IMMEDIATE): 216*c8e769f6Sjeremylt """Restrict a local vector to a block of an element vector or apply its transpose. 217*c8e769f6Sjeremylt 218*c8e769f6Sjeremylt Args: 219*c8e769f6Sjeremylt block: block number to restrict to/from, i.e. block=0 will handle 220*c8e769f6Sjeremylt elements [0 : blksize] and block=3 will handle elements 221*c8e769f6Sjeremylt [3*blksize : 4*blksize] 222*c8e769f6Sjeremylt u: input vector 223*c8e769f6Sjeremylt v: output vector 224*c8e769f6Sjeremylt **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE 225*c8e769f6Sjeremylt **lmode: ordering of the ncomp components, i.e. it specifies 226*c8e769f6Sjeremylt the ordering of the components of the l-vector used 227*c8e769f6Sjeremylt by this CeedElemRestriction. CEED_NOTRANSPOSE indicates 228*c8e769f6Sjeremylt the component is the outermost index and CEED_TRANSPOSE 229*c8e769f6Sjeremylt indicates the component is the innermost index in 230*c8e769f6Sjeremylt ordering of the local vector tmode=CEED_NOTRANSPOSE; 231*c8e769f6Sjeremylt default CEED_NOTRANSPOSE 232*c8e769f6Sjeremylt **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 233*c8e769f6Sjeremylt 234*c8e769f6Sjeremylt # libCEED call 235*c8e769f6Sjeremylt lib.CeedElemRestrictionApplyBlock(self._pointer[0], block, tmode, 236*c8e769f6Sjeremylt lmode, u._pointer[0], v._pointer[0], 237*c8e769f6Sjeremylt request) 238*c8e769f6Sjeremylt 239*c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 240*c8e769f6Sjeremyltclass TransposeElemRestriction(): 241*c8e769f6Sjeremylt """Ceed ElemRestriction: transpose restriction from elements to local vectors.""" 242*c8e769f6Sjeremylt 243*c8e769f6Sjeremylt # Attributes 244*c8e769f6Sjeremylt _elemrestriction = None 245*c8e769f6Sjeremylt 246*c8e769f6Sjeremylt # Constructor 247*c8e769f6Sjeremylt def __init__(self, elemrestriction): 248*c8e769f6Sjeremylt 249*c8e769f6Sjeremylt # Reference elemrestriction 250*c8e769f6Sjeremylt self._elemrestriction = elemrestriction 251*c8e769f6Sjeremylt 252*c8e769f6Sjeremylt # Representation 253*c8e769f6Sjeremylt def __repr__(self): 254*c8e769f6Sjeremylt return "<Transpose CeedElemRestriction instance at " + hex(id(self)) + ">" 255*c8e769f6Sjeremylt 256*c8e769f6Sjeremylt 257*c8e769f6Sjeremylt # Apply Transpose CeedElemRestriction 258*c8e769f6Sjeremylt def apply(self, u, v, request=REQUEST_IMMEDIATE, lmode=NOTRANSPOSE): 259*c8e769f6Sjeremylt """Restrict an element vector to a local vector. 260*c8e769f6Sjeremylt 261*c8e769f6Sjeremylt Args: 262*c8e769f6Sjeremylt u: input vector 263*c8e769f6Sjeremylt v: output vector 264*c8e769f6Sjeremylt **lmode: ordering of the ncomp components, i.e. it specifies 265*c8e769f6Sjeremylt the ordering of the components of the local vector used 266*c8e769f6Sjeremylt by this CeedElemRestriction. CEED_NOTRANSPOSE indicates 267*c8e769f6Sjeremylt the component is the outermost index and CEED_TRANSPOSE 268*c8e769f6Sjeremylt indicates the component is the innermost index in 269*c8e769f6Sjeremylt ordering of the local vector, default CEED_NOTRANSPOSE 270*c8e769f6Sjeremylt **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 271*c8e769f6Sjeremylt 272*c8e769f6Sjeremylt # libCEED call 273*c8e769f6Sjeremylt self._elemrestriction.apply(u, v, request=request, lmode=lmode, 274*c8e769f6Sjeremylt tmode=TRANSPOSE) 275*c8e769f6Sjeremylt 276*c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 277*c8e769f6Sjeremyltclass TransposeBlockedElemRestriction(TransposeElemRestriction): 278*c8e769f6Sjeremylt """Transpose Ceed Blocked ElemRestriction: blocked transpose restriction from elements 279*c8e769f6Sjeremylt to local vectors.""" 280*c8e769f6Sjeremylt 281*c8e769f6Sjeremylt # Apply Transpose CeedElemRestriction 282*c8e769f6Sjeremylt def apply_block(self, block, u, v, request=REQUEST_IMMEDIATE, 283*c8e769f6Sjeremylt lmode=NOTRANSPOSE): 284*c8e769f6Sjeremylt """Restrict a block of an element vector to a local vector. 285*c8e769f6Sjeremylt 286*c8e769f6Sjeremylt Args: 287*c8e769f6Sjeremylt block: block number to restrict to/from, i.e. block=0 will handle 288*c8e769f6Sjeremylt elements [0 : blksize] and block=3 will handle elements 289*c8e769f6Sjeremylt [3*blksize : 4*blksize] 290*c8e769f6Sjeremylt u: input vector 291*c8e769f6Sjeremylt v: output vector 292*c8e769f6Sjeremylt **lmode: ordering of the ncomp components, i.e. it specifies 293*c8e769f6Sjeremylt the ordering of the components of the l-vector used 294*c8e769f6Sjeremylt by this CeedElemRestriction. CEED_NOTRANSPOSE indicates 295*c8e769f6Sjeremylt the component is the outermost index and CEED_TRANSPOSE 296*c8e769f6Sjeremylt indicates the component is the innermost index in 297*c8e769f6Sjeremylt ordering of the local vector tmode=CEED_NOTRANSPOSE), 298*c8e769f6Sjeremylt default CEED_NOTRANSPOSE 299*c8e769f6Sjeremylt **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 300*c8e769f6Sjeremylt 301*c8e769f6Sjeremylt # libCEED call 302*c8e769f6Sjeremylt self._elemrestriction.apply_block(block, u, v, request=request, lmode=lmode, 303*c8e769f6Sjeremylt tmode=TRANSPOSE) 304*c8e769f6Sjeremylt 305*c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 306