1*3d8e8822SJeremy L Thompson# Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors 2*3d8e8822SJeremy L Thompson# All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3c8e769f6Sjeremylt# 4*3d8e8822SJeremy L Thompson# SPDX-License-Identifier: BSD-2-Clause 5c8e769f6Sjeremylt# 6*3d8e8822SJeremy L Thompson# This file is part of CEED: http://github.com/ceed 7c8e769f6Sjeremylt 8c8e769f6Sjeremyltfrom _ceed_cffi import ffi, lib 9c8e769f6Sjeremyltimport tempfile 10c8e769f6Sjeremyltimport numpy as np 11c8e769f6Sjeremyltfrom abc import ABC 12187168c7SJeremy L Thompsonfrom .ceed_constants import REQUEST_IMMEDIATE, REQUEST_ORDERED, MEM_HOST, USE_POINTER, COPY_VALUES, TRANSPOSE, NOTRANSPOSE 13c8e769f6Sjeremyltfrom .ceed_vector import _VectorWrap 14c8e769f6Sjeremylt 15c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 167a7b0fa3SJed Brown 177a7b0fa3SJed Brown 18c8e769f6Sjeremyltclass _ElemRestrictionBase(ABC): 19c8e769f6Sjeremylt """Ceed ElemRestriction: restriction from local vectors to elements.""" 20c8e769f6Sjeremylt 21c8e769f6Sjeremylt # Destructor 22c8e769f6Sjeremylt def __del__(self): 23c8e769f6Sjeremylt # libCEED call 24477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionDestroy(self._pointer) 25477729cfSJeremy L Thompson self._ceed._check_error(err_code) 26c8e769f6Sjeremylt 27c8e769f6Sjeremylt # Representation 28c8e769f6Sjeremylt def __repr__(self): 29c8e769f6Sjeremylt return "<CeedElemRestriction instance at " + hex(id(self)) + ">" 30c8e769f6Sjeremylt 31c8e769f6Sjeremylt # String conversion for print() to stdout 32c8e769f6Sjeremylt def __str__(self): 33c8e769f6Sjeremylt """View an ElemRestriction via print().""" 34c8e769f6Sjeremylt 35c8e769f6Sjeremylt # libCEED call 36c8e769f6Sjeremylt with tempfile.NamedTemporaryFile() as key_file: 37c8e769f6Sjeremylt with open(key_file.name, 'r+') as stream_file: 38c8e769f6Sjeremylt stream = ffi.cast("FILE *", stream_file) 39c8e769f6Sjeremylt 40477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionView(self._pointer[0], stream) 41477729cfSJeremy L Thompson self._ceed._check_error(err_code) 42c8e769f6Sjeremylt 43c8e769f6Sjeremylt stream_file.seek(0) 44c8e769f6Sjeremylt out_string = stream_file.read() 45c8e769f6Sjeremylt 46c8e769f6Sjeremylt return out_string 47c8e769f6Sjeremylt 48c8e769f6Sjeremylt # Apply CeedElemRestriction 49a8d32208Sjeremylt def apply(self, u, v, tmode=NOTRANSPOSE, request=REQUEST_IMMEDIATE): 50c8e769f6Sjeremylt """Restrict a local vector to an element vector or apply its transpose. 51c8e769f6Sjeremylt 52c8e769f6Sjeremylt Args: 53c8e769f6Sjeremylt u: input vector 54c8e769f6Sjeremylt v: output vector 55c8e769f6Sjeremylt **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE 56c8e769f6Sjeremylt **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 57c8e769f6Sjeremylt 58c8e769f6Sjeremylt # libCEED call 59477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionApply(self._pointer[0], tmode, u._pointer[0], 60a8d32208Sjeremylt v._pointer[0], request) 61477729cfSJeremy L Thompson self._ceed._check_error(err_code) 62c8e769f6Sjeremylt 63c8e769f6Sjeremylt # Transpose an ElemRestriction 64c8e769f6Sjeremylt @property 65c8e769f6Sjeremylt def T(self): 66c8e769f6Sjeremylt """Transpose an ElemRestriction.""" 67c8e769f6Sjeremylt 68c8e769f6Sjeremylt return TransposeElemRestriction(self) 69c8e769f6Sjeremylt 70c8e769f6Sjeremylt # Transpose an ElemRestriction 71c8e769f6Sjeremylt @property 72c8e769f6Sjeremylt def transpose(self): 73c8e769f6Sjeremylt """Transpose an ElemRestriction.""" 74c8e769f6Sjeremylt 75c8e769f6Sjeremylt return TransposeElemRestriction(self) 76c8e769f6Sjeremylt 77c8e769f6Sjeremylt # Create restriction vectors 78c8e769f6Sjeremylt def create_vector(self, createLvec=True, createEvec=True): 79c8e769f6Sjeremylt """Create Vectors associated with an ElemRestriction. 80c8e769f6Sjeremylt 81c8e769f6Sjeremylt Args: 82c8e769f6Sjeremylt **createLvec: flag to create local vector, default True 83c8e769f6Sjeremylt **createEvec: flag to create element vector, default True 84c8e769f6Sjeremylt 85c8e769f6Sjeremylt Returns: 86c8e769f6Sjeremylt [lvec, evec]: local vector and element vector, or None if flag set to false""" 87c8e769f6Sjeremylt 88c8e769f6Sjeremylt # Vector pointers 89c8e769f6Sjeremylt lvecPointer = ffi.new("CeedVector *") if createLvec else ffi.NULL 90c8e769f6Sjeremylt evecPointer = ffi.new("CeedVector *") if createEvec else ffi.NULL 91c8e769f6Sjeremylt 92c8e769f6Sjeremylt # libCEED call 93477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionCreateVector(self._pointer[0], lvecPointer, 94c8e769f6Sjeremylt evecPointer) 95477729cfSJeremy L Thompson self._ceed._check_error(err_code) 96c8e769f6Sjeremylt 97c8e769f6Sjeremylt # Return vectors 987a7b0fa3SJed Brown lvec = _VectorWrap( 99477729cfSJeremy L Thompson self._ceed, lvecPointer) if createLvec else None 1007a7b0fa3SJed Brown evec = _VectorWrap( 101477729cfSJeremy L Thompson self._ceed, evecPointer) if createEvec else None 102c8e769f6Sjeremylt 103c8e769f6Sjeremylt # Return 104c8e769f6Sjeremylt return [lvec, evec] 105c8e769f6Sjeremylt 106c8e769f6Sjeremylt # Get ElemRestriction multiplicity 107a8d32208Sjeremylt def get_multiplicity(self): 108c8e769f6Sjeremylt """Get the multiplicity of nodes in an ElemRestriction. 109c8e769f6Sjeremylt 110c8e769f6Sjeremylt Returns: 111c8e769f6Sjeremylt mult: local vector containing multiplicity of nodes in ElemRestriction""" 112c8e769f6Sjeremylt 113c8e769f6Sjeremylt # Create mult vector 114c8e769f6Sjeremylt [mult, evec] = self.create_vector(createEvec=False) 115c8e769f6Sjeremylt mult.set_value(0) 116c8e769f6Sjeremylt 117c8e769f6Sjeremylt # libCEED call 118477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionGetMultiplicity( 1197a7b0fa3SJed Brown self._pointer[0], mult._pointer[0]) 120477729cfSJeremy L Thompson self._ceed._check_error(err_code) 121c8e769f6Sjeremylt 122c8e769f6Sjeremylt # Return 123c8e769f6Sjeremylt return mult 124c8e769f6Sjeremylt 125c3a5a609SJeremy L Thompson # Get ElemRestrition Layout 126c3a5a609SJeremy L Thompson def get_layout(self): 127c3a5a609SJeremy L Thompson """Get the element vector layout of an ElemRestriction. 128c3a5a609SJeremy L Thompson 129c3a5a609SJeremy L Thompson Returns: 130c3a5a609SJeremy L Thompson layout: Vector containing layout array, stored as [nodes, components, elements]. 131c3a5a609SJeremy L Thompson The data for node i, component j, element k in the element 132c3a5a609SJeremy L Thompson vector is given by i*layout[0] + j*layout[1] + k*layout[2].""" 133c3a5a609SJeremy L Thompson 134c3a5a609SJeremy L Thompson # Create output array 135c3a5a609SJeremy L Thompson layout = np.zeros(3, dtype="int32") 136c3a5a609SJeremy L Thompson array_pointer = ffi.cast( 137c3a5a609SJeremy L Thompson "CeedInt *", 138c3a5a609SJeremy L Thompson layout.__array_interface__['data'][0]) 139c3a5a609SJeremy L Thompson 140c3a5a609SJeremy L Thompson # libCEED call 141c3a5a609SJeremy L Thompson err_code = lib.CeedElemRestrictionGetELayout( 142c3a5a609SJeremy L Thompson self._pointer[0], array_pointer) 143c3a5a609SJeremy L Thompson self._ceed._check_error(err_code) 144c3a5a609SJeremy L Thompson 145c3a5a609SJeremy L Thompson # Return 146c3a5a609SJeremy L Thompson return layout 147c3a5a609SJeremy L Thompson 148c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 1497a7b0fa3SJed Brown 1507a7b0fa3SJed Brown 151c8e769f6Sjeremyltclass ElemRestriction(_ElemRestrictionBase): 152c8e769f6Sjeremylt """Ceed ElemRestriction: restriction from local vectors to elements.""" 153c8e769f6Sjeremylt 154c8e769f6Sjeremylt # Constructor 155d979a051Sjeremylt def __init__(self, ceed, nelem, elemsize, ncomp, compstride, lsize, offsets, 156d979a051Sjeremylt memtype=MEM_HOST, cmode=COPY_VALUES): 157c8e769f6Sjeremylt # CeedVector object 158c8e769f6Sjeremylt self._pointer = ffi.new("CeedElemRestriction *") 159c8e769f6Sjeremylt 160c8e769f6Sjeremylt # Reference to Ceed 161c8e769f6Sjeremylt self._ceed = ceed 162c8e769f6Sjeremylt 163187168c7SJeremy L Thompson # Store array reference if needed 164187168c7SJeremy L Thompson if cmode == USE_POINTER: 165187168c7SJeremy L Thompson self._array_reference = offsets 166187168c7SJeremy L Thompson else: 167187168c7SJeremy L Thompson self._array_reference = None 168187168c7SJeremy L Thompson 169c8e769f6Sjeremylt # Setup the numpy array for the libCEED call 170d979a051Sjeremylt offsets_pointer = ffi.new("const CeedInt *") 171d979a051Sjeremylt offsets_pointer = ffi.cast("const CeedInt *", 172d979a051Sjeremylt offsets.__array_interface__['data'][0]) 173c8e769f6Sjeremylt 174c8e769f6Sjeremylt # libCEED call 175477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionCreate(self._ceed._pointer[0], nelem, 176477729cfSJeremy L Thompson elemsize, ncomp, compstride, 177477729cfSJeremy L Thompson lsize, memtype, cmode, 178d979a051Sjeremylt offsets_pointer, self._pointer) 179477729cfSJeremy L Thompson self._ceed._check_error(err_code) 180c8e769f6Sjeremylt 181c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 1827a7b0fa3SJed Brown 1837a7b0fa3SJed Brown 18469a53589Sjeremyltclass StridedElemRestriction(_ElemRestrictionBase): 18569a53589Sjeremylt """Ceed Strided ElemRestriction: strided restriction from local vectors to elements.""" 186c8e769f6Sjeremylt 187c8e769f6Sjeremylt # Constructor 188d979a051Sjeremylt def __init__(self, ceed, nelem, elemsize, ncomp, lsize, strides): 189c8e769f6Sjeremylt # CeedVector object 190c8e769f6Sjeremylt self._pointer = ffi.new("CeedElemRestriction *") 191c8e769f6Sjeremylt 192c8e769f6Sjeremylt # Reference to Ceed 193c8e769f6Sjeremylt self._ceed = ceed 194c8e769f6Sjeremylt 19569a53589Sjeremylt # Setup the numpy array for the libCEED call 19669a53589Sjeremylt strides_pointer = ffi.new("const CeedInt *") 19769a53589Sjeremylt strides_pointer = ffi.cast("const CeedInt *", 19869a53589Sjeremylt strides.__array_interface__['data'][0]) 19969a53589Sjeremylt 200c8e769f6Sjeremylt # libCEED call 201477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionCreateStrided(self._ceed._pointer[0], 202477729cfSJeremy L Thompson nelem, elemsize, ncomp, 203477729cfSJeremy L Thompson lsize, strides_pointer, 204477729cfSJeremy L Thompson self._pointer) 205477729cfSJeremy L Thompson self._ceed._check_error(err_code) 206c8e769f6Sjeremylt 207c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 2087a7b0fa3SJed Brown 2097a7b0fa3SJed Brown 210c8e769f6Sjeremyltclass BlockedElemRestriction(_ElemRestrictionBase): 211c8e769f6Sjeremylt """Ceed Blocked ElemRestriction: blocked restriction from local vectors to elements.""" 212c8e769f6Sjeremylt 213c8e769f6Sjeremylt # Constructor 214d979a051Sjeremylt def __init__(self, ceed, nelem, elemsize, blksize, ncomp, compstride, lsize, 215d979a051Sjeremylt offsets, memtype=MEM_HOST, cmode=COPY_VALUES): 216c8e769f6Sjeremylt # CeedVector object 217c8e769f6Sjeremylt self._pointer = ffi.new("CeedElemRestriction *") 218c8e769f6Sjeremylt 219c8e769f6Sjeremylt # Reference to Ceed 220c8e769f6Sjeremylt self._ceed = ceed 221c8e769f6Sjeremylt 222c8e769f6Sjeremylt # Setup the numpy array for the libCEED call 223d979a051Sjeremylt offsets_pointer = ffi.new("const CeedInt *") 224d979a051Sjeremylt offsets_pointer = ffi.cast("const CeedInt *", 225d979a051Sjeremylt offsets.__array_interface__['data'][0]) 226c8e769f6Sjeremylt 227c8e769f6Sjeremylt # libCEED call 228477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionCreateBlocked(self._ceed._pointer[0], nelem, 229d979a051Sjeremylt elemsize, blksize, ncomp, 230d979a051Sjeremylt compstride, lsize, memtype, cmode, 231d979a051Sjeremylt offsets_pointer, self._pointer) 232477729cfSJeremy L Thompson self._ceed._check_error(err_code) 233c8e769f6Sjeremylt 234c8e769f6Sjeremylt # Transpose a Blocked ElemRestriction 235c8e769f6Sjeremylt @property 236c8e769f6Sjeremylt def T(self): 237c8e769f6Sjeremylt """Transpose a BlockedElemRestriction.""" 238c8e769f6Sjeremylt 239c8e769f6Sjeremylt return TransposeBlockedElemRestriction(self) 240c8e769f6Sjeremylt 241c8e769f6Sjeremylt # Transpose a Blocked ElemRestriction 242c8e769f6Sjeremylt @property 243c8e769f6Sjeremylt def transpose(self): 244c8e769f6Sjeremylt """Transpose a BlockedElemRestriction.""" 245c8e769f6Sjeremylt 246c8e769f6Sjeremylt return TransposeBlockedElemRestriction(self) 247c8e769f6Sjeremylt 248c8e769f6Sjeremylt # Apply CeedElemRestriction to single block 249a8d32208Sjeremylt def apply_block(self, block, u, v, tmode=NOTRANSPOSE, 250c8e769f6Sjeremylt request=REQUEST_IMMEDIATE): 251c8e769f6Sjeremylt """Restrict a local vector to a block of an element vector or apply its transpose. 252c8e769f6Sjeremylt 253c8e769f6Sjeremylt Args: 254c8e769f6Sjeremylt block: block number to restrict to/from, i.e. block=0 will handle 255c8e769f6Sjeremylt elements [0 : blksize] and block=3 will handle elements 256c8e769f6Sjeremylt [3*blksize : 4*blksize] 257c8e769f6Sjeremylt u: input vector 258c8e769f6Sjeremylt v: output vector 259c8e769f6Sjeremylt **tmode: apply restriction or transpose, default CEED_NOTRANSPOSE 260c8e769f6Sjeremylt **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 261c8e769f6Sjeremylt 262c8e769f6Sjeremylt # libCEED call 263477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionApplyBlock(self._pointer[0], block, tmode, 264477729cfSJeremy L Thompson u._pointer[0], v._pointer[0], 265477729cfSJeremy L Thompson request) 266477729cfSJeremy L Thompson self._ceed._check_error(err_code) 267c8e769f6Sjeremylt 268c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 2697a7b0fa3SJed Brown 2707a7b0fa3SJed Brown 27169a53589Sjeremyltclass BlockedStridedElemRestriction(BlockedElemRestriction): 27269a53589Sjeremylt """Ceed Blocked Strided ElemRestriction: strided restriction from local vectors to elements.""" 27369a53589Sjeremylt 27469a53589Sjeremylt # Constructor 275d979a051Sjeremylt def __init__(self, ceed, nelem, elemsize, blksize, ncomp, lsize, strides): 27669a53589Sjeremylt # CeedVector object 27769a53589Sjeremylt self._pointer = ffi.new("CeedElemRestriction *") 27869a53589Sjeremylt 27969a53589Sjeremylt # Reference to Ceed 28069a53589Sjeremylt self._ceed = ceed 28169a53589Sjeremylt 28269a53589Sjeremylt # Setup the numpy array for the libCEED call 28369a53589Sjeremylt strides_pointer = ffi.new("const CeedInt *") 28469a53589Sjeremylt strides_pointer = ffi.cast("const CeedInt *", 28569a53589Sjeremylt strides.__array_interface__['data'][0]) 28669a53589Sjeremylt 28769a53589Sjeremylt # libCEED call 288477729cfSJeremy L Thompson err_code = lib.CeedElemRestrictionCreateBlockedStrided(self._ceed._pointer[0], nelem, 289d979a051Sjeremylt elemsize, blksize, ncomp, 290d979a051Sjeremylt lsize, strides_pointer, 29169a53589Sjeremylt self._pointer) 292477729cfSJeremy L Thompson self._ceed._check_error(err_code) 29369a53589Sjeremylt 29469a53589Sjeremylt# ------------------------------------------------------------------------------ 2957a7b0fa3SJed Brown 2967a7b0fa3SJed Brown 297c8e769f6Sjeremyltclass TransposeElemRestriction(): 298c8e769f6Sjeremylt """Ceed ElemRestriction: transpose restriction from elements to local vectors.""" 299c8e769f6Sjeremylt 300c8e769f6Sjeremylt # Attributes 301c8e769f6Sjeremylt _elemrestriction = None 302c8e769f6Sjeremylt 303c8e769f6Sjeremylt # Constructor 304c8e769f6Sjeremylt def __init__(self, elemrestriction): 305c8e769f6Sjeremylt 306c8e769f6Sjeremylt # Reference elemrestriction 307c8e769f6Sjeremylt self._elemrestriction = elemrestriction 308c8e769f6Sjeremylt 309c8e769f6Sjeremylt # Representation 310c8e769f6Sjeremylt def __repr__(self): 3117a7b0fa3SJed Brown return "<Transpose CeedElemRestriction instance at " + \ 3127a7b0fa3SJed Brown hex(id(self)) + ">" 313c8e769f6Sjeremylt 314c8e769f6Sjeremylt # Apply Transpose CeedElemRestriction 3157a7b0fa3SJed Brown 316a8d32208Sjeremylt def apply(self, u, v, request=REQUEST_IMMEDIATE): 317c8e769f6Sjeremylt """Restrict an element vector to a local vector. 318c8e769f6Sjeremylt 319c8e769f6Sjeremylt Args: 320c8e769f6Sjeremylt u: input vector 321c8e769f6Sjeremylt v: output vector 322c8e769f6Sjeremylt **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 323c8e769f6Sjeremylt 324c8e769f6Sjeremylt # libCEED call 325a8d32208Sjeremylt self._elemrestriction.apply(u, v, request=request, tmode=TRANSPOSE) 326c8e769f6Sjeremylt 327c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 3287a7b0fa3SJed Brown 3297a7b0fa3SJed Brown 330c8e769f6Sjeremyltclass TransposeBlockedElemRestriction(TransposeElemRestriction): 331c8e769f6Sjeremylt """Transpose Ceed Blocked ElemRestriction: blocked transpose restriction from elements 332c8e769f6Sjeremylt to local vectors.""" 333c8e769f6Sjeremylt 334c8e769f6Sjeremylt # Apply Transpose CeedElemRestriction 335a8d32208Sjeremylt def apply_block(self, block, u, v, request=REQUEST_IMMEDIATE): 336c8e769f6Sjeremylt """Restrict a block of an element vector to a local vector. 337c8e769f6Sjeremylt 338c8e769f6Sjeremylt Args: 339c8e769f6Sjeremylt block: block number to restrict to/from, i.e. block=0 will handle 340c8e769f6Sjeremylt elements [0 : blksize] and block=3 will handle elements 341c8e769f6Sjeremylt [3*blksize : 4*blksize] 342c8e769f6Sjeremylt u: input vector 343c8e769f6Sjeremylt v: output vector 344c8e769f6Sjeremylt **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 345c8e769f6Sjeremylt 346c8e769f6Sjeremylt # libCEED call 347a8d32208Sjeremylt self._elemrestriction.apply_block(block, u, v, request=request, 348c8e769f6Sjeremylt tmode=TRANSPOSE) 349c8e769f6Sjeremylt 350c8e769f6Sjeremylt# ------------------------------------------------------------------------------ 351