1*44554ea0SWill Paznerimport LinearAlgebra: norm 2*44554ea0SWill Pazner 3*44554ea0SWill Paznerabstract type AbstractCeedVector end 4*44554ea0SWill Pazner 5*44554ea0SWill Paznerstruct CeedVectorActive <: AbstractCeedVector end 6*44554ea0SWill PaznerBase.getindex(::CeedVectorActive) = C.CEED_VECTOR_ACTIVE[] 7*44554ea0SWill Pazner 8*44554ea0SWill Paznerstruct CeedVectorNone <: AbstractCeedVector end 9*44554ea0SWill PaznerBase.getindex(::CeedVectorNone) = C.CEED_VECTOR_NONE[] 10*44554ea0SWill Pazner 11*44554ea0SWill Paznermutable struct CeedVector <: AbstractCeedVector 12*44554ea0SWill Pazner ref::RefValue{C.CeedVector} 13*44554ea0SWill Pazner arr::Union{Nothing,AbstractArray} 14*44554ea0SWill Pazner CeedVector(ref::Ref{C.CeedVector}) = new(ref, nothing) 15*44554ea0SWill Paznerend 16*44554ea0SWill Pazner 17*44554ea0SWill Pazner""" 18*44554ea0SWill Pazner CeedVector(c::Ceed, len::Integer) 19*44554ea0SWill Pazner 20*44554ea0SWill PaznerCreates a `CeedVector` of given length. 21*44554ea0SWill Pazner""" 22*44554ea0SWill Paznerfunction CeedVector(c::Ceed, len::Integer) 23*44554ea0SWill Pazner ref = Ref{C.CeedVector}() 24*44554ea0SWill Pazner C.CeedVectorCreate(c[], len, ref) 25*44554ea0SWill Pazner obj = CeedVector(ref) 26*44554ea0SWill Pazner finalizer(obj) do x 27*44554ea0SWill Pazner # ccall(:jl_safe_printf, Cvoid, (Cstring, Cstring), "Finalizing %s.\n", repr(x)) 28*44554ea0SWill Pazner destroy(x) 29*44554ea0SWill Pazner end 30*44554ea0SWill Pazner return obj 31*44554ea0SWill Paznerend 32*44554ea0SWill Paznerdestroy(v::CeedVector) = C.CeedVectorDestroy(v.ref) # COV_EXCL_LINE 33*44554ea0SWill PaznerBase.getindex(v::CeedVector) = v.ref[] 34*44554ea0SWill Pazner 35*44554ea0SWill PaznerBase.summary(io::IO, v::CeedVector) = print(io, length(v), "-element CeedVector") 36*44554ea0SWill Paznerfunction Base.show(io::IO, ::MIME"text/plain", v::CeedVector) 37*44554ea0SWill Pazner summary(io, v) 38*44554ea0SWill Pazner println(io, ":") 39*44554ea0SWill Pazner witharray_read(v, MEM_HOST) do arr 40*44554ea0SWill Pazner Base.print_array(io, arr) 41*44554ea0SWill Pazner end 42*44554ea0SWill Paznerend 43*44554ea0SWill PaznerBase.show(io::IO, v::CeedVector) = witharray_read(a -> show(io, a), v, MEM_HOST) 44*44554ea0SWill Pazner 45*44554ea0SWill Paznerfunction Base.length(::Type{T}, v::CeedVector) where {T} 46*44554ea0SWill Pazner len = Ref{C.CeedInt}() 47*44554ea0SWill Pazner C.CeedVectorGetLength(v[], len) 48*44554ea0SWill Pazner return T(len[]) 49*44554ea0SWill Paznerend 50*44554ea0SWill Pazner 51*44554ea0SWill PaznerBase.ndims(::CeedVector) = 1 52*44554ea0SWill PaznerBase.ndims(::Type{CeedVector}) = 1 53*44554ea0SWill PaznerBase.axes(v::CeedVector) = (Base.OneTo(length(v)),) 54*44554ea0SWill PaznerBase.size(v::CeedVector) = (length(Int, v),) 55*44554ea0SWill PaznerBase.length(v::CeedVector) = length(Int, v) 56*44554ea0SWill Pazner 57*44554ea0SWill Pazner""" 58*44554ea0SWill Pazner setvalue!(v::CeedVector, val::CeedScalar) 59*44554ea0SWill Pazner 60*44554ea0SWill PaznerSet the [`CeedVector`](@ref) to a constant value. 61*44554ea0SWill Pazner""" 62*44554ea0SWill Paznersetvalue!(v::CeedVector, val::CeedScalar) = C.CeedVectorSetValue(v[], val) 63*44554ea0SWill Pazner""" 64*44554ea0SWill Pazner setindex!(v::CeedVector, val::CeedScalar) 65*44554ea0SWill Pazner v[] = val 66*44554ea0SWill Pazner 67*44554ea0SWill PaznerSet the [`CeedVector`](@ref) to a constant value, synonymous to [`setvalue!`](@ref). 68*44554ea0SWill Pazner""" 69*44554ea0SWill PaznerBase.setindex!(v::CeedVector, val::CeedScalar) = setvalue!(v, val) 70*44554ea0SWill Pazner 71*44554ea0SWill Pazner""" 72*44554ea0SWill Pazner norm(v::CeedVector, ntype::NormType) 73*44554ea0SWill Pazner 74*44554ea0SWill PaznerReturn the norm of the given [`CeedVector`](@ref). 75*44554ea0SWill Pazner 76*44554ea0SWill PaznerThe norm type can either be specified as one of `NORM_1`, `NORM_2`, `NORM_MAX`. 77*44554ea0SWill Pazner""" 78*44554ea0SWill Paznerfunction norm(v::CeedVector, ntype::NormType) 79*44554ea0SWill Pazner nrm = Ref{CeedScalar}() 80*44554ea0SWill Pazner C.CeedVectorNorm(v[], ntype, nrm) 81*44554ea0SWill Pazner nrm[] 82*44554ea0SWill Paznerend 83*44554ea0SWill Pazner 84*44554ea0SWill Pazner""" 85*44554ea0SWill Pazner norm(v::CeedVector, p::Real) 86*44554ea0SWill Pazner 87*44554ea0SWill PaznerReturn the norm of the given [`CeedVector`](@ref), see [`norm(::CeedVector, 88*44554ea0SWill Pazner::NormType)`](@ref). 89*44554ea0SWill Pazner 90*44554ea0SWill Pazner`p` can have value 1, 2, or Inf, corresponding to `NORM_1`, `NORM_2`, and `NORM_MAX`, 91*44554ea0SWill Paznerrespectively. 92*44554ea0SWill Pazner""" 93*44554ea0SWill Paznerfunction norm(v::CeedVector, p::Real) 94*44554ea0SWill Pazner if p == 1 95*44554ea0SWill Pazner ntype = NORM_1 96*44554ea0SWill Pazner elseif p == 2 97*44554ea0SWill Pazner ntype = NORM_2 98*44554ea0SWill Pazner elseif isinf(p) 99*44554ea0SWill Pazner ntype = NORM_MAX 100*44554ea0SWill Pazner else 101*44554ea0SWill Pazner error("norm(v::CeedVector, p): p must be 1, 2, or Inf") 102*44554ea0SWill Pazner end 103*44554ea0SWill Pazner norm(v, ntype) 104*44554ea0SWill Paznerend 105*44554ea0SWill Pazner 106*44554ea0SWill Pazner""" 107*44554ea0SWill Pazner reciprocal!(v::CeedVector) 108*44554ea0SWill Pazner 109*44554ea0SWill PaznerSet `v` to be equal to its elementwise reciprocal. 110*44554ea0SWill Pazner""" 111*44554ea0SWill Paznerreciprocal!(v::CeedVector) = C.CeedVectorReciprocal(v[]) 112*44554ea0SWill Pazner 113*44554ea0SWill Pazner""" 114*44554ea0SWill Pazner setarray!(v::CeedVector, mtype::MemType, cmode::CopyMode, arr) 115*44554ea0SWill Pazner 116*44554ea0SWill PaznerSet the array used by a [`CeedVector`](@ref), freeing any previously allocated array if 117*44554ea0SWill Paznerapplicable. The backend may copy values to a different [`MemType`](@ref). See also 118*44554ea0SWill Pazner[`syncarray!`](@ref) and [`takearray!`](@ref). 119*44554ea0SWill Pazner 120*44554ea0SWill Pazner!!! warning "Avoid OWN_POINTER CopyMode" 121*44554ea0SWill Pazner The [`CopyMode`](@ref) `OWN_POINTER` is not suitable for use with arrays that are 122*44554ea0SWill Pazner allocated by Julia, since those cannot be properly freed from libCEED. 123*44554ea0SWill Pazner""" 124*44554ea0SWill Paznerfunction setarray!(v::CeedVector, mtype::MemType, cmode::CopyMode, arr) 125*44554ea0SWill Pazner C.CeedVectorSetArray(v[], mtype, cmode, arr) 126*44554ea0SWill Pazner if cmode == USE_POINTER 127*44554ea0SWill Pazner v.arr = arr 128*44554ea0SWill Pazner end 129*44554ea0SWill Paznerend 130*44554ea0SWill Pazner 131*44554ea0SWill Pazner""" 132*44554ea0SWill Pazner syncarray!(v::CeedVector, mtype::MemType) 133*44554ea0SWill Pazner 134*44554ea0SWill PaznerSync the [`CeedVector`](@ref) to a specified [`MemType`](@ref). This function is used to 135*44554ea0SWill Paznerforce synchronization of arrays set with [`setarray!`](@ref). If the requested memtype is 136*44554ea0SWill Pazneralready synchronized, this function results in a no-op. 137*44554ea0SWill Pazner""" 138*44554ea0SWill Paznersyncarray!(v::CeedVector, mtype::MemType) = C.CeedVectorSyncArray(v[], mtype) 139*44554ea0SWill Pazner 140*44554ea0SWill Pazner""" 141*44554ea0SWill Pazner takearray!(v::CeedVector, mtype::MemType) 142*44554ea0SWill Pazner 143*44554ea0SWill PaznerTake ownership of the [`CeedVector`](@ref) array and remove the array from the 144*44554ea0SWill Pazner[`CeedVector`](@ref). The caller is responsible for managing and freeing the array. The 145*44554ea0SWill Paznerarray is returns as a `Ptr{CeedScalar}`. 146*44554ea0SWill Pazner""" 147*44554ea0SWill Paznerfunction takearray!(v::CeedVector, mtype::MemType) 148*44554ea0SWill Pazner ptr = Ref{Ptr{CeedScalar}}() 149*44554ea0SWill Pazner C.CeedVectorTakeArray(v[], mtype, ptr) 150*44554ea0SWill Pazner v.arr = nothing 151*44554ea0SWill Pazner ptr[] 152*44554ea0SWill Paznerend 153*44554ea0SWill Pazner 154*44554ea0SWill Pazner# Helper function to parse arguments of @witharray and @witharray_read 155*44554ea0SWill Paznerfunction witharray_parse(assignment, args) 156*44554ea0SWill Pazner if !Meta.isexpr(assignment, :(=)) 157*44554ea0SWill Pazner error("@witharray must have first argument of the form v_arr=v") # COV_EXCL_LINE 158*44554ea0SWill Pazner end 159*44554ea0SWill Pazner arr = assignment.args[1] 160*44554ea0SWill Pazner v = assignment.args[2] 161*44554ea0SWill Pazner mtype = MEM_HOST 162*44554ea0SWill Pazner sz = :((length($(esc(v))),)) 163*44554ea0SWill Pazner body = args[end] 164*44554ea0SWill Pazner for i = 1:length(args)-1 165*44554ea0SWill Pazner a = args[i] 166*44554ea0SWill Pazner if !Meta.isexpr(a, :(=)) 167*44554ea0SWill Pazner error("Incorrect call to @witharray or @witharray_read") # COV_EXCL_LINE 168*44554ea0SWill Pazner end 169*44554ea0SWill Pazner if a.args[1] == :mtype 170*44554ea0SWill Pazner mtype = a.args[2] 171*44554ea0SWill Pazner elseif a.args[1] == :size 172*44554ea0SWill Pazner sz = esc(a.args[2]) 173*44554ea0SWill Pazner end 174*44554ea0SWill Pazner end 175*44554ea0SWill Pazner arr, v, sz, mtype, body 176*44554ea0SWill Paznerend 177*44554ea0SWill Pazner 178*44554ea0SWill Pazner""" 179*44554ea0SWill Pazner @witharray(v_arr=v, [size=(dims...)], [mtype=MEM_HOST], body) 180*44554ea0SWill Pazner 181*44554ea0SWill PaznerExecutes `body`, having extracted the contents of the [`CeedVector`](@ref) `v` as an array 182*44554ea0SWill Paznerwith name `v_arr`. If the [`memory type`](@ref MemType) `mtype` is not provided, `MEM_HOST` 183*44554ea0SWill Paznerwill be used. If the size is not specified, a flat vector will be assumed. 184*44554ea0SWill Pazner 185*44554ea0SWill Pazner# Examples 186*44554ea0SWill PaznerNegate the contents of `CeedVector` `v`: 187*44554ea0SWill Pazner``` 188*44554ea0SWill Pazner@witharray v_arr=v v_arr *= -1.0 189*44554ea0SWill Pazner``` 190*44554ea0SWill Pazner""" 191*44554ea0SWill Paznermacro witharray(assignment, args...) 192*44554ea0SWill Pazner arr, v, sz, mtype, body = witharray_parse(assignment, args) 193*44554ea0SWill Pazner quote 194*44554ea0SWill Pazner arr_ref = Ref{Ptr{C.CeedScalar}}() 195*44554ea0SWill Pazner C.CeedVectorGetArray($(esc(v))[], $(esc(mtype)), arr_ref) 196*44554ea0SWill Pazner try 197*44554ea0SWill Pazner $(esc(arr)) = UnsafeArray(arr_ref[], Int.($sz)) 198*44554ea0SWill Pazner $(esc(body)) 199*44554ea0SWill Pazner finally 200*44554ea0SWill Pazner C.CeedVectorRestoreArray($(esc(v))[], arr_ref) 201*44554ea0SWill Pazner end 202*44554ea0SWill Pazner end 203*44554ea0SWill Paznerend 204*44554ea0SWill Pazner 205*44554ea0SWill Pazner""" 206*44554ea0SWill Pazner @witharray_read(v_arr=v, [size=(dims...)], [mtype=MEM_HOST], body) 207*44554ea0SWill Pazner 208*44554ea0SWill PaznerSame as [`@witharray`](@ref), but provides read-only access to the data. 209*44554ea0SWill Pazner""" 210*44554ea0SWill Paznermacro witharray_read(assignment, args...) 211*44554ea0SWill Pazner arr, v, sz, mtype, body = witharray_parse(assignment, args) 212*44554ea0SWill Pazner quote 213*44554ea0SWill Pazner arr_ref = Ref{Ptr{C.CeedScalar}}() 214*44554ea0SWill Pazner C.CeedVectorGetArrayRead($(esc(v))[], $(esc(mtype)), arr_ref) 215*44554ea0SWill Pazner try 216*44554ea0SWill Pazner $(esc(arr)) = UnsafeArray(arr_ref[], Int.($sz)) 217*44554ea0SWill Pazner $(esc(body)) 218*44554ea0SWill Pazner finally 219*44554ea0SWill Pazner C.CeedVectorRestoreArrayRead($(esc(v))[], arr_ref) 220*44554ea0SWill Pazner end 221*44554ea0SWill Pazner end 222*44554ea0SWill Paznerend 223*44554ea0SWill Pazner 224*44554ea0SWill Pazner""" 225*44554ea0SWill Pazner setindex!(v::CeedVector, v2::AbstractArray) 226*44554ea0SWill Pazner v[] = v2 227*44554ea0SWill Pazner 228*44554ea0SWill PaznerSets the values of [`CeedVector`](@ref) `v` equal to those of `v2` using broadcasting. 229*44554ea0SWill Pazner""" 230*44554ea0SWill PaznerBase.setindex!(v::CeedVector, v2::AbstractArray) = @witharray(a = v, a .= v2) 231*44554ea0SWill Pazner 232*44554ea0SWill Pazner""" 233*44554ea0SWill Pazner CeedVector(c::Ceed, v2::AbstractVector; mtype=MEM_HOST, cmode=COPY_VALUES) 234*44554ea0SWill Pazner 235*44554ea0SWill PaznerCreates a new [`CeedVector`](@ref) using the contents of the given vector `v2`. By default, 236*44554ea0SWill Paznerthe contents of `v2` will be copied to the new [`CeedVector`](@ref), but this behavior can 237*44554ea0SWill Paznerbe changed by specifying a different `cmode`. 238*44554ea0SWill Pazner""" 239*44554ea0SWill Paznerfunction CeedVector(c::Ceed, v2::AbstractVector; mtype=MEM_HOST, cmode=COPY_VALUES) 240*44554ea0SWill Pazner v = CeedVector(c, length(v2)) 241*44554ea0SWill Pazner setarray!(v, mtype, cmode, v2) 242*44554ea0SWill Pazner v 243*44554ea0SWill Paznerend 244*44554ea0SWill Pazner 245*44554ea0SWill Pazner""" 246*44554ea0SWill Pazner Vector(v::CeedVector) 247*44554ea0SWill Pazner 248*44554ea0SWill PaznerCreate a new `Vector` by copying the contents of `v`. 249*44554ea0SWill Pazner""" 250*44554ea0SWill Paznerfunction Base.Vector(v::CeedVector) 251*44554ea0SWill Pazner v2 = Vector{CeedScalar}(undef, length(v)) 252*44554ea0SWill Pazner @witharray_read(a = v, v2 .= a) 253*44554ea0SWill Paznerend 254*44554ea0SWill Pazner 255*44554ea0SWill Pazner""" 256*44554ea0SWill Pazner witharray(f, v::CeedVector, mtype=MEM_HOST) 257*44554ea0SWill Pazner 258*44554ea0SWill PaznerCalls `f` with an array containing the data of the `CeedVector` `v`, using [`memory 259*44554ea0SWill Paznertype`](@ref MemType) `mtype`. 260*44554ea0SWill Pazner 261*44554ea0SWill PaznerBecause of performance issues involving closures, if `f` is a complex operation, it may be 262*44554ea0SWill Paznermore efficient to use the macro version `@witharray` (cf. the section on "Performance of 263*44554ea0SWill Paznercaptured variable" in the [Julia 264*44554ea0SWill Paznerdocumentation](https://docs.julialang.org/en/v1/manual/performance-tips) and related [GitHub 265*44554ea0SWill Paznerissue](https://github.com/JuliaLang/julia/issues/15276). 266*44554ea0SWill Pazner 267*44554ea0SWill Pazner# Examples 268*44554ea0SWill Pazner 269*44554ea0SWill PaznerReturn the sum of a vector: 270*44554ea0SWill Pazner``` 271*44554ea0SWill Paznerwitharray(sum, v) 272*44554ea0SWill Pazner``` 273*44554ea0SWill Pazner""" 274*44554ea0SWill Paznerfunction witharray(f, v::CeedVector, mtype::MemType=MEM_HOST) 275*44554ea0SWill Pazner arr_ref = Ref{Ptr{C.CeedScalar}}() 276*44554ea0SWill Pazner C.CeedVectorGetArray(v[], mtype, arr_ref) 277*44554ea0SWill Pazner arr = UnsafeArray(arr_ref[], (length(v),)) 278*44554ea0SWill Pazner res = try 279*44554ea0SWill Pazner f(arr) 280*44554ea0SWill Pazner finally 281*44554ea0SWill Pazner C.CeedVectorRestoreArray(v[], arr_ref) 282*44554ea0SWill Pazner end 283*44554ea0SWill Pazner return res 284*44554ea0SWill Paznerend 285*44554ea0SWill Pazner 286*44554ea0SWill Pazner""" 287*44554ea0SWill Pazner witharray_read(f, v::CeedVector, mtype::MemType=MEM_HOST) 288*44554ea0SWill Pazner 289*44554ea0SWill PaznerSame as [`witharray`](@ref), but with read-only access to the data. 290*44554ea0SWill Pazner 291*44554ea0SWill Pazner# Examples 292*44554ea0SWill Pazner 293*44554ea0SWill PaznerDisplay the contents of a vector: 294*44554ea0SWill Pazner``` 295*44554ea0SWill Paznerwitharray_read(display, v) 296*44554ea0SWill Pazner``` 297*44554ea0SWill Pazner""" 298*44554ea0SWill Paznerfunction witharray_read(f, v::CeedVector, mtype::MemType=MEM_HOST) 299*44554ea0SWill Pazner arr_ref = Ref{Ptr{C.CeedScalar}}() 300*44554ea0SWill Pazner C.CeedVectorGetArrayRead(v[], mtype, arr_ref) 301*44554ea0SWill Pazner arr = UnsafeArray(arr_ref[], (length(v),)) 302*44554ea0SWill Pazner res = try 303*44554ea0SWill Pazner f(arr) 304*44554ea0SWill Pazner finally 305*44554ea0SWill Pazner C.CeedVectorRestoreArrayRead(v[], arr_ref) 306*44554ea0SWill Pazner end 307*44554ea0SWill Pazner return res 308*44554ea0SWill Paznerend 309