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