xref: /libCEED/julia/LibCEED.jl/src/ElemRestriction.jl (revision b6972d7456611f84b0e462eb1490bcb662442e6a)
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_oriented(
99        ceed::Ceed,
100        nelem,
101        elemsize,
102        ncomp,
103        compstride,
104        lsize,
105        offsets::AbstractArray{CeedInt},
106        orients::AbstractArray{Bool},
107        mtype::MemType=MEM_HOST,
108        cmode::CopyMode=COPY_VALUES,
109    )
110
111Create an oriented `CeedElemRestriction`.
112
113!!! warning "Zero-based indexing"
114    In the below notation, we are using **0-based indexing**. libCEED expects the offset
115    indices to be 0-based.
116
117# Arguments:
118- `ceed`:       The [`Ceed`](@ref) object
119- `nelem`:      Number of elements described in the `offsets` array
120- `elemsize`:   Size (number of "nodes") per element
121- `ncomp`:      Number of field components per interpolation node (1 for scalar fields)
122- `compstride`: Stride between components for the same L-vector "node". Data for node $i$,
123                component $j$, element $k$ can be found in the L-vector at index `offsets[i
124                + k*elemsize] + j*compstride`.
125- `lsize`:      The size of the L-vector. This vector may be larger than the elements and
126                fields given by this restriction.
127- `offsets`:    Array of shape `(elemsize, nelem)`. Column $i$ holds the ordered list of the
128                offsets (into the input [`CeedVector`](@ref)) for the unknowns corresponding
129                to element $i$, where $0 \leq i < \textit{nelem}$. All offsets must be in
130                the range $[0, \textit{lsize} - 1]$.
131- `orients`:    Array of shape `(elemsize, nelem)` with bool false for positively oriented
132                and true to flip the orientation.
133- `mtype`:      Memory type of the `offsets` array, see [`MemType`](@ref)
134- `cmode`:      Copy mode for the `offsets` array, see [`CopyMode`](@ref)
135"""
136function create_elem_restriction_oriented(
137    c::Ceed,
138    nelem,
139    elemsize,
140    ncomp,
141    compstride,
142    lsize,
143    offsets::AbstractArray{CeedInt},
144    orients::AbstractArray{Bool};
145    mtype::MemType=MEM_HOST,
146    cmode::CopyMode=COPY_VALUES,
147)
148    ref = Ref{C.CeedElemRestriction}()
149    C.CeedElemRestrictionCreateOriented(
150        c[],
151        nelem,
152        elemsize,
153        ncomp,
154        compstride,
155        lsize,
156        mtype,
157        cmode,
158        offsets,
159        orients,
160        ref,
161    )
162    ElemRestriction(ref)
163end
164
165@doc raw"""
166    create_elem_restriction_curl_oriented(
167        ceed::Ceed,
168        nelem,
169        elemsize,
170        ncomp,
171        compstride,
172        lsize,
173        offsets::AbstractArray{CeedInt},
174        curlorients::AbstractArray{CeedInt},
175        mtype::MemType=MEM_HOST,
176        cmode::CopyMode=COPY_VALUES,
177    )
178
179Create an curl-oriented `CeedElemRestriction`.
180
181!!! warning "Zero-based indexing"
182    In the below notation, we are using **0-based indexing**. libCEED expects the offset
183    indices to be 0-based.
184
185# Arguments:
186- `ceed`:        The [`Ceed`](@ref) object
187- `nelem`:       Number of elements described in the `offsets` array
188- `elemsize`:    Size (number of "nodes") per element
189- `ncomp`:       Number of field components per interpolation node (1 for scalar fields)
190- `compstride`:  Stride between components for the same L-vector "node". Data for node $i$,
191                 component $j$, element $k$ can be found in the L-vector at index `offsets[i
192                 + k*elemsize] + j*compstride`.
193- `lsize`:       The size of the L-vector. This vector may be larger than the elements and
194                 fields given by this restriction.
195- `offsets`:     Array of shape `(elemsize, nelem)`. Column $i$ holds the ordered list of
196                 the offsets (into the input [`CeedVector`](@ref)) for the unknowns
197                 corresponding to element $i$, where $0 \leq i < \textit{nelem}$. All
198                 offsets must be in the range $[0, \textit{lsize} - 1]$.
199- `curlorients`: Array of shape `(3 * elemsize, nelem)` representing a row-major tridiagonal
200                 matrix (`curlorients[0, i] = curlorients[3 * elemsize - 1, i] = 0`, where
201                 $0 \leq i < \textit{nelem}$) which is applied to the element unknowns upon
202                 restriction.
203- `mtype`:       Memory type of the `offsets` array, see [`MemType`](@ref)
204- `cmode`:       Copy mode for the `offsets` array, see [`CopyMode`](@ref)
205"""
206function create_elem_restriction_curl_oriented(
207    c::Ceed,
208    nelem,
209    elemsize,
210    ncomp,
211    compstride,
212    lsize,
213    offsets::AbstractArray{CeedInt},
214    curlorients::AbstractArray{CeedInt8};
215    mtype::MemType=MEM_HOST,
216    cmode::CopyMode=COPY_VALUES,
217)
218    ref = Ref{C.CeedElemRestriction}()
219    C.CeedElemRestrictionCreateCurlOriented(
220        c[],
221        nelem,
222        elemsize,
223        ncomp,
224        compstride,
225        lsize,
226        mtype,
227        cmode,
228        offsets,
229        curlorients,
230        ref,
231    )
232    ElemRestriction(ref)
233end
234
235@doc raw"""
236    create_elem_restriction_strided(ceed::Ceed, nelem, elemsize, ncomp, lsize, strides)
237
238Create a strided `CeedElemRestriction`.
239
240!!! warning "Zero-based indexing"
241    In the below notation, we are using **0-based indexing**. libCEED expects the offset
242    indices to be 0-based.
243
244# Arguments:
245- `ceed`:     The [`Ceed`](@ref) object
246- `nelem`:    Number of elements described by the restriction
247- `elemsize`: Size (number of "nodes") per element
248- `ncomp`:    Number of field components per interpolation node (1 for scalar fields)
249- `lsize`:    The size of the L-vector. This vector may be larger than the elements and
250              fields given by this restriction.
251- `strides`:  Array for strides between [nodes, components, elements]. Data for node $i$,
252              component $j$, element $k$ can be found in the L-vector at index `i*strides[0]
253              + j*strides[1] + k*strides[2]`. [`STRIDES_BACKEND`](@ref) may be used with
254              vectors created by a Ceed backend.
255"""
256function create_elem_restriction_strided(c::Ceed, nelem, elemsize, ncomp, lsize, strides)
257    ref = Ref{C.CeedElemRestriction}()
258    C.CeedElemRestrictionCreateStrided(c[], nelem, elemsize, ncomp, lsize, strides, ref)
259    ElemRestriction(ref)
260end
261
262"""
263    apply!(
264        r::ElemRestriction,
265        u::CeedVector,
266        ru::CeedVector;
267        tmode=NOTRANSPOSE,
268        request=RequestImmediate(),
269    )
270
271Use the [`ElemRestriction`](@ref) to convert from L-vector to an E-vector (or apply the
272tranpose operation). The input [`CeedVector`](@ref) is `u` and the result stored in `ru`.
273
274If `tmode` is `TRANSPOSE`, then the result is added to `ru`. If `tmode` is `NOTRANSPOSE`,
275then `ru` is overwritten with the result.
276"""
277function apply!(
278    r::ElemRestriction,
279    u::CeedVector,
280    ru::CeedVector;
281    tmode=NOTRANSPOSE,
282    request=RequestImmediate(),
283)
284    C.CeedElemRestrictionApply(r[], tmode, u[], ru[], request[])
285end
286
287"""
288    apply(r::ElemRestriction, u::AbstractVector; tmode=NOTRANSPOSE)
289
290Use the [`ElemRestriction`](@ref) to convert from L-vector to an E-vector (or apply the
291tranpose operation). The input is given by `u`, and the result is returned as an array of
292type `Vector{CeedScalar}`.
293"""
294function apply(r::ElemRestriction, u::AbstractVector; tmode=NOTRANSPOSE)
295    ceed_ref = Ref{C.Ceed}()
296    ccall(
297        (:CeedElemRestrictionGetCeed, C.libceed),
298        Cint,
299        (C.CeedElemRestriction, Ptr{C.Ceed}),
300        r[],
301        ceed_ref,
302    )
303    c = Ceed(ceed_ref)
304    uv = CeedVector(c, u)
305    if tmode == NOTRANSPOSE
306        ruv = create_evector(r)
307    else
308        ruv = create_lvector(r)
309    end
310    ruv[] = 0.0
311    apply!(r, uv, ruv; tmode=tmode)
312    Vector(ruv)
313end
314
315"""
316    create_evector(r::ElemRestriction)
317
318Return a new [`CeedVector`](@ref) E-vector.
319"""
320function create_evector(r::ElemRestriction)
321    ref = Ref{C.CeedVector}()
322    C.CeedElemRestrictionCreateVector(r[], C_NULL, ref)
323    CeedVector(ref)
324end
325
326"""
327    create_lvector(r::ElemRestriction)
328
329Return a new [`CeedVector`](@ref) L-vector.
330"""
331function create_lvector(r::ElemRestriction)
332    ref = Ref{C.CeedVector}()
333    C.CeedElemRestrictionCreateVector(r[], ref, C_NULL)
334    CeedVector(ref)
335end
336
337"""
338    create_vectors(r::ElemRestriction)
339
340Return an (L-vector, E-vector) pair.
341"""
342function create_vectors(r::ElemRestriction)
343    l_ref = Ref{C.CeedVector}()
344    e_ref = Ref{C.CeedVector}()
345    C.CeedElemRestrictionCreateVector(r[], l_ref, e_ref)
346    CeedVector(l_ref), CeedVector(e_ref)
347end
348
349"""
350    getcompstride(r::ElemRestriction)
351
352Get the L-vector component stride.
353"""
354function getcompstride(r::ElemRestriction)
355    lsize = Ref{CeedInt}()
356    C.CeedElemRestrictionGetCompStride(r[], lsize)
357    lsize[]
358end
359
360"""
361    getnumelements(r::ElemRestriction)
362
363Get the total number of elements in the range of an [`ElemRestriction`](@ref).
364"""
365function getnumelements(r::ElemRestriction)
366    result = Ref{CeedInt}()
367    C.CeedElemRestrictionGetNumElements(r[], result)
368    result[]
369end
370
371"""
372    getelementsize(r::ElemRestriction)
373
374Get the size of elements in the given [`ElemRestriction`](@ref).
375"""
376function getelementsize(r::ElemRestriction)
377    result = Ref{CeedInt}()
378    C.CeedElemRestrictionGetElementSize(r[], result)
379    result[]
380end
381
382"""
383    getlvectorsize(r::ElemRestriction)
384
385Get the size of an L-vector for the given [`ElemRestriction`](@ref).
386"""
387function getlvectorsize(r::ElemRestriction)
388    result = Ref{CeedSize}()
389    C.CeedElemRestrictionGetLVectorSize(r[], result)
390    result[]
391end
392
393"""
394    getnumcomponents(r::ElemRestriction)
395
396Get the number of components in the elements of an [`ElemRestriction`](@ref).
397"""
398function getnumcomponents(r::ElemRestriction)
399    result = Ref{CeedInt}()
400    C.CeedElemRestrictionGetNumComponents(r[], result)
401    result[]
402end
403
404"""
405    getmultiplicity!(r::ElemRestriction, v::AbstractCeedVector)
406
407Get the multiplicity of nodes in an [`ElemRestriction`](@ref). The [`CeedVector`](@ref) `v`
408should be an L-vector (i.e. `length(v) == getlvectorsize(r)`, see [`create_lvector`](@ref)).
409"""
410function getmultiplicity!(r::ElemRestriction, v::AbstractCeedVector)
411    @assert length(v) == getlvectorsize(r)
412    C.CeedElemRestrictionGetMultiplicity(r[], v[])
413end
414
415"""
416    getmultiplicity(r::ElemRestriction)
417
418Convenience function to get the multiplicity of nodes in the [`ElemRestriction`](@ref),
419where the result is returned in a newly allocated Julia `Vector{CeedScalar}` (see also
420[`getmultiplicity!`](@ref)).
421"""
422function getmultiplicity(r::ElemRestriction)
423    v = create_lvector(r)
424    getmultiplicity!(r, v)
425    Vector(v)
426end
427