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