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 19from abc import ABC 20from .ceed_constants import REQUEST_IMMEDIATE, REQUEST_ORDERED, NOTRANSPOSE 21 22# ------------------------------------------------------------------------------ 23 24 25class _OperatorBase(ABC): 26 """Ceed Operator: composed FE-type operations on vectors.""" 27 28 # Attributes 29 _ceed = ffi.NULL 30 _pointer = ffi.NULL 31 32 # Destructor 33 def __del__(self): 34 # libCEED call 35 err_code = lib.CeedOperatorDestroy(self._pointer) 36 self._ceed._check_error(err_code) 37 38 # Representation 39 def __repr__(self): 40 return "<CeedOperator instance at " + hex(id(self)) + ">" 41 42 # String conversion for print() to stdout 43 def __str__(self): 44 """View an Operator via print().""" 45 46 # libCEED call 47 with tempfile.NamedTemporaryFile() as key_file: 48 with open(key_file.name, 'r+') as stream_file: 49 stream = ffi.cast("FILE *", stream_file) 50 51 err_code = lib.CeedOperatorView(self._pointer[0], stream) 52 self._ceed._check_error(err_code) 53 54 stream_file.seek(0) 55 out_string = stream_file.read() 56 57 return out_string 58 59 # Assemble linear diagonal 60 def linear_assemble_diagonal(self, d, request=REQUEST_IMMEDIATE): 61 """Assemble the diagonal of a square linear Operator 62 63 Args: 64 d: Vector to store assembled Operator diagonal 65 **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 66 67 # libCEED call 68 err_code = lib.CeedOperatorLinearAssembleDiagonal(self._pointer[0], 69 d._pointer[0], request) 70 self._ceed._check_error(err_code) 71 72 # Assemble add linear diagonal 73 def linear_assemble_add_diagonal(self, d, request=REQUEST_IMMEDIATE): 74 """Sum the diagonal of a square linear Operator into a Vector 75 76 Args: 77 d: Vector to store assembled Operator diagonal 78 **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 79 80 # libCEED call 81 err_code = lib.CeedOperatorLinearAssembleAddDiagonal(self._pointer[0], 82 d._pointer[0], request) 83 self._ceed._check_error(err_code) 84 85 # Assemble linear point block diagonal 86 def linear_assemble_point_block_diagonal( 87 self, d, request=REQUEST_IMMEDIATE): 88 """Assemble the point block diagonal of a square linear Operator 89 90 Args: 91 d: Vector to store assembled Operator point block diagonal, 92 provided in row-major form with an ncomp*ncomp block 93 at each node 94 **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 95 96 # libCEED call 97 err_code = lib.CeedOperatorLinearAssemblePointBlockDiagonal(self._pointer[0], 98 d._pointer[0], request) 99 self._ceed._check_error(err_code) 100 101 # Assemble linear point block diagonal 102 def linear_assemble_add_point_block_diagonal( 103 self, d, request=REQUEST_IMMEDIATE): 104 """Sum the point block diagonal of a square linear Operator into a Vector 105 106 Args: 107 d: Vector to store assembled Operator point block diagonal, 108 provided in row-major form with an ncomp*ncomp block 109 at each node 110 **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 111 112 # libCEED call 113 err_code = lib.CeedOperatorLinearAssembleAddPointBlockDiagonal(self._pointer[0], 114 d._pointer[0], request) 115 self._ceed._check_error(err_code) 116 117 # Apply CeedOperator 118 def apply(self, u, v, request=REQUEST_IMMEDIATE): 119 """Apply Operator to a vector. 120 121 Args: 122 u: Vector containing input state or CEED_VECTOR_NONE if there are no 123 active inputs 124 v: Vector to store result of applying operator (must be distinct from u) 125 or CEED_VECTOR_NONE if there are no active outputs 126 **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 127 128 # libCEED call 129 err_code = lib.CeedOperatorApply(self._pointer[0], u._pointer[0], v._pointer[0], 130 request) 131 self._ceed._check_error(err_code) 132 133 # Apply CeedOperator 134 def apply_add(self, u, v, request=REQUEST_IMMEDIATE): 135 """Apply Operator to a vector and add result to output vector. 136 137 Args: 138 u: Vector containing input state or CEED_VECTOR_NONE if there are no 139 active inputs 140 v: Vector to sum in result of applying operator (must be distinct from u) 141 or CEED_VECTOR_NONE if there are no active outputs 142 **request: Ceed request, default CEED_REQUEST_IMMEDIATE""" 143 144 # libCEED call 145 err_code = lib.CeedOperatorApplyAdd(self._pointer[0], u._pointer[0], v._pointer[0], 146 request) 147 self._ceed._check_error(err_code) 148 149# ------------------------------------------------------------------------------ 150 151 152class Operator(_OperatorBase): 153 """Ceed Operator: composed FE-type operations on vectors.""" 154 155 # Constructor 156 def __init__(self, ceed, qf, dqf=None, dqfT=None): 157 # CeedOperator object 158 self._pointer = ffi.new("CeedOperator *") 159 160 # Reference to Ceed 161 self._ceed = ceed 162 163 # libCEED call 164 err_code = lib.CeedOperatorCreate(self._ceed._pointer[0], qf._pointer[0], 165 dqf._pointer[0] if dqf else ffi.NULL, 166 dqfT._pointer[0] if dqfT else ffi.NULL, 167 self._pointer) 168 self._ceed._check_error(err_code) 169 170 # Add field to CeedOperator 171 def set_field(self, fieldname, restriction, basis, vector): 172 """Provide a field to an Operator for use by its QFunction. 173 174 Args: 175 fieldname: name of the field (to be matched with the same name used 176 by QFunction) 177 restriction: ElemRestriction 178 basis: Basis in which the field resides or CEED_BASIS_COLLOCATED 179 if collocated with quadrature points 180 vector: Vector to be used by Operator or CEED_VECTOR_ACTIVE 181 if field is active or CEED_VECTOR_NONE if using 182 CEED_EVAL_WEIGHT in the QFunction""" 183 184 # libCEED call 185 fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii')) 186 err_code = lib.CeedOperatorSetField(self._pointer[0], fieldnameAscii, 187 restriction._pointer[0], basis._pointer[0], 188 vector._pointer[0]) 189 self._ceed._check_error(err_code) 190 191# ------------------------------------------------------------------------------ 192 193 194class CompositeOperator(_OperatorBase): 195 """Ceed Composite Operator: composition of multiple Operators.""" 196 197 # Constructor 198 def __init__(self, ceed): 199 # CeedOperator object 200 self._pointer = ffi.new("CeedOperator *") 201 202 # Reference to Ceed 203 self._ceed = ceed 204 # libCEED call 205 err_code = lib.CeedCompositeOperatorCreate( 206 self._ceed._pointer[0], self._pointer) 207 self._ceed._check_error(err_code) 208 209 # Add sub operators 210 def add_sub(self, subop): 211 """Add a sub-operator to a composite CeedOperator. 212 213 Args: 214 subop: sub-operator Operator""" 215 216 # libCEED call 217 err_code = lib.CeedCompositeOperatorAddSub( 218 self._pointer[0], subop._pointer[0]) 219 self._ceed._check_error(err_code) 220 221# ------------------------------------------------------------------------------ 222