xref: /libCEED/python/ceed_qfunction.py (revision 7d8d0e25636a94a27ff75b3dec09737e24cdb0fe)
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 ctypes
19import tempfile
20from abc import ABC
21
22# ------------------------------------------------------------------------------
23
24
25class _QFunctionBase(ABC):
26    """Ceed QFunction: point-wise operation at quadrature points for evaluating
27         volumetric terms."""
28
29    # Destructor
30    def __del__(self):
31        # libCEED call
32        err_code = lib.CeedQFunctionDestroy(self._pointer)
33        self._ceed._check_error(err_code)
34
35    # Representation
36    def __repr__(self):
37        return "<CeedQFunction instance at " + hex(id(self)) + ">"
38
39    # String conversion for print() to stdout
40    def __str__(self):
41        """View a QFunction via print()."""
42
43        # libCEED call
44        with tempfile.NamedTemporaryFile() as key_file:
45            with open(key_file.name, 'r+') as stream_file:
46                stream = ffi.cast("FILE *", stream_file)
47
48                err_code = lib.CeedQFunctionView(self._pointer[0], stream)
49                self._ceed._check_error(err_code)
50
51                stream_file.seek(0)
52                out_string = stream_file.read()
53
54        return out_string
55
56    # Apply CeedQFunction
57    def apply(self, q, inputs, outputs):
58        """Apply the action of a QFunction.
59
60           Args:
61             q: number of quadrature points
62             *inputs: array of input data vectors
63             *outputs: array of output data vectors"""
64
65        # Array of vectors
66        invecs = ffi.new("CeedVector[16]")
67        for i in range(min(16, len(inputs))):
68            invecs[i] = inputs[i]._pointer[0]
69        outvecs = ffi.new("CeedVector[16]")
70        for i in range(min(16, len(outputs))):
71            outvecs[i] = outputs[i]._pointer[0]
72
73        # libCEED call
74        err_code = lib.CeedQFunctionApply(self._pointer[0], q, invecs, outvecs)
75        self._ceed._check_error(err_code)
76
77        # Clean-up
78        ffi.release(invecs)
79        ffi.release(outvecs)
80
81
82# ------------------------------------------------------------------------------
83class QFunction(_QFunctionBase):
84    """Ceed QFunction: point-wise operation at quadrature points for evaluating
85         volumetric terms."""
86
87    # Constructor
88    def __init__(self, ceed, vlength, f, source):
89        # libCEED object
90        self._pointer = ffi.new("CeedQFunction *")
91
92        # Reference to Ceed
93        self._ceed = ceed
94
95        # Function pointer
96        fpointer = ffi.cast(
97            "CeedQFunctionUser", ctypes.cast(
98                f, ctypes.c_void_p).value)
99
100        # libCEED call
101        sourceAscii = ffi.new("char[]", source.encode('ascii'))
102        err_code = lib.CeedQFunctionCreateInterior(self._ceed._pointer[0], vlength,
103                                                   fpointer, sourceAscii, self._pointer)
104        self._ceed._check_error(err_code)
105
106    # Set context data
107    def set_context(self, ctx):
108        """Set global context for a QFunction.
109
110           Args:
111             ctx: Ceed User Context object holding context data"""
112
113        # libCEED call
114        err_code = lib.CeedQFunctionSetContext(
115            self._pointer[0],
116            ctx._pointer[0])
117        self._ceed._check_error(err_code)
118
119    # Add fields to CeedQFunction
120    def add_input(self, fieldname, size, emode):
121        """Add a QFunction input.
122
123           Args:
124             fieldname: name of QFunction field
125             size: size of QFunction field, (ncomp * dim) for CEED_EVAL_GRAD or
126                     (ncomp * 1) for CEED_EVAL_NONE and CEED_EVAL_INTERP
127             **emode: CEED_EVAL_NONE to use values directly,
128                      CEED_EVAL_INTERP to use interpolated values,
129                      CEED_EVAL_GRAD to use gradients."""
130
131        # libCEED call
132        fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii'))
133        err_code = lib.CeedQFunctionAddInput(
134            self._pointer[0], fieldnameAscii, size, emode)
135        self._ceed._check_error(err_code)
136
137    def add_output(self, fieldname, size, emode):
138        """Add a QFunction output.
139
140           Args:
141             fieldname: name of QFunction field
142             size: size of QFunction field, (ncomp * dim) for CEED_EVAL_GRAD or
143                     (ncomp * 1) for CEED_EVAL_NONE and CEED_EVAL_INTERP
144             **emode: CEED_EVAL_NONE to use values directly,
145                      CEED_EVAL_INTERP to use interpolated values,
146                      CEED_EVAL_GRAD to use gradients."""
147
148        # libCEED call
149        fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii'))
150        err_code = lib.CeedQFunctionAddOutput(
151            self._pointer[0], fieldnameAscii, size, emode)
152        self._ceed._check_error(err_code)
153
154# ------------------------------------------------------------------------------
155
156
157class QFunctionByName(_QFunctionBase):
158    """Ceed QFunction By Name: point-wise operation at quadrature points
159         from a given gallery, for evaluating volumetric terms."""
160
161    # Constructor
162    def __init__(self, ceed, name):
163        # libCEED object
164        self._pointer = ffi.new("CeedQFunction *")
165
166        # Reference to Ceed
167        self._ceed = ceed
168
169        # libCEED call
170        nameAscii = ffi.new("char[]", name.encode('ascii'))
171        err_code = lib.CeedQFunctionCreateInteriorByName(self._ceed._pointer[0],
172                                                         nameAscii, self._pointer)
173        self._ceed._check_error(err_code)
174
175# ------------------------------------------------------------------------------
176
177
178class IdentityQFunction(_QFunctionBase):
179    """Ceed Identity QFunction: identity qfunction operation."""
180
181    # Constructor
182    def __init__(self, ceed, size, inmode, outmode):
183        # libCEED object
184        self._pointer = ffi.new("CeedQFunction *")
185
186        # Reference to Ceed
187        self._ceed = ceed
188
189        # libCEED call
190        err_code = lib.CeedQFunctionCreateIdentity(self._ceed._pointer[0], size,
191                                                   inmode, outmode, self._pointer)
192
193# ------------------------------------------------------------------------------
194