xref: /libCEED/julia/LibCEED.jl/src/QFunction.jl (revision 0b548709a018764ef6265c48e3aa362e22a5c217)
144554ea0SWill Paznerabstract type AbstractQFunction end
244554ea0SWill Pazner
344554ea0SWill Paznerstruct QFunctionNone <: AbstractQFunction end
444554ea0SWill PaznerBase.getindex(::QFunctionNone) = C.CEED_QFUNCTION_NONE[]
544554ea0SWill Pazner
644554ea0SWill Pazner"""
744554ea0SWill Pazner    QFunction
844554ea0SWill Pazner
944554ea0SWill PaznerA libCEED `CeedQFunction` object, typically created using the [`@interior_qf`](@ref) macro.
1044554ea0SWill Pazner
1144554ea0SWill PaznerA `QFunction` can also be created from the "Q-function gallery" using
1244554ea0SWill Pazner[`create_interior_qfunction`](@ref). The identity Q-function can be created using
1344554ea0SWill Pazner[`create_identity_qfunction`](@ref).
1444554ea0SWill Pazner"""
1544554ea0SWill Paznermutable struct QFunction <: AbstractQFunction
1644554ea0SWill Pazner    ref::RefValue{C.CeedQFunction}
1744554ea0SWill Pazner    user_qf::Union{Nothing,UserQFunction}
1844554ea0SWill Pazner    ctx::Union{Nothing,Context}
1944554ea0SWill Pazner    function QFunction(ref, user_qf)
2044554ea0SWill Pazner        obj = new(ref, user_qf, nothing)
2144554ea0SWill Pazner        finalizer(obj) do x
2244554ea0SWill Pazner            # ccall(:jl_safe_printf, Cvoid, (Cstring, Cstring), "Finalizing %s.\n", repr(x))
2344554ea0SWill Pazner            destroy(x)
2444554ea0SWill Pazner        end
2544554ea0SWill Pazner        return obj
2644554ea0SWill Pazner    end
2744554ea0SWill Paznerend
2844554ea0SWill PaznerQFunction(ref::Ref{C.CeedQFunction}) = QFunction(ref, nothing)
2944554ea0SWill Paznerdestroy(qf::QFunction) = C.CeedQFunctionDestroy(qf.ref) # COV_EXCL_LINE
3044554ea0SWill PaznerBase.getindex(qf::QFunction) = qf.ref[]
3144554ea0SWill PaznerBase.show(io::IO, ::MIME"text/plain", qf::QFunction) =
3244554ea0SWill Pazner    ceed_show(io, qf, C.CeedQFunctionView)
3344554ea0SWill Pazner
3444554ea0SWill Paznerfunction create_interior_qfunction(c::Ceed, f::UserQFunction; vlength=1)
3544554ea0SWill Pazner    ref = Ref{C.CeedQFunction}()
3644554ea0SWill Pazner    # Use empty string as source location to indicate to libCEED that there is
3744554ea0SWill Pazner    # no C source for this Q-function
3844554ea0SWill Pazner    C.CeedQFunctionCreateInterior(c[], vlength, f.fptr, "", ref)
3944554ea0SWill Pazner    # COV_EXCL_START
4044554ea0SWill Pazner    if !isnothing(f.cuf)
4144554ea0SWill Pazner        C.CeedQFunctionSetCUDAUserFunction(ref[], f.cuf)
4215c93590SWill Pazner    elseif iscuda(c) && !isdefined(@__MODULE__, :CUDA)
4397769a3dSJed Brown        error(
4497769a3dSJed Brown            string(
4544554ea0SWill Pazner                "In order to use user Q-functions with a CUDA backend, the CUDA.jl package ",
4644554ea0SWill Pazner                "must be loaded",
4797769a3dSJed Brown            ),
4897769a3dSJed Brown        )
4944554ea0SWill Pazner    end
5044554ea0SWill Pazner    # COV_EXCL_STOP
5144554ea0SWill Pazner    QFunction(ref, f)
5244554ea0SWill Paznerend
5344554ea0SWill Pazner
5444554ea0SWill Pazner"""
5544554ea0SWill Pazner    create_interior_qfunction(ceed::Ceed, name::AbstractString)
5644554ea0SWill Pazner
5744554ea0SWill PaznerCreate a [`QFunction`](@ref) from the Q-function gallery, using the provided name.
5844554ea0SWill Pazner
5944554ea0SWill Pazner# Examples
6044554ea0SWill Pazner
6144554ea0SWill Pazner- Build and apply the 3D mass operator
6244554ea0SWill Pazner```
6344554ea0SWill Paznerbuild_mass_qf = create_interior_qfunction(c, "Mass3DBuild")
6444554ea0SWill Paznerapply_mass_qf = create_interior_qfunction(c, "MassApply")
6544554ea0SWill Pazner```
6644554ea0SWill Pazner- Build and apply the 3D Poisson operator
6744554ea0SWill Pazner```
6844554ea0SWill Paznerbuild_poi_qf = create_interior_qfunction(c, "Poisson3DBuild")
6944554ea0SWill Paznerapply_poi_qf = create_interior_qfunction(c, "Poisson3DApply")
7044554ea0SWill Pazner```
7144554ea0SWill Pazner"""
7244554ea0SWill Paznerfunction create_interior_qfunction(c::Ceed, name::AbstractString)
7344554ea0SWill Pazner    ref = Ref{C.CeedQFunction}()
7444554ea0SWill Pazner    C.CeedQFunctionCreateInteriorByName(c.ref[], name, ref)
7544554ea0SWill Pazner    QFunction(ref)
7644554ea0SWill Paznerend
7744554ea0SWill Pazner
7844554ea0SWill Pazner"""
7944554ea0SWill Pazner    create_identity_qfunction(c::Ceed, size, inmode::EvalMode, outmode::EvalMode)
8044554ea0SWill Pazner
8144554ea0SWill PaznerCreate an identity [`QFunction`](@ref). Inputs are written into outputs in the order given.
8244554ea0SWill PaznerThis is useful for [`Operators`](@ref Operator) that can be represented with only the action
8344554ea0SWill Paznerof a [`ElemRestriction`](@ref) and [`Basis`](@ref), such as restriction and prolongation
8444554ea0SWill Pazneroperators for p-multigrid. Backends may optimize `CeedOperators` with this Q-function to
8544554ea0SWill Pazneravoid the copy of input data to output fields by using the same memory location for both.
8644554ea0SWill Pazner"""
8744554ea0SWill Paznerfunction create_identity_qfunction(c::Ceed, size, inmode::EvalMode, outmode::EvalMode)
8844554ea0SWill Pazner    ref = Ref{C.CeedQFunction}()
8944554ea0SWill Pazner    C.CeedQFunctionCreateIdentity(c[], size, inmode, outmode, ref)
9044554ea0SWill Pazner    QFunction(ref)
9144554ea0SWill Paznerend
9244554ea0SWill Pazner
9344554ea0SWill Paznerfunction add_input!(qf::AbstractQFunction, name::AbstractString, size, emode)
9444554ea0SWill Pazner    C.CeedQFunctionAddInput(qf[], name, size, emode)
9544554ea0SWill Paznerend
9644554ea0SWill Pazner
9744554ea0SWill Paznerfunction add_output!(qf::AbstractQFunction, name::AbstractString, size, emode)
9844554ea0SWill Pazner    C.CeedQFunctionAddOutput(qf[], name, size, emode)
9944554ea0SWill Paznerend
10044554ea0SWill Pazner
10144554ea0SWill Pazner"""
10244554ea0SWill Pazner    set_context!(qf::QFunction, ctx::Context)
10344554ea0SWill Pazner
10444554ea0SWill PaznerAssociate a [`Context`](@ref) object `ctx` with the given Q-function `qf`.
10544554ea0SWill Pazner"""
10644554ea0SWill Paznerfunction set_context!(qf::QFunction, ctx)
10744554ea0SWill Pazner    # Preserve the context data from the GC by storing a reference
10844554ea0SWill Pazner    qf.ctx = ctx
10944554ea0SWill Pazner    C.CeedQFunctionSetContext(qf[], ctx[])
11044554ea0SWill Paznerend
11144554ea0SWill Pazner
11244554ea0SWill Paznerfunction get_field_sizes(qf::AbstractQFunction)
11344554ea0SWill Pazner    ninputs = Ref{CeedInt}()
11444554ea0SWill Pazner    noutputs = Ref{CeedInt}()
11544554ea0SWill Pazner    inputs = Ref{Ptr{C.CeedQFunctionField}}()
11644554ea0SWill Pazner    outputs = Ref{Ptr{C.CeedQFunctionField}}()
117*7e7773b5SJeremy L Thompson    C.CeedQFunctionGetFields(qf[], ninputs, inputs, noutputs, outputs)
11844554ea0SWill Pazner
11944554ea0SWill Pazner    input_sizes = zeros(CeedInt, ninputs[])
12044554ea0SWill Pazner    output_sizes = zeros(CeedInt, noutputs[])
12144554ea0SWill Pazner
12244554ea0SWill Pazner    for i = 1:ninputs[]
12344554ea0SWill Pazner        field = unsafe_load(inputs[], i)
12444554ea0SWill Pazner        C.CeedQFunctionFieldGetSize(field, pointer(input_sizes, i))
12544554ea0SWill Pazner    end
12644554ea0SWill Pazner
12744554ea0SWill Pazner    for i = 1:noutputs[]
12844554ea0SWill Pazner        field = unsafe_load(outputs[], i)
12944554ea0SWill Pazner        C.CeedQFunctionFieldGetSize(field, pointer(output_sizes, i))
13044554ea0SWill Pazner    end
13144554ea0SWill Pazner
13244554ea0SWill Pazner    input_sizes, output_sizes
13344554ea0SWill Paznerend
13444554ea0SWill Pazner
13544554ea0SWill Pazner"""
13644554ea0SWill Pazner    apply!(qf::QFunction, Q, vin, vout)
13744554ea0SWill Pazner
13844554ea0SWill PaznerApply the action of a [`QFunction`](@ref) to an array of input vectors, and store the result
13944554ea0SWill Paznerin an array of output vectors.
14044554ea0SWill Pazner"""
14144554ea0SWill Paznerfunction apply!(qf::QFunction, Q, vin, vout)
14244554ea0SWill Pazner    vins = map(x -> x[], vin)
14344554ea0SWill Pazner    vouts = map(x -> x[], vout)
14444554ea0SWill Pazner    GC.@preserve vin vout begin
14544554ea0SWill Pazner        C.CeedQFunctionApply(qf[], Q, pointer(vins), pointer(vouts))
14644554ea0SWill Pazner    end
14744554ea0SWill Paznerend
148