1c8e769f6Sjeremylt# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2c8e769f6Sjeremylt# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3c8e769f6Sjeremylt# reserved. See files LICENSE and NOTICE for details. 4c8e769f6Sjeremylt# 5c8e769f6Sjeremylt# This file is part of CEED, a collection of benchmarks, miniapps, software 6c8e769f6Sjeremylt# libraries and APIs for efficient high-order finite element and spectral 7c8e769f6Sjeremylt# element discretizations for exascale applications. For more information and 8c8e769f6Sjeremylt# source code availability see http://github.com/ceed. 9c8e769f6Sjeremylt# 10c8e769f6Sjeremylt# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11c8e769f6Sjeremylt# a collaborative effort of two U.S. Department of Energy organizations (Office 12c8e769f6Sjeremylt# of Science and the National Nuclear Security Administration) responsible for 13c8e769f6Sjeremylt# the planning and preparation of a capable exascale ecosystem, including 14c8e769f6Sjeremylt# software, applications, hardware, advanced system engineering and early 15c8e769f6Sjeremylt# testbed platforms, in support of the nation's exascale computing imperative. 16c8e769f6Sjeremylt 17c8e769f6Sjeremyltfrom _ceed_cffi import ffi, lib 18c8e769f6Sjeremyltimport tempfile 19c8e769f6Sjeremyltimport numpy as np 20c8e769f6Sjeremyltfrom abc import ABC 21187168c7SJeremy L Thompsonfrom .ceed_constants import REQUEST_IMMEDIATE, REQUEST_ORDERED, MEM_HOST, USE_POINTER, COPY_VALUES, TRANSPOSE, NOTRANSPOSE 22c8e769f6Sjeremyltfrom .ceed_vector import _VectorWrap 23c8e769f6Sjeremylt 24c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 257a7b0fa3SJed Brown 267a7b0fa3SJed Brown 27c8e769f6Sjeremyltclass _ElemRestrictionBase(ABC): 28c8e769f6Sjeremylt """Ceed ElemRestriction: restriction from local vectors to elements.""" 29c8e769f6Sjeremylt 30c8e769f6Sjeremylt # Destructor 31c8e769f6Sjeremylt def __del__(self): 32c8e769f6Sjeremylt # libCEED call 33477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionDestroy(self._pointer) 34477729cfSJeremy L Thompson self._ceed._check_error(err_code) 35c8e769f6Sjeremylt 36c8e769f6Sjeremylt # Representation 37c8e769f6Sjeremylt def __repr__(self): 38c8e769f6Sjeremylt return "<CeedElemRestriction instance at " + hex(id(self)) + ">" 39c8e769f6Sjeremylt 40c8e769f6Sjeremylt # String conversion for print() to stdout 41c8e769f6Sjeremylt def __str__(self): 42c8e769f6Sjeremylt """View an ElemRestriction via print().""" 43c8e769f6Sjeremylt 44c8e769f6Sjeremylt # libCEED call 45c8e769f6Sjeremylt with tempfile.NamedTemporaryFile() as key_file: 46c8e769f6Sjeremylt with open(key_file.name, 'r+') as stream_file: 47c8e769f6Sjeremylt stream = ffi.cast("FILE *", stream_file) 48c8e769f6Sjeremylt 49477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionView(self._pointer[0], stream) 50477729cfSJeremy L Thompson self._ceed._check_error(err_code) 51c8e769f6Sjeremylt 52c8e769f6Sjeremylt stream_file.seek(0) 53c8e769f6Sjeremylt out_string = stream_file.read() 54c8e769f6Sjeremylt 55c8e769f6Sjeremylt return out_string 56c8e769f6Sjeremylt 57c8e769f6Sjeremylt # Apply CeedElemRestriction 58a8d32208Sjeremylt def apply(self, u, v, tmode=NOTRANSPOSE, request=REQUEST_IMMEDIATE): 59c8e769f6Sjeremylt """Restrict a local vector to an element vector or apply its transpose. 60c8e769f6Sjeremylt 61c8e769f6Sjeremylt Args: 62c8e769f6Sjeremylt u: input vector 63c8e769f6Sjeremylt v: output vector 64c8e769f6Sjeremylt **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE 65c8e769f6Sjeremylt **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 66c8e769f6Sjeremylt 67c8e769f6Sjeremylt # libCEED call 68477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionApply(self._pointer[0], tmode, u._pointer[0], 69a8d32208Sjeremylt v._pointer[0], request) 70477729cfSJeremy L Thompson self._ceed._check_error(err_code) 71c8e769f6Sjeremylt 72c8e769f6Sjeremylt # Transpose an ElemRestriction 73c8e769f6Sjeremylt @property 74c8e769f6Sjeremylt def T(self): 75c8e769f6Sjeremylt """Transpose an ElemRestriction.""" 76c8e769f6Sjeremylt 77c8e769f6Sjeremylt return TransposeElemRestriction(self) 78c8e769f6Sjeremylt 79c8e769f6Sjeremylt # Transpose an ElemRestriction 80c8e769f6Sjeremylt @property 81c8e769f6Sjeremylt def transpose(self): 82c8e769f6Sjeremylt """Transpose an ElemRestriction.""" 83c8e769f6Sjeremylt 84c8e769f6Sjeremylt return TransposeElemRestriction(self) 85c8e769f6Sjeremylt 86c8e769f6Sjeremylt # Create restriction vectors 87c8e769f6Sjeremylt def create_vector(self, createLvec=True, createEvec=True): 88c8e769f6Sjeremylt """Create Vectors associated with an ElemRestriction. 89c8e769f6Sjeremylt 90c8e769f6Sjeremylt Args: 91c8e769f6Sjeremylt **createLvec: flag to create local vector, default True 92c8e769f6Sjeremylt **createEvec: flag to create element vector, default True 93c8e769f6Sjeremylt 94c8e769f6Sjeremylt Returns: 95c8e769f6Sjeremylt [lvec, evec]: local vector and element vector, or None if flag set to false""" 96c8e769f6Sjeremylt 97c8e769f6Sjeremylt # Vector pointers 98c8e769f6Sjeremylt lvecPointer = ffi.new("CeedVector *") if createLvec else ffi.NULL 99c8e769f6Sjeremylt evecPointer = ffi.new("CeedVector *") if createEvec else ffi.NULL 100c8e769f6Sjeremylt 101c8e769f6Sjeremylt # libCEED call 102477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionCreateVector(self._pointer[0], lvecPointer, 103c8e769f6Sjeremylt evecPointer) 104477729cfSJeremy L Thompson self._ceed._check_error(err_code) 105c8e769f6Sjeremylt 106c8e769f6Sjeremylt # Return vectors 1077a7b0fa3SJed Brown lvec = _VectorWrap( 108477729cfSJeremy L Thompson self._ceed, lvecPointer) if createLvec else None 1097a7b0fa3SJed Brown evec = _VectorWrap( 110477729cfSJeremy L Thompson self._ceed, evecPointer) if createEvec else None 111c8e769f6Sjeremylt 112c8e769f6Sjeremylt # Return 113c8e769f6Sjeremylt return [lvec, evec] 114c8e769f6Sjeremylt 115c8e769f6Sjeremylt # Get ElemRestriction multiplicity 116a8d32208Sjeremylt def get_multiplicity(self): 117c8e769f6Sjeremylt """Get the multiplicity of nodes in an ElemRestriction. 118c8e769f6Sjeremylt 119c8e769f6Sjeremylt Returns: 120c8e769f6Sjeremylt mult: local vector containing multiplicity of nodes in ElemRestriction""" 121c8e769f6Sjeremylt 122c8e769f6Sjeremylt # Create mult vector 123c8e769f6Sjeremylt [mult, evec] = self.create_vector(createEvec=False) 124c8e769f6Sjeremylt mult.set_value(0) 125c8e769f6Sjeremylt 126c8e769f6Sjeremylt # libCEED call 127477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionGetMultiplicity( 1287a7b0fa3SJed Brown self._pointer[0], mult._pointer[0]) 129477729cfSJeremy L Thompson self._ceed._check_error(err_code) 130c8e769f6Sjeremylt 131c8e769f6Sjeremylt # Return 132c8e769f6Sjeremylt return mult 133c8e769f6Sjeremylt 134*c3a5a609SJeremy L Thompson # Get ElemRestrition Layout 135*c3a5a609SJeremy L Thompson def get_layout(self): 136*c3a5a609SJeremy L Thompson """Get the element vector layout of an ElemRestriction. 137*c3a5a609SJeremy L Thompson 138*c3a5a609SJeremy L Thompson Returns: 139*c3a5a609SJeremy L Thompson layout: Vector containing layout array, stored as [nodes, components, elements]. 140*c3a5a609SJeremy L Thompson The data for node i, component j, element k in the element 141*c3a5a609SJeremy L Thompson vector is given by i*layout[0] + j*layout[1] + k*layout[2].""" 142*c3a5a609SJeremy L Thompson 143*c3a5a609SJeremy L Thompson # Create output array 144*c3a5a609SJeremy L Thompson layout = np.zeros(3, dtype="int32") 145*c3a5a609SJeremy L Thompson array_pointer = ffi.cast( 146*c3a5a609SJeremy L Thompson "CeedInt *", 147*c3a5a609SJeremy L Thompson layout.__array_interface__['data'][0]) 148*c3a5a609SJeremy L Thompson 149*c3a5a609SJeremy L Thompson # libCEED call 150*c3a5a609SJeremy L Thompson err_code = lib.CeedElemRestrictionGetELayout( 151*c3a5a609SJeremy L Thompson self._pointer[0], array_pointer) 152*c3a5a609SJeremy L Thompson self._ceed._check_error(err_code) 153*c3a5a609SJeremy L Thompson 154*c3a5a609SJeremy L Thompson # Return 155*c3a5a609SJeremy L Thompson return layout 156*c3a5a609SJeremy L Thompson 157c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 1587a7b0fa3SJed Brown 1597a7b0fa3SJed Brown 160c8e769f6Sjeremyltclass ElemRestriction(_ElemRestrictionBase): 161c8e769f6Sjeremylt """Ceed ElemRestriction: restriction from local vectors to elements.""" 162c8e769f6Sjeremylt 163c8e769f6Sjeremylt # Constructor 164d979a051Sjeremylt def __init__(self, ceed, nelem, elemsize, ncomp, compstride, lsize, offsets, 165d979a051Sjeremylt memtype=MEM_HOST, cmode=COPY_VALUES): 166c8e769f6Sjeremylt # CeedVector object 167c8e769f6Sjeremylt self._pointer = ffi.new("CeedElemRestriction *") 168c8e769f6Sjeremylt 169c8e769f6Sjeremylt # Reference to Ceed 170c8e769f6Sjeremylt self._ceed = ceed 171c8e769f6Sjeremylt 172187168c7SJeremy L Thompson # Store array reference if needed 173187168c7SJeremy L Thompson if cmode == USE_POINTER: 174187168c7SJeremy L Thompson self._array_reference = offsets 175187168c7SJeremy L Thompson else: 176187168c7SJeremy L Thompson self._array_reference = None 177187168c7SJeremy L Thompson 178c8e769f6Sjeremylt # Setup the numpy array for the libCEED call 179d979a051Sjeremylt offsets_pointer = ffi.new("const CeedInt *") 180d979a051Sjeremylt offsets_pointer = ffi.cast("const CeedInt *", 181d979a051Sjeremylt offsets.__array_interface__['data'][0]) 182c8e769f6Sjeremylt 183c8e769f6Sjeremylt # libCEED call 184477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionCreate(self._ceed._pointer[0], nelem, 185477729cfSJeremy L Thompson elemsize, ncomp, compstride, 186477729cfSJeremy L Thompson lsize, memtype, cmode, 187d979a051Sjeremylt offsets_pointer, self._pointer) 188477729cfSJeremy L Thompson self._ceed._check_error(err_code) 189c8e769f6Sjeremylt 190c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 1917a7b0fa3SJed Brown 1927a7b0fa3SJed Brown 19369a53589Sjeremyltclass StridedElemRestriction(_ElemRestrictionBase): 19469a53589Sjeremylt """Ceed Strided ElemRestriction: strided restriction from local vectors to elements.""" 195c8e769f6Sjeremylt 196c8e769f6Sjeremylt # Constructor 197d979a051Sjeremylt def __init__(self, ceed, nelem, elemsize, ncomp, lsize, strides): 198c8e769f6Sjeremylt # CeedVector object 199c8e769f6Sjeremylt self._pointer = ffi.new("CeedElemRestriction *") 200c8e769f6Sjeremylt 201c8e769f6Sjeremylt # Reference to Ceed 202c8e769f6Sjeremylt self._ceed = ceed 203c8e769f6Sjeremylt 20469a53589Sjeremylt # Setup the numpy array for the libCEED call 20569a53589Sjeremylt strides_pointer = ffi.new("const CeedInt *") 20669a53589Sjeremylt strides_pointer = ffi.cast("const CeedInt *", 20769a53589Sjeremylt strides.__array_interface__['data'][0]) 20869a53589Sjeremylt 209c8e769f6Sjeremylt # libCEED call 210477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionCreateStrided(self._ceed._pointer[0], 211477729cfSJeremy L Thompson nelem, elemsize, ncomp, 212477729cfSJeremy L Thompson lsize, strides_pointer, 213477729cfSJeremy L Thompson self._pointer) 214477729cfSJeremy L Thompson self._ceed._check_error(err_code) 215c8e769f6Sjeremylt 216c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 2177a7b0fa3SJed Brown 2187a7b0fa3SJed Brown 219c8e769f6Sjeremyltclass BlockedElemRestriction(_ElemRestrictionBase): 220c8e769f6Sjeremylt """Ceed Blocked ElemRestriction: blocked restriction from local vectors to elements.""" 221c8e769f6Sjeremylt 222c8e769f6Sjeremylt # Constructor 223d979a051Sjeremylt def __init__(self, ceed, nelem, elemsize, blksize, ncomp, compstride, lsize, 224d979a051Sjeremylt offsets, memtype=MEM_HOST, cmode=COPY_VALUES): 225c8e769f6Sjeremylt # CeedVector object 226c8e769f6Sjeremylt self._pointer = ffi.new("CeedElemRestriction *") 227c8e769f6Sjeremylt 228c8e769f6Sjeremylt # Reference to Ceed 229c8e769f6Sjeremylt self._ceed = ceed 230c8e769f6Sjeremylt 231c8e769f6Sjeremylt # Setup the numpy array for the libCEED call 232d979a051Sjeremylt offsets_pointer = ffi.new("const CeedInt *") 233d979a051Sjeremylt offsets_pointer = ffi.cast("const CeedInt *", 234d979a051Sjeremylt offsets.__array_interface__['data'][0]) 235c8e769f6Sjeremylt 236c8e769f6Sjeremylt # libCEED call 237477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionCreateBlocked(self._ceed._pointer[0], nelem, 238d979a051Sjeremylt elemsize, blksize, ncomp, 239d979a051Sjeremylt compstride, lsize, memtype, cmode, 240d979a051Sjeremylt offsets_pointer, self._pointer) 241477729cfSJeremy L Thompson self._ceed._check_error(err_code) 242c8e769f6Sjeremylt 243c8e769f6Sjeremylt # Transpose a Blocked ElemRestriction 244c8e769f6Sjeremylt @property 245c8e769f6Sjeremylt def T(self): 246c8e769f6Sjeremylt """Transpose a BlockedElemRestriction.""" 247c8e769f6Sjeremylt 248c8e769f6Sjeremylt return TransposeBlockedElemRestriction(self) 249c8e769f6Sjeremylt 250c8e769f6Sjeremylt # Transpose a Blocked ElemRestriction 251c8e769f6Sjeremylt @property 252c8e769f6Sjeremylt def transpose(self): 253c8e769f6Sjeremylt """Transpose a BlockedElemRestriction.""" 254c8e769f6Sjeremylt 255c8e769f6Sjeremylt return TransposeBlockedElemRestriction(self) 256c8e769f6Sjeremylt 257c8e769f6Sjeremylt # Apply CeedElemRestriction to single block 258a8d32208Sjeremylt def apply_block(self, block, u, v, tmode=NOTRANSPOSE, 259c8e769f6Sjeremylt request=REQUEST_IMMEDIATE): 260c8e769f6Sjeremylt """Restrict a local vector to a block of an element vector or apply its transpose. 261c8e769f6Sjeremylt 262c8e769f6Sjeremylt Args: 263c8e769f6Sjeremylt block: block number to restrict to/from, i.e. block=0 will handle 264c8e769f6Sjeremylt elements [0 : blksize] and block=3 will handle elements 265c8e769f6Sjeremylt [3*blksize : 4*blksize] 266c8e769f6Sjeremylt u: input vector 267c8e769f6Sjeremylt v: output vector 268c8e769f6Sjeremylt **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE 269c8e769f6Sjeremylt **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 270c8e769f6Sjeremylt 271c8e769f6Sjeremylt # libCEED call 272477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionApplyBlock(self._pointer[0], block, tmode, 273477729cfSJeremy L Thompson u._pointer[0], v._pointer[0], 274477729cfSJeremy L Thompson request) 275477729cfSJeremy L Thompson self._ceed._check_error(err_code) 276c8e769f6Sjeremylt 277c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 2787a7b0fa3SJed Brown 2797a7b0fa3SJed Brown 28069a53589Sjeremyltclass BlockedStridedElemRestriction(BlockedElemRestriction): 28169a53589Sjeremylt """Ceed Blocked Strided ElemRestriction: strided restriction from local vectors to elements.""" 28269a53589Sjeremylt 28369a53589Sjeremylt # Constructor 284d979a051Sjeremylt def __init__(self, ceed, nelem, elemsize, blksize, ncomp, lsize, strides): 28569a53589Sjeremylt # CeedVector object 28669a53589Sjeremylt self._pointer = ffi.new("CeedElemRestriction *") 28769a53589Sjeremylt 28869a53589Sjeremylt # Reference to Ceed 28969a53589Sjeremylt self._ceed = ceed 29069a53589Sjeremylt 29169a53589Sjeremylt # Setup the numpy array for the libCEED call 29269a53589Sjeremylt strides_pointer = ffi.new("const CeedInt *") 29369a53589Sjeremylt strides_pointer = ffi.cast("const CeedInt *", 29469a53589Sjeremylt strides.__array_interface__['data'][0]) 29569a53589Sjeremylt 29669a53589Sjeremylt # libCEED call 297477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionCreateBlockedStrided(self._ceed._pointer[0], nelem, 298d979a051Sjeremylt elemsize, blksize, ncomp, 299d979a051Sjeremylt lsize, strides_pointer, 30069a53589Sjeremylt self._pointer) 301477729cfSJeremy L Thompson self._ceed._check_error(err_code) 30269a53589Sjeremylt 30369a53589Sjeremylt# ------------------------------------------------------------------------------ 3047a7b0fa3SJed Brown 3057a7b0fa3SJed Brown 306c8e769f6Sjeremyltclass TransposeElemRestriction(): 307c8e769f6Sjeremylt """Ceed ElemRestriction: transpose restriction from elements to local vectors.""" 308c8e769f6Sjeremylt 309c8e769f6Sjeremylt # Attributes 310c8e769f6Sjeremylt _elemrestriction = None 311c8e769f6Sjeremylt 312c8e769f6Sjeremylt # Constructor 313c8e769f6Sjeremylt def __init__(self, elemrestriction): 314c8e769f6Sjeremylt 315c8e769f6Sjeremylt # Reference elemrestriction 316c8e769f6Sjeremylt self._elemrestriction = elemrestriction 317c8e769f6Sjeremylt 318c8e769f6Sjeremylt # Representation 319c8e769f6Sjeremylt def __repr__(self): 3207a7b0fa3SJed Brown return "<Transpose CeedElemRestriction instance at " + \ 3217a7b0fa3SJed Brown hex(id(self)) + ">" 322c8e769f6Sjeremylt 323c8e769f6Sjeremylt # Apply Transpose CeedElemRestriction 3247a7b0fa3SJed Brown 325a8d32208Sjeremylt def apply(self, u, v, request=REQUEST_IMMEDIATE): 326c8e769f6Sjeremylt """Restrict an element vector to a local vector. 327c8e769f6Sjeremylt 328c8e769f6Sjeremylt Args: 329c8e769f6Sjeremylt u: input vector 330c8e769f6Sjeremylt v: output vector 331c8e769f6Sjeremylt **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 332c8e769f6Sjeremylt 333c8e769f6Sjeremylt # libCEED call 334a8d32208Sjeremylt self._elemrestriction.apply(u, v, request=request, tmode=TRANSPOSE) 335c8e769f6Sjeremylt 336c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 3377a7b0fa3SJed Brown 3387a7b0fa3SJed Brown 339c8e769f6Sjeremyltclass TransposeBlockedElemRestriction(TransposeElemRestriction): 340c8e769f6Sjeremylt """Transpose Ceed Blocked ElemRestriction: blocked transpose restriction from elements 341c8e769f6Sjeremylt to local vectors.""" 342c8e769f6Sjeremylt 343c8e769f6Sjeremylt # Apply Transpose CeedElemRestriction 344a8d32208Sjeremylt def apply_block(self, block, u, v, request=REQUEST_IMMEDIATE): 345c8e769f6Sjeremylt """Restrict a block of an element vector to a local vector. 346c8e769f6Sjeremylt 347c8e769f6Sjeremylt Args: 348c8e769f6Sjeremylt block: block number to restrict to/from, i.e. block=0 will handle 349c8e769f6Sjeremylt elements [0 : blksize] and block=3 will handle elements 350c8e769f6Sjeremylt [3*blksize : 4*blksize] 351c8e769f6Sjeremylt u: input vector 352c8e769f6Sjeremylt v: output vector 353c8e769f6Sjeremylt **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 354c8e769f6Sjeremylt 355c8e769f6Sjeremylt # libCEED call 356a8d32208Sjeremylt self._elemrestriction.apply_block(block, u, v, request=request, 357c8e769f6Sjeremylt tmode=TRANSPOSE) 358c8e769f6Sjeremylt 359c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 360