1*557acef3SWill Paznerimport LinearAlgebra: norm, axpy! 244554ea0SWill Pazner 344554ea0SWill Paznerabstract type AbstractCeedVector end 444554ea0SWill Pazner 544554ea0SWill Paznerstruct CeedVectorActive <: AbstractCeedVector end 644554ea0SWill PaznerBase.getindex(::CeedVectorActive) = C.CEED_VECTOR_ACTIVE[] 744554ea0SWill Pazner 844554ea0SWill Paznerstruct CeedVectorNone <: AbstractCeedVector end 944554ea0SWill PaznerBase.getindex(::CeedVectorNone) = C.CEED_VECTOR_NONE[] 1044554ea0SWill Pazner 1144554ea0SWill Paznermutable struct CeedVector <: AbstractCeedVector 1244554ea0SWill Pazner ref::RefValue{C.CeedVector} 1344554ea0SWill Pazner arr::Union{Nothing,AbstractArray} 1444554ea0SWill Pazner CeedVector(ref::Ref{C.CeedVector}) = new(ref, nothing) 1544554ea0SWill Paznerend 1644554ea0SWill Pazner 1744554ea0SWill Pazner""" 1844554ea0SWill Pazner CeedVector(c::Ceed, len::Integer) 1944554ea0SWill Pazner 2044554ea0SWill PaznerCreates a `CeedVector` of given length. 2144554ea0SWill Pazner""" 2244554ea0SWill Paznerfunction CeedVector(c::Ceed, len::Integer) 2344554ea0SWill Pazner ref = Ref{C.CeedVector}() 2444554ea0SWill Pazner C.CeedVectorCreate(c[], len, ref) 2544554ea0SWill Pazner obj = CeedVector(ref) 2644554ea0SWill Pazner finalizer(obj) do x 2744554ea0SWill Pazner # ccall(:jl_safe_printf, Cvoid, (Cstring, Cstring), "Finalizing %s.\n", repr(x)) 2844554ea0SWill Pazner destroy(x) 2944554ea0SWill Pazner end 3044554ea0SWill Pazner return obj 3144554ea0SWill Paznerend 3244554ea0SWill Paznerdestroy(v::CeedVector) = C.CeedVectorDestroy(v.ref) # COV_EXCL_LINE 3344554ea0SWill PaznerBase.getindex(v::CeedVector) = v.ref[] 3444554ea0SWill Pazner 3544554ea0SWill PaznerBase.summary(io::IO, v::CeedVector) = print(io, length(v), "-element CeedVector") 3644554ea0SWill Paznerfunction Base.show(io::IO, ::MIME"text/plain", v::CeedVector) 3744554ea0SWill Pazner summary(io, v) 3844554ea0SWill Pazner println(io, ":") 3944554ea0SWill Pazner witharray_read(v, MEM_HOST) do arr 4044554ea0SWill Pazner Base.print_array(io, arr) 4144554ea0SWill Pazner end 4244554ea0SWill Paznerend 4344554ea0SWill PaznerBase.show(io::IO, v::CeedVector) = witharray_read(a -> show(io, a), v, MEM_HOST) 4444554ea0SWill Pazner 4544554ea0SWill Paznerfunction Base.length(::Type{T}, v::CeedVector) where {T} 4644554ea0SWill Pazner len = Ref{C.CeedInt}() 4744554ea0SWill Pazner C.CeedVectorGetLength(v[], len) 4844554ea0SWill Pazner return T(len[]) 4944554ea0SWill Paznerend 5044554ea0SWill Pazner 5144554ea0SWill PaznerBase.ndims(::CeedVector) = 1 5244554ea0SWill PaznerBase.ndims(::Type{CeedVector}) = 1 5344554ea0SWill PaznerBase.axes(v::CeedVector) = (Base.OneTo(length(v)),) 5444554ea0SWill PaznerBase.size(v::CeedVector) = (length(Int, v),) 5544554ea0SWill PaznerBase.length(v::CeedVector) = length(Int, v) 5644554ea0SWill Pazner 5744554ea0SWill Pazner""" 5844554ea0SWill Pazner setvalue!(v::CeedVector, val::CeedScalar) 5944554ea0SWill Pazner 6044554ea0SWill PaznerSet the [`CeedVector`](@ref) to a constant value. 6144554ea0SWill Pazner""" 6244554ea0SWill Paznersetvalue!(v::CeedVector, val::CeedScalar) = C.CeedVectorSetValue(v[], val) 6344554ea0SWill Pazner""" 6444554ea0SWill Pazner setindex!(v::CeedVector, val::CeedScalar) 6544554ea0SWill Pazner v[] = val 6644554ea0SWill Pazner 6744554ea0SWill PaznerSet the [`CeedVector`](@ref) to a constant value, synonymous to [`setvalue!`](@ref). 6844554ea0SWill Pazner""" 6944554ea0SWill PaznerBase.setindex!(v::CeedVector, val::CeedScalar) = setvalue!(v, val) 7044554ea0SWill Pazner 7144554ea0SWill Pazner""" 7244554ea0SWill Pazner norm(v::CeedVector, ntype::NormType) 7344554ea0SWill Pazner 7444554ea0SWill PaznerReturn the norm of the given [`CeedVector`](@ref). 7544554ea0SWill Pazner 7644554ea0SWill PaznerThe norm type can either be specified as one of `NORM_1`, `NORM_2`, `NORM_MAX`. 7744554ea0SWill Pazner""" 7844554ea0SWill Paznerfunction norm(v::CeedVector, ntype::NormType) 7944554ea0SWill Pazner nrm = Ref{CeedScalar}() 8044554ea0SWill Pazner C.CeedVectorNorm(v[], ntype, nrm) 8144554ea0SWill Pazner nrm[] 8244554ea0SWill Paznerend 8344554ea0SWill Pazner 8444554ea0SWill Pazner""" 8544554ea0SWill Pazner norm(v::CeedVector, p::Real) 8644554ea0SWill Pazner 8744554ea0SWill PaznerReturn the norm of the given [`CeedVector`](@ref), see [`norm(::CeedVector, 8844554ea0SWill Pazner::NormType)`](@ref). 8944554ea0SWill Pazner 9044554ea0SWill Pazner`p` can have value 1, 2, or Inf, corresponding to `NORM_1`, `NORM_2`, and `NORM_MAX`, 9144554ea0SWill Paznerrespectively. 9244554ea0SWill Pazner""" 9344554ea0SWill Paznerfunction norm(v::CeedVector, p::Real) 9444554ea0SWill Pazner if p == 1 9544554ea0SWill Pazner ntype = NORM_1 9644554ea0SWill Pazner elseif p == 2 9744554ea0SWill Pazner ntype = NORM_2 9844554ea0SWill Pazner elseif isinf(p) 9944554ea0SWill Pazner ntype = NORM_MAX 10044554ea0SWill Pazner else 10144554ea0SWill Pazner error("norm(v::CeedVector, p): p must be 1, 2, or Inf") 10244554ea0SWill Pazner end 10344554ea0SWill Pazner norm(v, ntype) 10444554ea0SWill Paznerend 10544554ea0SWill Pazner 10644554ea0SWill Pazner""" 10744554ea0SWill Pazner reciprocal!(v::CeedVector) 10844554ea0SWill Pazner 10944554ea0SWill PaznerSet `v` to be equal to its elementwise reciprocal. 11044554ea0SWill Pazner""" 11144554ea0SWill Paznerreciprocal!(v::CeedVector) = C.CeedVectorReciprocal(v[]) 11244554ea0SWill Pazner 11344554ea0SWill Pazner""" 11444554ea0SWill Pazner setarray!(v::CeedVector, mtype::MemType, cmode::CopyMode, arr) 11544554ea0SWill Pazner 11644554ea0SWill PaznerSet the array used by a [`CeedVector`](@ref), freeing any previously allocated array if 11744554ea0SWill Paznerapplicable. The backend may copy values to a different [`MemType`](@ref). See also 11844554ea0SWill Pazner[`syncarray!`](@ref) and [`takearray!`](@ref). 11944554ea0SWill Pazner 12044554ea0SWill Pazner!!! warning "Avoid OWN_POINTER CopyMode" 12144554ea0SWill Pazner The [`CopyMode`](@ref) `OWN_POINTER` is not suitable for use with arrays that are 12244554ea0SWill Pazner allocated by Julia, since those cannot be properly freed from libCEED. 12344554ea0SWill Pazner""" 12444554ea0SWill Paznerfunction setarray!(v::CeedVector, mtype::MemType, cmode::CopyMode, arr) 12544554ea0SWill Pazner C.CeedVectorSetArray(v[], mtype, cmode, arr) 12644554ea0SWill Pazner if cmode == USE_POINTER 12744554ea0SWill Pazner v.arr = arr 12844554ea0SWill Pazner end 12944554ea0SWill Paznerend 13044554ea0SWill Pazner 13144554ea0SWill Pazner""" 13244554ea0SWill Pazner syncarray!(v::CeedVector, mtype::MemType) 13344554ea0SWill Pazner 13444554ea0SWill PaznerSync the [`CeedVector`](@ref) to a specified [`MemType`](@ref). This function is used to 13544554ea0SWill Paznerforce synchronization of arrays set with [`setarray!`](@ref). If the requested memtype is 13644554ea0SWill Pazneralready synchronized, this function results in a no-op. 13744554ea0SWill Pazner""" 13844554ea0SWill Paznersyncarray!(v::CeedVector, mtype::MemType) = C.CeedVectorSyncArray(v[], mtype) 13944554ea0SWill Pazner 14044554ea0SWill Pazner""" 14144554ea0SWill Pazner takearray!(v::CeedVector, mtype::MemType) 14244554ea0SWill Pazner 14344554ea0SWill PaznerTake ownership of the [`CeedVector`](@ref) array and remove the array from the 14444554ea0SWill Pazner[`CeedVector`](@ref). The caller is responsible for managing and freeing the array. The 14544554ea0SWill Paznerarray is returns as a `Ptr{CeedScalar}`. 14644554ea0SWill Pazner""" 14744554ea0SWill Paznerfunction takearray!(v::CeedVector, mtype::MemType) 14844554ea0SWill Pazner ptr = Ref{Ptr{CeedScalar}}() 14944554ea0SWill Pazner C.CeedVectorTakeArray(v[], mtype, ptr) 15044554ea0SWill Pazner v.arr = nothing 15144554ea0SWill Pazner ptr[] 15244554ea0SWill Paznerend 15344554ea0SWill Pazner 15444554ea0SWill Pazner# Helper function to parse arguments of @witharray and @witharray_read 15544554ea0SWill Paznerfunction witharray_parse(assignment, args) 15644554ea0SWill Pazner if !Meta.isexpr(assignment, :(=)) 15744554ea0SWill Pazner error("@witharray must have first argument of the form v_arr=v") # COV_EXCL_LINE 15844554ea0SWill Pazner end 15944554ea0SWill Pazner arr = assignment.args[1] 16044554ea0SWill Pazner v = assignment.args[2] 16144554ea0SWill Pazner mtype = MEM_HOST 16244554ea0SWill Pazner sz = :((length($(esc(v))),)) 16344554ea0SWill Pazner body = args[end] 16444554ea0SWill Pazner for i = 1:length(args)-1 16544554ea0SWill Pazner a = args[i] 16644554ea0SWill Pazner if !Meta.isexpr(a, :(=)) 16744554ea0SWill Pazner error("Incorrect call to @witharray or @witharray_read") # COV_EXCL_LINE 16844554ea0SWill Pazner end 16944554ea0SWill Pazner if a.args[1] == :mtype 17044554ea0SWill Pazner mtype = a.args[2] 17144554ea0SWill Pazner elseif a.args[1] == :size 17244554ea0SWill Pazner sz = esc(a.args[2]) 17344554ea0SWill Pazner end 17444554ea0SWill Pazner end 17544554ea0SWill Pazner arr, v, sz, mtype, body 17644554ea0SWill Paznerend 17744554ea0SWill Pazner 17844554ea0SWill Pazner""" 17944554ea0SWill Pazner @witharray(v_arr=v, [size=(dims...)], [mtype=MEM_HOST], body) 18044554ea0SWill Pazner 18144554ea0SWill PaznerExecutes `body`, having extracted the contents of the [`CeedVector`](@ref) `v` as an array 18244554ea0SWill Paznerwith name `v_arr`. If the [`memory type`](@ref MemType) `mtype` is not provided, `MEM_HOST` 18344554ea0SWill Paznerwill be used. If the size is not specified, a flat vector will be assumed. 18444554ea0SWill Pazner 18544554ea0SWill Pazner# Examples 18644554ea0SWill PaznerNegate the contents of `CeedVector` `v`: 18744554ea0SWill Pazner``` 188*557acef3SWill Pazner@witharray v_arr=v v_arr .*= -1.0 18944554ea0SWill Pazner``` 19044554ea0SWill Pazner""" 19144554ea0SWill Paznermacro witharray(assignment, args...) 19244554ea0SWill Pazner arr, v, sz, mtype, body = witharray_parse(assignment, args) 19344554ea0SWill Pazner quote 19444554ea0SWill Pazner arr_ref = Ref{Ptr{C.CeedScalar}}() 19544554ea0SWill Pazner C.CeedVectorGetArray($(esc(v))[], $(esc(mtype)), arr_ref) 19644554ea0SWill Pazner try 19744554ea0SWill Pazner $(esc(arr)) = UnsafeArray(arr_ref[], Int.($sz)) 19844554ea0SWill Pazner $(esc(body)) 19944554ea0SWill Pazner finally 20044554ea0SWill Pazner C.CeedVectorRestoreArray($(esc(v))[], arr_ref) 20144554ea0SWill Pazner end 20244554ea0SWill Pazner end 20344554ea0SWill Paznerend 20444554ea0SWill Pazner 20544554ea0SWill Pazner""" 20644554ea0SWill Pazner @witharray_read(v_arr=v, [size=(dims...)], [mtype=MEM_HOST], body) 20744554ea0SWill Pazner 20844554ea0SWill PaznerSame as [`@witharray`](@ref), but provides read-only access to the data. 20944554ea0SWill Pazner""" 21044554ea0SWill Paznermacro witharray_read(assignment, args...) 21144554ea0SWill Pazner arr, v, sz, mtype, body = witharray_parse(assignment, args) 21244554ea0SWill Pazner quote 21344554ea0SWill Pazner arr_ref = Ref{Ptr{C.CeedScalar}}() 21444554ea0SWill Pazner C.CeedVectorGetArrayRead($(esc(v))[], $(esc(mtype)), arr_ref) 21544554ea0SWill Pazner try 21644554ea0SWill Pazner $(esc(arr)) = UnsafeArray(arr_ref[], Int.($sz)) 21744554ea0SWill Pazner $(esc(body)) 21844554ea0SWill Pazner finally 21944554ea0SWill Pazner C.CeedVectorRestoreArrayRead($(esc(v))[], arr_ref) 22044554ea0SWill Pazner end 22144554ea0SWill Pazner end 22244554ea0SWill Paznerend 22344554ea0SWill Pazner 22444554ea0SWill Pazner""" 22544554ea0SWill Pazner setindex!(v::CeedVector, v2::AbstractArray) 22644554ea0SWill Pazner v[] = v2 22744554ea0SWill Pazner 22844554ea0SWill PaznerSets the values of [`CeedVector`](@ref) `v` equal to those of `v2` using broadcasting. 22944554ea0SWill Pazner""" 23044554ea0SWill PaznerBase.setindex!(v::CeedVector, v2::AbstractArray) = @witharray(a = v, a .= v2) 23144554ea0SWill Pazner 23244554ea0SWill Pazner""" 23344554ea0SWill Pazner CeedVector(c::Ceed, v2::AbstractVector; mtype=MEM_HOST, cmode=COPY_VALUES) 23444554ea0SWill Pazner 23544554ea0SWill PaznerCreates a new [`CeedVector`](@ref) using the contents of the given vector `v2`. By default, 23644554ea0SWill Paznerthe contents of `v2` will be copied to the new [`CeedVector`](@ref), but this behavior can 23744554ea0SWill Paznerbe changed by specifying a different `cmode`. 23844554ea0SWill Pazner""" 23944554ea0SWill Paznerfunction CeedVector(c::Ceed, v2::AbstractVector; mtype=MEM_HOST, cmode=COPY_VALUES) 24044554ea0SWill Pazner v = CeedVector(c, length(v2)) 24144554ea0SWill Pazner setarray!(v, mtype, cmode, v2) 24244554ea0SWill Pazner v 24344554ea0SWill Paznerend 24444554ea0SWill Pazner 24544554ea0SWill Pazner""" 24644554ea0SWill Pazner Vector(v::CeedVector) 24744554ea0SWill Pazner 24844554ea0SWill PaznerCreate a new `Vector` by copying the contents of `v`. 24944554ea0SWill Pazner""" 25044554ea0SWill Paznerfunction Base.Vector(v::CeedVector) 25144554ea0SWill Pazner v2 = Vector{CeedScalar}(undef, length(v)) 25244554ea0SWill Pazner @witharray_read(a = v, v2 .= a) 25344554ea0SWill Paznerend 25444554ea0SWill Pazner 25544554ea0SWill Pazner""" 25644554ea0SWill Pazner witharray(f, v::CeedVector, mtype=MEM_HOST) 25744554ea0SWill Pazner 25844554ea0SWill PaznerCalls `f` with an array containing the data of the `CeedVector` `v`, using [`memory 25944554ea0SWill Paznertype`](@ref MemType) `mtype`. 26044554ea0SWill Pazner 26144554ea0SWill PaznerBecause of performance issues involving closures, if `f` is a complex operation, it may be 26244554ea0SWill Paznermore efficient to use the macro version `@witharray` (cf. the section on "Performance of 26344554ea0SWill Paznercaptured variable" in the [Julia 26444554ea0SWill Paznerdocumentation](https://docs.julialang.org/en/v1/manual/performance-tips) and related [GitHub 26544554ea0SWill Paznerissue](https://github.com/JuliaLang/julia/issues/15276). 26644554ea0SWill Pazner 26744554ea0SWill Pazner# Examples 26844554ea0SWill Pazner 26944554ea0SWill PaznerReturn the sum of a vector: 27044554ea0SWill Pazner``` 27144554ea0SWill Paznerwitharray(sum, v) 27244554ea0SWill Pazner``` 27344554ea0SWill Pazner""" 27444554ea0SWill Paznerfunction witharray(f, v::CeedVector, mtype::MemType=MEM_HOST) 27544554ea0SWill Pazner arr_ref = Ref{Ptr{C.CeedScalar}}() 27644554ea0SWill Pazner C.CeedVectorGetArray(v[], mtype, arr_ref) 27744554ea0SWill Pazner arr = UnsafeArray(arr_ref[], (length(v),)) 27844554ea0SWill Pazner res = try 27944554ea0SWill Pazner f(arr) 28044554ea0SWill Pazner finally 28144554ea0SWill Pazner C.CeedVectorRestoreArray(v[], arr_ref) 28244554ea0SWill Pazner end 28344554ea0SWill Pazner return res 28444554ea0SWill Paznerend 28544554ea0SWill Pazner 28644554ea0SWill Pazner""" 28744554ea0SWill Pazner witharray_read(f, v::CeedVector, mtype::MemType=MEM_HOST) 28844554ea0SWill Pazner 28944554ea0SWill PaznerSame as [`witharray`](@ref), but with read-only access to the data. 29044554ea0SWill Pazner 29144554ea0SWill Pazner# Examples 29244554ea0SWill Pazner 29344554ea0SWill PaznerDisplay the contents of a vector: 29444554ea0SWill Pazner``` 29544554ea0SWill Paznerwitharray_read(display, v) 29644554ea0SWill Pazner``` 29744554ea0SWill Pazner""" 29844554ea0SWill Paznerfunction witharray_read(f, v::CeedVector, mtype::MemType=MEM_HOST) 29944554ea0SWill Pazner arr_ref = Ref{Ptr{C.CeedScalar}}() 30044554ea0SWill Pazner C.CeedVectorGetArrayRead(v[], mtype, arr_ref) 30144554ea0SWill Pazner arr = UnsafeArray(arr_ref[], (length(v),)) 30244554ea0SWill Pazner res = try 30344554ea0SWill Pazner f(arr) 30444554ea0SWill Pazner finally 30544554ea0SWill Pazner C.CeedVectorRestoreArrayRead(v[], arr_ref) 30644554ea0SWill Pazner end 30744554ea0SWill Pazner return res 30844554ea0SWill Paznerend 309*557acef3SWill Pazner 310*557acef3SWill Pazner""" 311*557acef3SWill Pazner scale!(v::CeedVector, a::Real) 312*557acef3SWill Pazner 313*557acef3SWill PaznerOverwrite `v` with `a*v` for scalar `a`. Returns `v`. 314*557acef3SWill Pazner""" 315*557acef3SWill Paznerfunction scale!(v::CeedVector, a::Real) 316*557acef3SWill Pazner C.CeedVectorScale(v[], a) 317*557acef3SWill Pazner return v 318*557acef3SWill Paznerend 319*557acef3SWill Pazner 320*557acef3SWill Pazner""" 321*557acef3SWill Pazner axpy!(a::Real, x::CeedVector, y::CeedVector) 322*557acef3SWill Pazner 323*557acef3SWill PaznerOverwrite `y` with `x*a + y`, where `a` is a scalar. Returns `y`. 324*557acef3SWill Pazner 325*557acef3SWill Pazner!!! warning "Different argument order" 326*557acef3SWill Pazner In order to be consistent with `LinearAlgebra.axpy!`, the arguments are passed in order: `a`, 327*557acef3SWill Pazner `x`, `y`. This is different than the order of arguments of the C function `CeedVectorAXPY`. 328*557acef3SWill Pazner""" 329*557acef3SWill Paznerfunction axpy!(a::Real, x::CeedVector, y::CeedVector) 330*557acef3SWill Pazner C.CeedVectorAXPY(y[], a, x[]) 331*557acef3SWill Pazner return y 332*557acef3SWill Paznerend 333*557acef3SWill Pazner 334*557acef3SWill Pazner""" 335*557acef3SWill Pazner pointwisemult!(w::CeedVector, x::CeedVector, y::CeedVector) 336*557acef3SWill Pazner 337*557acef3SWill PaznerOverwrite `w` with `x .* y`. Any subset of x, y, and w may be the same vector. Returns `w`. 338*557acef3SWill Pazner""" 339*557acef3SWill Paznerfunction pointwisemult!(w::CeedVector, x::CeedVector, y::CeedVector) 340*557acef3SWill Pazner C.CeedVectorPointwiseMult(w[], x[], y[]) 341*557acef3SWill Pazner return w 342*557acef3SWill Paznerend 343