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