xref: /libCEED/python/ceed_qfunction.py (revision f8bc67e5d26b876457ae758232551aa5c7d39cef)
1*f8bc67e5Sjeremylt# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2*f8bc67e5Sjeremylt# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3*f8bc67e5Sjeremylt# reserved. See files LICENSE and NOTICE for details.
4*f8bc67e5Sjeremylt#
5*f8bc67e5Sjeremylt# This file is part of CEED, a collection of benchmarks, miniapps, software
6*f8bc67e5Sjeremylt# libraries and APIs for efficient high-order finite element and spectral
7*f8bc67e5Sjeremylt# element discretizations for exascale applications. For more information and
8*f8bc67e5Sjeremylt# source code availability see http://github.com/ceed.
9*f8bc67e5Sjeremylt#
10*f8bc67e5Sjeremylt# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11*f8bc67e5Sjeremylt# a collaborative effort of two U.S. Department of Energy organizations (Office
12*f8bc67e5Sjeremylt# of Science and the National Nuclear Security Administration) responsible for
13*f8bc67e5Sjeremylt# the planning and preparation of a capable exascale ecosystem, including
14*f8bc67e5Sjeremylt# software, applications, hardware, advanced system engineering and early
15*f8bc67e5Sjeremylt# testbed platforms, in support of the nation's exascale computing imperative.
16*f8bc67e5Sjeremylt
17*f8bc67e5Sjeremyltfrom _ceed_cffi import ffi, lib
18*f8bc67e5Sjeremyltimport ctypes
19*f8bc67e5Sjeremyltimport tempfile
20*f8bc67e5Sjeremyltfrom abc import ABC
21*f8bc67e5Sjeremylt
22*f8bc67e5Sjeremylt# ------------------------------------------------------------------------------
23*f8bc67e5Sjeremyltclass _QFunctionBase(ABC):
24*f8bc67e5Sjeremylt  """Ceed QFunction: point-wise operation at quadrature points for evaluating
25*f8bc67e5Sjeremylt       volumetric terms."""
26*f8bc67e5Sjeremylt
27*f8bc67e5Sjeremylt  # Attributes
28*f8bc67e5Sjeremylt  _ceed = ffi.NULL
29*f8bc67e5Sjeremylt  _pointer = ffi.NULL
30*f8bc67e5Sjeremylt
31*f8bc67e5Sjeremylt  # Destructor
32*f8bc67e5Sjeremylt  def __del__(self):
33*f8bc67e5Sjeremylt    # libCEED call
34*f8bc67e5Sjeremylt    lib.CeedQFunctionDestroy(self._pointer)
35*f8bc67e5Sjeremylt
36*f8bc67e5Sjeremylt  # Representation
37*f8bc67e5Sjeremylt  def __repr__(self):
38*f8bc67e5Sjeremylt    return "<CeedQFunction instance at " + hex(id(self)) + ">"
39*f8bc67e5Sjeremylt
40*f8bc67e5Sjeremylt  # String conversion for print() to stdout
41*f8bc67e5Sjeremylt  def __str__(self):
42*f8bc67e5Sjeremylt    """View a QFunction via print()."""
43*f8bc67e5Sjeremylt
44*f8bc67e5Sjeremylt    # libCEED call
45*f8bc67e5Sjeremylt    with tempfile.NamedTemporaryFile() as key_file:
46*f8bc67e5Sjeremylt      with open(key_file.name, 'r+') as stream_file:
47*f8bc67e5Sjeremylt        stream = ffi.cast("FILE *", stream_file)
48*f8bc67e5Sjeremylt
49*f8bc67e5Sjeremylt        lib.CeedQFunctionView(self._pointer[0], stream)
50*f8bc67e5Sjeremylt
51*f8bc67e5Sjeremylt        stream_file.seek(0)
52*f8bc67e5Sjeremylt        out_string = stream_file.read()
53*f8bc67e5Sjeremylt
54*f8bc67e5Sjeremylt    return out_string
55*f8bc67e5Sjeremylt
56*f8bc67e5Sjeremylt  # Apply CeedQFunction
57*f8bc67e5Sjeremylt  def apply(self, q, inputs, outputs):
58*f8bc67e5Sjeremylt    """Apply the action of a QFunction.
59*f8bc67e5Sjeremylt
60*f8bc67e5Sjeremylt       Args:
61*f8bc67e5Sjeremylt         q: number of quadrature points
62*f8bc67e5Sjeremylt         *inputs: array of input data vectors
63*f8bc67e5Sjeremylt         *outputs: array of output data vectors"""
64*f8bc67e5Sjeremylt
65*f8bc67e5Sjeremylt    # Array of vectors
66*f8bc67e5Sjeremylt    invecs = ffi.new("CeedVector[16]")
67*f8bc67e5Sjeremylt    for i in range(min(16, len(inputs))):
68*f8bc67e5Sjeremylt      invecs[i] = inputs[i]._pointer[0]
69*f8bc67e5Sjeremylt    outvecs = ffi.new("CeedVector[16]")
70*f8bc67e5Sjeremylt    for i in range(min(16, len(outputs))):
71*f8bc67e5Sjeremylt      outvecs[i] = outputs[i]._pointer[0]
72*f8bc67e5Sjeremylt
73*f8bc67e5Sjeremylt    # libCEED call
74*f8bc67e5Sjeremylt    lib.CeedQFunctionApply(self._pointer[0], q, invecs, outvecs)
75*f8bc67e5Sjeremylt
76*f8bc67e5Sjeremylt    # Clean-up
77*f8bc67e5Sjeremylt    ffi.release(invecs)
78*f8bc67e5Sjeremylt    ffi.release(outvecs)
79*f8bc67e5Sjeremylt
80*f8bc67e5Sjeremylt
81*f8bc67e5Sjeremylt# ------------------------------------------------------------------------------
82*f8bc67e5Sjeremyltclass QFunction(_QFunctionBase):
83*f8bc67e5Sjeremylt  """Ceed QFunction: point-wise operation at quadrature points for evaluating
84*f8bc67e5Sjeremylt       volumetric terms."""
85*f8bc67e5Sjeremylt
86*f8bc67e5Sjeremylt  # Constructor
87*f8bc67e5Sjeremylt  def __init__(self, ceed, vlength, f, source):
88*f8bc67e5Sjeremylt    # libCEED object
89*f8bc67e5Sjeremylt    self._pointer = ffi.new("CeedQFunction *")
90*f8bc67e5Sjeremylt
91*f8bc67e5Sjeremylt    # Reference to Ceed
92*f8bc67e5Sjeremylt    self._ceed = ceed
93*f8bc67e5Sjeremylt
94*f8bc67e5Sjeremylt    # Function pointer
95*f8bc67e5Sjeremylt    fpointer = ffi.cast("CeedQFunctionUser", ctypes.cast(f, ctypes.c_void_p).value)
96*f8bc67e5Sjeremylt
97*f8bc67e5Sjeremylt    # libCEED call
98*f8bc67e5Sjeremylt    sourceAscii = ffi.new("char[]", source.encode('ascii'))
99*f8bc67e5Sjeremylt    lib.CeedQFunctionCreateInterior(self._ceed._pointer[0], vlength, fpointer,
100*f8bc67e5Sjeremylt                                    sourceAscii, self._pointer)
101*f8bc67e5Sjeremylt
102*f8bc67e5Sjeremylt  # Set context data
103*f8bc67e5Sjeremylt  def set_context(self, ctx):
104*f8bc67e5Sjeremylt    """Set global context for a QFunction.
105*f8bc67e5Sjeremylt
106*f8bc67e5Sjeremylt       Args:
107*f8bc67e5Sjeremylt         *ctx: Numpy array holding context data to set"""
108*f8bc67e5Sjeremylt
109*f8bc67e5Sjeremylt    # Setup the numpy array for the libCEED call
110*f8bc67e5Sjeremylt    ctx_pointer = ffi.new("CeedScalar *")
111*f8bc67e5Sjeremylt    ctx_pointer = ffi.cast("void *", ctx.__array_interface__['data'][0])
112*f8bc67e5Sjeremylt
113*f8bc67e5Sjeremylt    # libCEED call
114*f8bc67e5Sjeremylt    lib.CeedQFunctionSetContext(self._pointer[0], ctx_pointer, len(ctx))
115*f8bc67e5Sjeremylt
116*f8bc67e5Sjeremylt  # Add fields to CeedQFunction
117*f8bc67e5Sjeremylt  def add_input(self, fieldname, size, emode):
118*f8bc67e5Sjeremylt    """Add a QFunction input.
119*f8bc67e5Sjeremylt
120*f8bc67e5Sjeremylt       Args:
121*f8bc67e5Sjeremylt         fieldname: name of QFunction field
122*f8bc67e5Sjeremylt         size: size of QFunction field, (ncomp * dim) for CEED_EVAL_GRAD or
123*f8bc67e5Sjeremylt                 (ncomp * 1) for CEED_EVAL_NONE and CEED_EVAL_INTERP
124*f8bc67e5Sjeremylt         **emode: CEED_EVAL_NONE to use values directly,
125*f8bc67e5Sjeremylt                  CEED_EVAL_INTERP to use interpolated values,
126*f8bc67e5Sjeremylt                  CEED_EVAL_GRAD to use gradients."""
127*f8bc67e5Sjeremylt
128*f8bc67e5Sjeremylt    # libCEED call
129*f8bc67e5Sjeremylt    fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii'))
130*f8bc67e5Sjeremylt    lib.CeedQFunctionAddInput(self._pointer[0], fieldnameAscii, size, emode)
131*f8bc67e5Sjeremylt
132*f8bc67e5Sjeremylt  def add_output(self, fieldname, size, emode):
133*f8bc67e5Sjeremylt    """Add a QFunction output.
134*f8bc67e5Sjeremylt
135*f8bc67e5Sjeremylt       Args:
136*f8bc67e5Sjeremylt         fieldname: name of QFunction field
137*f8bc67e5Sjeremylt         size: size of QFunction field, (ncomp * dim) for CEED_EVAL_GRAD or
138*f8bc67e5Sjeremylt                 (ncomp * 1) for CEED_EVAL_NONE and CEED_EVAL_INTERP
139*f8bc67e5Sjeremylt         **emode: CEED_EVAL_NONE to use values directly,
140*f8bc67e5Sjeremylt                  CEED_EVAL_INTERP to use interpolated values,
141*f8bc67e5Sjeremylt                  CEED_EVAL_GRAD to use gradients."""
142*f8bc67e5Sjeremylt
143*f8bc67e5Sjeremylt    # libCEED call
144*f8bc67e5Sjeremylt    fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii'))
145*f8bc67e5Sjeremylt    lib.CeedQFunctionAddOutput(self._pointer[0], fieldnameAscii, size, emode)
146*f8bc67e5Sjeremylt
147*f8bc67e5Sjeremylt# ------------------------------------------------------------------------------
148*f8bc67e5Sjeremyltclass QFunctionByName(_QFunctionBase):
149*f8bc67e5Sjeremylt  """Ceed QFunction By Name: point-wise operation at quadrature points
150*f8bc67e5Sjeremylt       from a given gallery, for evaluating volumetric terms."""
151*f8bc67e5Sjeremylt
152*f8bc67e5Sjeremylt  # Constructor
153*f8bc67e5Sjeremylt  def __init__(self, ceed, name):
154*f8bc67e5Sjeremylt    # libCEED object
155*f8bc67e5Sjeremylt    self._pointer = ffi.new("CeedQFunction *")
156*f8bc67e5Sjeremylt
157*f8bc67e5Sjeremylt    # Reference to Ceed
158*f8bc67e5Sjeremylt    self._ceed = ceed
159*f8bc67e5Sjeremylt
160*f8bc67e5Sjeremylt    # libCEED call
161*f8bc67e5Sjeremylt    nameAscii = ffi.new("char[]", name.encode('ascii'))
162*f8bc67e5Sjeremylt    lib.CeedQFunctionCreateInteriorByName(self._ceed._pointer[0], nameAscii,
163*f8bc67e5Sjeremylt                                          self._pointer)
164*f8bc67e5Sjeremylt
165*f8bc67e5Sjeremylt# ------------------------------------------------------------------------------
166*f8bc67e5Sjeremyltclass IdentityQFunction(_QFunctionBase):
167*f8bc67e5Sjeremylt  """Ceed Identity QFunction: identity qfunction operation."""
168*f8bc67e5Sjeremylt
169*f8bc67e5Sjeremylt  # Constructor
170*f8bc67e5Sjeremylt  def __init__(self, ceed, size, inmode, outmode):
171*f8bc67e5Sjeremylt    # libCEED object
172*f8bc67e5Sjeremylt    self._pointer = ffi.new("CeedQFunction *")
173*f8bc67e5Sjeremylt
174*f8bc67e5Sjeremylt    # Reference to Ceed
175*f8bc67e5Sjeremylt    self._ceed = ceed
176*f8bc67e5Sjeremylt
177*f8bc67e5Sjeremylt    # libCEED call
178*f8bc67e5Sjeremylt    lib.CeedQFunctionCreateIdentity(self._ceed._pointer[0], size, inmode,
179*f8bc67e5Sjeremylt                                    outmode, self._pointer)
180*f8bc67e5Sjeremylt
181*f8bc67e5Sjeremylt# ------------------------------------------------------------------------------
182