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