xref: /libCEED/python/ceed_qfunction.py (revision d9995aec8949465977409d138cd94b7dd885e51e)
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# ------------------------------------------------------------------------------
23class _QFunctionBase(ABC):
24  """Ceed QFunction: point-wise operation at quadrature points for evaluating
25       volumetric terms."""
26
27  # Attributes
28  _ceed = ffi.NULL
29  _pointer = ffi.NULL
30
31  # Destructor
32  def __del__(self):
33    # libCEED call
34    lib.CeedQFunctionDestroy(self._pointer)
35
36  # Representation
37  def __repr__(self):
38    return "<CeedQFunction instance at " + hex(id(self)) + ">"
39
40  # String conversion for print() to stdout
41  def __str__(self):
42    """View a QFunction via print()."""
43
44    # libCEED call
45    with tempfile.NamedTemporaryFile() as key_file:
46      with open(key_file.name, 'r+') as stream_file:
47        stream = ffi.cast("FILE *", stream_file)
48
49        lib.CeedQFunctionView(self._pointer[0], stream)
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    lib.CeedQFunctionApply(self._pointer[0], q, invecs, outvecs)
75
76    # Clean-up
77    ffi.release(invecs)
78    ffi.release(outvecs)
79
80
81# ------------------------------------------------------------------------------
82class QFunction(_QFunctionBase):
83  """Ceed QFunction: point-wise operation at quadrature points for evaluating
84       volumetric terms."""
85
86  # Constructor
87  def __init__(self, ceed, vlength, f, source):
88    # libCEED object
89    self._pointer = ffi.new("CeedQFunction *")
90
91    # Reference to Ceed
92    self._ceed = ceed
93
94    # Function pointer
95    fpointer = ffi.cast("CeedQFunctionUser", ctypes.cast(f, ctypes.c_void_p).value)
96
97    # libCEED call
98    sourceAscii = ffi.new("char[]", source.encode('ascii'))
99    lib.CeedQFunctionCreateInterior(self._ceed._pointer[0], vlength, fpointer,
100                                    sourceAscii, self._pointer)
101
102  # Set context data
103  def set_context(self, ctx):
104    """Set global context for a QFunction.
105
106       Args:
107         *ctx: Numpy array holding context data to set"""
108
109    # Setup the numpy array for the libCEED call
110    ctx_pointer = ffi.new("CeedScalar *")
111    ctx_pointer = ffi.cast("void *", ctx.__array_interface__['data'][0])
112
113    # libCEED call
114    lib.CeedQFunctionSetContext(self._pointer[0], ctx_pointer, len(ctx))
115
116  # Add fields to CeedQFunction
117  def add_input(self, fieldname, size, emode):
118    """Add a QFunction input.
119
120       Args:
121         fieldname: name of QFunction field
122         size: size of QFunction field, (ncomp * dim) for CEED_EVAL_GRAD or
123                 (ncomp * 1) for CEED_EVAL_NONE and CEED_EVAL_INTERP
124         **emode: CEED_EVAL_NONE to use values directly,
125                  CEED_EVAL_INTERP to use interpolated values,
126                  CEED_EVAL_GRAD to use gradients."""
127
128    # libCEED call
129    fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii'))
130    lib.CeedQFunctionAddInput(self._pointer[0], fieldnameAscii, size, emode)
131
132  def add_output(self, fieldname, size, emode):
133    """Add a QFunction output.
134
135       Args:
136         fieldname: name of QFunction field
137         size: size of QFunction field, (ncomp * dim) for CEED_EVAL_GRAD or
138                 (ncomp * 1) for CEED_EVAL_NONE and CEED_EVAL_INTERP
139         **emode: CEED_EVAL_NONE to use values directly,
140                  CEED_EVAL_INTERP to use interpolated values,
141                  CEED_EVAL_GRAD to use gradients."""
142
143    # libCEED call
144    fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii'))
145    lib.CeedQFunctionAddOutput(self._pointer[0], fieldnameAscii, size, emode)
146
147# ------------------------------------------------------------------------------
148class QFunctionByName(_QFunctionBase):
149  """Ceed QFunction By Name: point-wise operation at quadrature points
150       from a given gallery, for evaluating volumetric terms."""
151
152  # Constructor
153  def __init__(self, ceed, name):
154    # libCEED object
155    self._pointer = ffi.new("CeedQFunction *")
156
157    # Reference to Ceed
158    self._ceed = ceed
159
160    # libCEED call
161    nameAscii = ffi.new("char[]", name.encode('ascii'))
162    lib.CeedQFunctionCreateInteriorByName(self._ceed._pointer[0], nameAscii,
163                                          self._pointer)
164
165# ------------------------------------------------------------------------------
166class IdentityQFunction(_QFunctionBase):
167  """Ceed Identity QFunction: identity qfunction operation."""
168
169  # Constructor
170  def __init__(self, ceed, size, inmode, outmode):
171    # libCEED object
172    self._pointer = ffi.new("CeedQFunction *")
173
174    # Reference to Ceed
175    self._ceed = ceed
176
177    # libCEED call
178    lib.CeedQFunctionCreateIdentity(self._ceed._pointer[0], size, inmode,
179                                    outmode, self._pointer)
180
181# ------------------------------------------------------------------------------
182