xref: /libCEED/julia/LibCEED.jl/src/ElemRestriction.jl (revision 44554ea01e90fce366fc2a203c44be15754a38d6)
1abstract type AbstractElemRestriction end
2
3"""
4    ElemRestrictionNone()
5
6Returns the singleton object corresponding to libCEED's `CEED_ELEMRESTRICTION_NONE`
7"""
8struct ElemRestrictionNone <: AbstractElemRestriction end
9Base.getindex(::ElemRestrictionNone) = C.CEED_ELEMRESTRICTION_NONE[]
10
11"""
12    ElemRestriction
13
14Wraps a `CeedElemRestriction` object, representing the restriction from local vectors to
15elements. An `ElemRestriction` object can be created using [`create_elem_restriction`](@ref)
16or [`create_elem_restriction_strided`](@ref).
17"""
18mutable struct ElemRestriction <: AbstractElemRestriction
19    ref::RefValue{C.CeedElemRestriction}
20    function ElemRestriction(ref)
21        obj = new(ref)
22        finalizer(obj) do x
23            # ccall(:jl_safe_printf, Cvoid, (Cstring, Cstring), "Finalizing %s.\n", repr(x))
24            destroy(x)
25        end
26        return obj
27    end
28end
29destroy(r::ElemRestriction) = C.CeedElemRestrictionDestroy(r.ref) # COV_EXCL_LINE
30Base.getindex(r::ElemRestriction) = r.ref[]
31Base.show(io::IO, ::MIME"text/plain", e::ElemRestriction) =
32    ceed_show(io, e, C.CeedElemRestrictionView)
33
34@doc raw"""
35    create_elem_restriction(
36        ceed::Ceed,
37        nelem,
38        elemsize,
39        ncomp,
40        compstride,
41        lsize,
42        offsets::AbstractArray{CeedInt},
43        mtype::MemType=MEM_HOST,
44        cmode::CopyMode=COPY_VALUES,
45    )
46
47Create a `CeedElemRestriction`.
48
49!!! warning "Zero-based indexing"
50    In the below notation, we are using **0-based indexing**. libCEED expects the offset
51    indices to be 0-based.
52
53# Arguments:
54- `ceed`:       The [`Ceed`](@ref) object
55- `nelem`:      Number of elements described in the `offsets` array
56- `elemsize`:   Size (number of "nodes") per element
57- `ncomp`:      Number of field components per interpolation node (1 for scalar fields)
58- `compstride`: Stride between components for the same L-vector "node". Data for node $i$,
59                component $j$, element $k$ can be found in the L-vector at index `offsets[i
60                + k*elemsize] + j*compstride`.
61- `lsize`:      The size of the L-vector. This vector may be larger than the elements and
62                fields given by this restriction.
63- `offsets`:    Array of shape `(elemsize, nelem)`. Column $i$ holds the ordered list of the
64                offsets (into the input [`CeedVector`](@ref)) for the unknowns corresponding
65                to element $i$, where $0 \leq i < \textit{nelem}$. All offsets must be in
66                the range $[0, \textit{lsize} - 1]$.
67- `mtype`:      Memory type of the `offsets` array, see [`MemType`](@ref)
68- `cmode`:      Copy mode for the `offsets` array, see [`CopyMode`](@ref)
69"""
70function create_elem_restriction(
71    c::Ceed,
72    nelem,
73    elemsize,
74    ncomp,
75    compstride,
76    lsize,
77    offsets::AbstractArray{CeedInt};
78    mtype::MemType=MEM_HOST,
79    cmode::CopyMode=COPY_VALUES,
80)
81    ref = Ref{C.CeedElemRestriction}()
82    C.CeedElemRestrictionCreate(
83        c[],
84        nelem,
85        elemsize,
86        ncomp,
87        compstride,
88        lsize,
89        mtype,
90        cmode,
91        offsets,
92        ref,
93    )
94    ElemRestriction(ref)
95end
96
97@doc raw"""
98    create_elem_restriction_strided(ceed::Ceed, nelem, elemsize, ncomp, lsize, strides)
99
100Create a strided `CeedElemRestriction`.
101
102!!! warning "Zero-based indexing"
103    In the below notation, we are using **0-based indexing**. libCEED expects the offset
104    indices to be 0-based.
105
106# Arguments:
107- `ceed`:     The [`Ceed`](@ref) object
108- `nelem`:    Number of elements described by the restriction
109- `elemsize`: Size (number of "nodes") per element
110- `ncomp`:    Number of field components per interpolation node (1 for scalar fields)
111- `lsize`:    The size of the L-vector. This vector may be larger than the elements and
112              fields given by this restriction.
113- `strides`:  Array for strides between [nodes, components, elements]. Data for node $i$,
114              component $j$, element $k$ can be found in the L-vector at index `i*strides[0]
115              + j*strides[1] + k*strides[2]`. [`STRIDES_BACKEND`](@ref) may be used with
116              vectors created by a Ceed backend.
117"""
118function create_elem_restriction_strided(c::Ceed, nelem, elemsize, ncomp, lsize, strides)
119    ref = Ref{C.CeedElemRestriction}()
120    C.CeedElemRestrictionCreateStrided(c[], nelem, elemsize, ncomp, lsize, strides, ref)
121    ElemRestriction(ref)
122end
123
124"""
125    apply!(
126        r::ElemRestriction,
127        u::CeedVector,
128        ru::CeedVector;
129        tmode=NOTRANSPOSE,
130        request=RequestImmediate(),
131    )
132
133Use the [`ElemRestriction`](@ref) to convert from L-vector to an E-vector (or apply the
134tranpose operation). The input [`CeedVector`](@ref) is `u` and the result stored in `ru`.
135
136If `tmode` is `TRANSPOSE`, then the result is added to `ru`. If `tmode` is `NOTRANSPOSE`,
137then `ru` is overwritten with the result.
138"""
139function apply!(
140    r::ElemRestriction,
141    u::CeedVector,
142    ru::CeedVector;
143    tmode=NOTRANSPOSE,
144    request=RequestImmediate(),
145)
146    C.CeedElemRestrictionApply(r[], tmode, u[], ru[], request[])
147end
148
149"""
150    apply(r::ElemRestriction, u::AbstractVector; tmode=NOTRANSPOSE)
151
152Use the [`ElemRestriction`](@ref) to convert from L-vector to an E-vector (or apply the
153tranpose operation). The input is given by `u`, and the result is returned as an array of
154type `Vector{CeedScalar}`.
155"""
156function apply(r::ElemRestriction, u::AbstractVector; tmode=NOTRANSPOSE)
157    ceed_ref = Ref{C.Ceed}()
158    ccall(
159        (:CeedElemRestrictionGetCeed, C.libceed),
160        Cint,
161        (C.CeedElemRestriction, Ptr{C.Ceed}),
162        r[],
163        ceed_ref,
164    )
165    c = Ceed(ceed_ref)
166    uv = CeedVector(c, u)
167    if tmode == NOTRANSPOSE
168        ruv = create_evector(r)
169    else
170        ruv = create_lvector(r)
171        ruv[] = 0.0
172    end
173    apply!(r, uv, ruv; tmode=tmode)
174    Vector(ruv)
175end
176
177"""
178    create_evector(r::ElemRestriction)
179
180Return a new [`CeedVector`](@ref) E-vector.
181"""
182function create_evector(r::ElemRestriction)
183    ref = Ref{C.CeedVector}()
184    C.CeedElemRestrictionCreateVector(r[], C_NULL, ref)
185    CeedVector(ref)
186end
187
188"""
189    create_lvector(r::ElemRestriction)
190
191Return a new [`CeedVector`](@ref) L-vector.
192"""
193function create_lvector(r::ElemRestriction)
194    ref = Ref{C.CeedVector}()
195    C.CeedElemRestrictionCreateVector(r[], ref, C_NULL)
196    CeedVector(ref)
197end
198
199"""
200    create_vectors(r::ElemRestriction)
201
202Return an (L-vector, E-vector) pair.
203"""
204function create_vectors(r::ElemRestriction)
205    l_ref = Ref{C.CeedVector}()
206    e_ref = Ref{C.CeedVector}()
207    C.CeedElemRestrictionCreateVector(r[], l_ref, e_ref)
208    CeedVector(l_ref), CeedVector(e_ref)
209end
210
211"""
212    getcompstride(r::ElemRestriction)
213
214Get the L-vector component stride.
215"""
216function getcompstride(r::ElemRestriction)
217    lsize = Ref{CeedInt}()
218    C.CeedElemRestrictionGetCompStride(r[], lsize)
219    lsize[]
220end
221
222"""
223    getnumelements(r::ElemRestriction)
224
225Get the total number of elements in the range of an [`ElemRestriction`](@ref).
226"""
227function getnumelements(r::ElemRestriction)
228    result = Ref{CeedInt}()
229    C.CeedElemRestrictionGetNumElements(r[], result)
230    result[]
231end
232
233"""
234    getelementsize(r::ElemRestriction)
235
236Get the size of elements in the given [`ElemRestriction`](@ref).
237"""
238function getelementsize(r::ElemRestriction)
239    result = Ref{CeedInt}()
240    C.CeedElemRestrictionGetElementSize(r[], result)
241    result[]
242end
243
244"""
245    getlvectorsize(r::ElemRestriction)
246
247Get the size of an L-vector for the given [`ElemRestriction`](@ref).
248"""
249function getlvectorsize(r::ElemRestriction)
250    result = Ref{CeedInt}()
251    C.CeedElemRestrictionGetLVectorSize(r[], result)
252    result[]
253end
254
255"""
256    getnumcomponents(r::ElemRestriction)
257
258Get the number of components in the elements of an [`ElemRestriction`](@ref).
259"""
260function getnumcomponents(r::ElemRestriction)
261    result = Ref{CeedInt}()
262    C.CeedElemRestrictionGetNumComponents(r[], result)
263    result[]
264end
265
266"""
267    getmultiplicity!(r::ElemRestriction, v::AbstractCeedVector)
268
269Get the multiplicity of nodes in an [`ElemRestriction`](@ref). The [`CeedVector`](@ref) `v`
270should be an L-vector (i.e. `length(v) == getlvectorsize(r)`, see [`create_lvector`](@ref)).
271"""
272function getmultiplicity!(r::ElemRestriction, v::AbstractCeedVector)
273    @assert length(v) == getlvectorsize(r)
274    C.CeedElemRestrictionGetMultiplicity(r[], v[])
275end
276
277"""
278    getmultiplicity(r::ElemRestriction)
279
280Convenience function to get the multiplicity of nodes in the [`ElemRestriction`](@ref),
281where the result is returned in a newly allocated Julia `Vector{CeedScalar}` (see also
282[`getmultiplicity!`](@ref)).
283"""
284function getmultiplicity(r::ElemRestriction)
285    v = create_lvector(r)
286    getmultiplicity!(r, v)
287    Vector(v)
288end
289