xref: /libCEED/julia/LibCEED.jl/test/runtests.jl (revision 1ad466088344f9c7a89b938b3cea7230e969fe10)
137fad103SWill Paznerusing Test, LibCEED, LinearAlgebra, StaticArrays
237fad103SWill Pazner
3*77bb289aSJed Browninclude("buildmats.jl")
4*77bb289aSJed Brown
504085da3SWill Paznershowstr(x) = sprint(show, MIME("text/plain"), x)
604085da3SWill Paznersummarystr(x) = sprint(summary, x)
780a9ef05SNatalie Beamsgetoutput(fname) =
880a9ef05SNatalie Beams    chomp(read(joinpath(@__DIR__, "output", string(CeedScalar), fname), String))
980a9ef05SNatalie Beams
1080a9ef05SNatalie Beamsfunction checkoutput(str, fname)
1180a9ef05SNatalie Beams    if str != getoutput(fname)
1280a9ef05SNatalie Beams        write(fname, str)
1380a9ef05SNatalie Beams        return false
1480a9ef05SNatalie Beams    end
1580a9ef05SNatalie Beams    return true
1680a9ef05SNatalie Beamsend
1737fad103SWill Pazner
1837fad103SWill Paznermutable struct CtxData
1937fad103SWill Pazner    io::IOBuffer
2037fad103SWill Pazner    x::Vector{Float64}
2137fad103SWill Paznerend
2237fad103SWill Pazner
2304085da3SWill Paznerconst run_dev_tests = !isrelease() || ("--run-dev-tests" in ARGS)
24f99607bdSWill Pazner
25f99607bdSWill Paznerif run_dev_tests
26a697ff73SWill Pazner    include("rundevtests.jl")
27a697ff73SWill Paznerend
28a697ff73SWill Pazner
29c33c11c1SWill Paznerif !LibCEED.ceedversion_ge(LibCEED.minimum_libceed_version) && !run_dev_tests
30f99607bdSWill Pazner    @warn "Skipping tests because of incompatible libCEED versions."
31f99607bdSWill Paznerelse
32a697ff73SWill Pazner    @testset "LibCEED Release Tests" begin
3304085da3SWill Pazner        @testset "LibCEED" begin
3404085da3SWill Pazner            @test ceedversion() isa VersionNumber
3504085da3SWill Pazner            @test isrelease() isa Bool
3604085da3SWill Pazner            @test isfile(get_libceed_path())
3704085da3SWill Pazner        end
3804085da3SWill Pazner
3937fad103SWill Pazner        @testset "Ceed" begin
4037fad103SWill Pazner            res = "/cpu/self/ref/serial"
4137fad103SWill Pazner            c = Ceed(res)
4237fad103SWill Pazner            @test isdeterministic(c)
4337fad103SWill Pazner            @test getresource(c) == res
4437fad103SWill Pazner            @test !iscuda(c)
4537fad103SWill Pazner            @test get_preferred_memtype(c) == MEM_HOST
4637fad103SWill Pazner            @test_throws LibCEED.CeedError create_interior_qfunction(c, "")
4737fad103SWill Pazner            @test showstr(c) == """
4837fad103SWill Pazner                Ceed
4937fad103SWill Pazner                  Ceed Resource: $res
5037fad103SWill Pazner                  Preferred MemType: host"""
5137fad103SWill Pazner        end
5237fad103SWill Pazner
5337fad103SWill Pazner        @testset "Context" begin
5437fad103SWill Pazner            c = Ceed()
5580a9ef05SNatalie Beams            data = zeros(CeedScalar, 3)
5637fad103SWill Pazner            ctx = Context(c, data)
5737fad103SWill Pazner            @test showstr(ctx) == """
5837fad103SWill Pazner                CeedQFunctionContext
5937fad103SWill Pazner                  Context Data Size: $(sizeof(data))"""
6037fad103SWill Pazner            @test_throws Exception set_data!(ctx, MEM_HOST, OWN_POINTER, data)
6137fad103SWill Pazner        end
6237fad103SWill Pazner
6337fad103SWill Pazner        @testset "CeedVector" begin
6437fad103SWill Pazner            n = 10
6537fad103SWill Pazner            c = Ceed()
6637fad103SWill Pazner            v = CeedVector(c, n)
6737fad103SWill Pazner            @test size(v) == (n,)
6837fad103SWill Pazner            @test length(v) == n
6937fad103SWill Pazner            @test axes(v) == (1:n,)
7037fad103SWill Pazner            @test ndims(v) == 1
7137fad103SWill Pazner            @test ndims(CeedVector) == 1
7237fad103SWill Pazner
7337fad103SWill Pazner            v[] = 0.0
7437fad103SWill Pazner            @test @witharray(a = v, all(a .== 0.0))
7537fad103SWill Pazner
7680a9ef05SNatalie Beams            v1 = rand(CeedScalar, n)
7737fad103SWill Pazner            v2 = CeedVector(c, v1)
7837fad103SWill Pazner            @test @witharray_read(a = v2, mtype = MEM_HOST, a == v1)
7937fad103SWill Pazner            @test Vector(v2) == v1
8037fad103SWill Pazner            v[] = v1
8137fad103SWill Pazner            for p ∈ [1, 2, Inf]
8237fad103SWill Pazner                @test norm(v, p) ≈ norm(v1, p)
8337fad103SWill Pazner            end
8437fad103SWill Pazner            @test_throws Exception norm(v, 3)
8537fad103SWill Pazner            @test witharray_read(sum, v) == sum(v1)
8637fad103SWill Pazner            reciprocal!(v)
8780a9ef05SNatalie Beams            @test @witharray(a = v, mtype = MEM_HOST, all(a .== CeedScalar(1.0)./v1))
8837fad103SWill Pazner
8937fad103SWill Pazner            witharray(x -> x .= 1.0, v)
9037fad103SWill Pazner            @test @witharray(a = v, all(a .== 1.0))
9137fad103SWill Pazner
9237fad103SWill Pazner            @test summarystr(v) == "$n-element CeedVector"
93f99607bdSWill Pazner            @test sprint(show, v) == @witharray_read(a = v, sprint(show, a))
94f99607bdSWill Pazner            io = IOBuffer()
95f99607bdSWill Pazner            summary(io, v)
96f99607bdSWill Pazner            println(io, ":")
97f99607bdSWill Pazner            @witharray_read(a = v, Base.print_array(io, a))
98f99607bdSWill Pazner            s1 = String(take!(io))
99f99607bdSWill Pazner            @test showstr(v) == s1
100f99607bdSWill Pazner
101f99607bdSWill Pazner            setarray!(v, MEM_HOST, USE_POINTER, v1)
102f99607bdSWill Pazner            syncarray!(v, MEM_HOST)
103f99607bdSWill Pazner            @test @witharray_read(a = v, a == v1)
104f99607bdSWill Pazner            p = takearray!(v, MEM_HOST)
105f99607bdSWill Pazner            @test p == pointer(v1)
106f99607bdSWill Pazner
10780a9ef05SNatalie Beams            m = rand(CeedScalar, 10, 10)
108f99607bdSWill Pazner            vm = CeedVector(c, vec(m))
109f99607bdSWill Pazner            @test @witharray_read(a = vm, size = size(m), a == m)
110f99607bdSWill Pazner
111f99607bdSWill Pazner            @test CeedVectorActive()[] == LibCEED.C.CEED_VECTOR_ACTIVE[]
112f99607bdSWill Pazner            @test CeedVectorNone()[] == LibCEED.C.CEED_VECTOR_NONE[]
113f99607bdSWill Pazner
11480a9ef05SNatalie Beams            w1 = rand(CeedScalar, n)
11580a9ef05SNatalie Beams            w2 = rand(CeedScalar, n)
11680a9ef05SNatalie Beams            w3 = rand(CeedScalar, n)
117f99607bdSWill Pazner
118f99607bdSWill Pazner            cv1 = CeedVector(c, w1)
119f99607bdSWill Pazner            cv2 = CeedVector(c, w2)
120f99607bdSWill Pazner            cv3 = CeedVector(c, w3)
121f99607bdSWill Pazner
12280a9ef05SNatalie Beams            alpha = rand(CeedScalar)
123f99607bdSWill Pazner
124f99607bdSWill Pazner            scale!(cv1, alpha)
125f99607bdSWill Pazner            w1 .*= alpha
126f99607bdSWill Pazner            @test @witharray_read(a = cv1, a == w1)
127f99607bdSWill Pazner
128f99607bdSWill Pazner            pointwisemult!(cv1, cv2, cv3)
129f99607bdSWill Pazner            w1 .= w2.*w3
130f99607bdSWill Pazner            @test @witharray_read(a = cv1, a == w1)
131f99607bdSWill Pazner
132f99607bdSWill Pazner            axpy!(alpha, cv2, cv1)
133f99607bdSWill Pazner            axpy!(alpha, w2, w1)
134f99607bdSWill Pazner            @test @witharray_read(a = cv1, a ≈ w1)
135f99607bdSWill Pazner        end
13637fad103SWill Pazner
13737fad103SWill Pazner        @testset "Basis" begin
13837fad103SWill Pazner            c = Ceed()
13937fad103SWill Pazner            dim = 3
14037fad103SWill Pazner            ncomp = 1
14137fad103SWill Pazner            p = 4
14237fad103SWill Pazner            q = 6
14337fad103SWill Pazner            b1 = create_tensor_h1_lagrange_basis(c, dim, ncomp, p, q, GAUSS_LOBATTO)
14437fad103SWill Pazner
14537fad103SWill Pazner            @test getdimension(b1) == 3
14637fad103SWill Pazner            @test gettopology(b1) == HEX
14737fad103SWill Pazner            @test getnumcomponents(b1) == ncomp
14837fad103SWill Pazner            @test getnumnodes(b1) == p^dim
14937fad103SWill Pazner            @test getnumnodes1d(b1) == p
15037fad103SWill Pazner            @test getnumqpts(b1) == q^dim
15137fad103SWill Pazner            @test getnumqpts1d(b1) == q
15237fad103SWill Pazner
15337fad103SWill Pazner            q1d, w1d = lobatto_quadrature(3, AbscissaAndWeights)
15480a9ef05SNatalie Beams            @test q1d ≈ CeedScalar[-1.0, 0.0, 1.0]
15580a9ef05SNatalie Beams            @test w1d ≈ CeedScalar[1/3, 4/3, 1/3]
15637fad103SWill Pazner
15737fad103SWill Pazner            q1d, w1d = gauss_quadrature(3)
15880a9ef05SNatalie Beams            @test q1d ≈ CeedScalar[-sqrt(3/5), 0.0, sqrt(3/5)]
15980a9ef05SNatalie Beams            @test w1d ≈ CeedScalar[5/9, 8/9, 5/9]
16037fad103SWill Pazner
16180a9ef05SNatalie Beams            b1d = CeedScalar[1.0 0.0; 0.5 0.5; 0.0 1.0]
16280a9ef05SNatalie Beams            d1d = CeedScalar[-0.5 0.5; -0.5 0.5; -0.5 0.5]
16380a9ef05SNatalie Beams            q1d = CeedScalar[-1.0, 0.0, 1.0]
16480a9ef05SNatalie Beams            w1d = CeedScalar[1/3, 4/3, 1/3]
16537fad103SWill Pazner            q, p = size(b1d)
16680a9ef05SNatalie Beams            d2d = zeros(CeedScalar, 2, q*q, p*p)
16737fad103SWill Pazner            d2d[1, :, :] = kron(b1d, d1d)
16837fad103SWill Pazner            d2d[2, :, :] = kron(d1d, b1d)
16937fad103SWill Pazner
17037fad103SWill Pazner            dim2 = 2
17137fad103SWill Pazner            b2 = create_tensor_h1_basis(c, dim2, 1, p, q, b1d, d1d, q1d, w1d)
17237fad103SWill Pazner            @test getinterp(b2) == kron(b1d, b1d)
17337fad103SWill Pazner            @test getinterp1d(b2) == b1d
17437fad103SWill Pazner            @test getgrad(b2) == d2d
17537fad103SWill Pazner            @test getgrad1d(b2) == d1d
17637fad103SWill Pazner
177b2e3f8ecSSebastian Grimberg            b3 = create_h1_basis(
178b2e3f8ecSSebastian Grimberg                c,
179b2e3f8ecSSebastian Grimberg                LINE,
180b2e3f8ecSSebastian Grimberg                1,
181b2e3f8ecSSebastian Grimberg                p,
182b2e3f8ecSSebastian Grimberg                q,
183b2e3f8ecSSebastian Grimberg                b1d,
184b2e3f8ecSSebastian Grimberg                reshape(d1d, 1, q, p),
185b2e3f8ecSSebastian Grimberg                reshape(q1d, 1, q),
186b2e3f8ecSSebastian Grimberg                w1d,
187b2e3f8ecSSebastian Grimberg            )
188b2e3f8ecSSebastian Grimberg            @test getqref(b3) == reshape(q1d, 1, q)
18937fad103SWill Pazner            @test getqweights(b3) == w1d
19037fad103SWill Pazner
19180a9ef05SNatalie Beams            v = rand(CeedScalar, 2)
19237fad103SWill Pazner            vq = apply(b3, v)
19337fad103SWill Pazner            vd = apply(b3, v; emode=EVAL_GRAD)
19437fad103SWill Pazner            @test vq ≈ b1d*v
19537fad103SWill Pazner            @test vd ≈ d1d*v
19637fad103SWill Pazner        end
19737fad103SWill Pazner
19837fad103SWill Pazner        @testset "Request" begin
19937fad103SWill Pazner            @test RequestImmediate()[] == LibCEED.C.CEED_REQUEST_IMMEDIATE[]
20037fad103SWill Pazner            @test RequestOrdered()[] == LibCEED.C.CEED_REQUEST_ORDERED[]
20137fad103SWill Pazner        end
20237fad103SWill Pazner
20337fad103SWill Pazner        @testset "Misc" begin
20437fad103SWill Pazner            for dim = 1:3
20537fad103SWill Pazner                D = CeedDim(dim)
20680a9ef05SNatalie Beams                J = rand(CeedScalar, dim, dim)
20737fad103SWill Pazner                @test det(J, D) ≈ det(J)
20837fad103SWill Pazner                J = J + J' # make symmetric
20937fad103SWill Pazner                @test setvoigt(SMatrix{dim,dim}(J)) == setvoigt(J, D)
21037fad103SWill Pazner                @test getvoigt(setvoigt(J, D)) == J
21180a9ef05SNatalie Beams                V = zeros(CeedScalar, dim*(dim + 1)÷2)
21237fad103SWill Pazner                setvoigt!(V, J, D)
21337fad103SWill Pazner                @test V == setvoigt(J, D)
21480a9ef05SNatalie Beams                J2 = zeros(CeedScalar, dim, dim)
21537fad103SWill Pazner                getvoigt!(J2, V, D)
21637fad103SWill Pazner                @test J2 == J
21737fad103SWill Pazner            end
21837fad103SWill Pazner        end
21937fad103SWill Pazner
22037fad103SWill Pazner        @testset "Operator" begin
22137fad103SWill Pazner            c = Ceed()
22237fad103SWill Pazner            @interior_qf id = (
22337fad103SWill Pazner                c,
22437fad103SWill Pazner                (input, :in, EVAL_INTERP),
22537fad103SWill Pazner                (output, :out, EVAL_INTERP),
22637fad103SWill Pazner                begin
22737fad103SWill Pazner                    output[] = input
22837fad103SWill Pazner                end,
22937fad103SWill Pazner            )
23037fad103SWill Pazner            b = create_tensor_h1_lagrange_basis(c, 3, 1, 3, 3, GAUSS_LOBATTO)
23137fad103SWill Pazner            n = getnumnodes(b)
23237fad103SWill Pazner            offsets = Vector{CeedInt}(0:n-1)
23337fad103SWill Pazner            r = create_elem_restriction(c, 1, n, 1, 1, n, offsets)
23437fad103SWill Pazner            op = Operator(
23537fad103SWill Pazner                c;
23637fad103SWill Pazner                qf=id,
23737fad103SWill Pazner                fields=[
23837fad103SWill Pazner                    (:input, r, b, CeedVectorActive()),
23937fad103SWill Pazner                    (:output, r, b, CeedVectorActive()),
24037fad103SWill Pazner                ],
24137fad103SWill Pazner            )
24237fad103SWill Pazner
24380a9ef05SNatalie Beams            v = rand(CeedScalar, n)
24437fad103SWill Pazner            v1 = CeedVector(c, v)
24537fad103SWill Pazner            v2 = CeedVector(c, n)
24637fad103SWill Pazner            apply!(op, v1, v2)
24737fad103SWill Pazner            @test @witharray_read(a1 = v1, @witharray_read(a2 = v2, a1 == a2))
24837fad103SWill Pazner            apply_add!(op, v1, v2)
24937fad103SWill Pazner            @test @witharray_read(a1 = v1, @witharray_read(a2 = v2, a1 + a1 == a2))
25037fad103SWill Pazner
25137fad103SWill Pazner            diag_vector = create_lvector(r)
25237fad103SWill Pazner            LibCEED.assemble_diagonal!(op, diag_vector)
25337fad103SWill Pazner            @test @witharray_read(a = diag_vector, a == ones(n))
25437fad103SWill Pazner            # TODO: change this test after bug-fix in libCEED
25537fad103SWill Pazner            diag_vector[] = 0.0
25637fad103SWill Pazner            LibCEED.assemble_add_diagonal!(op, diag_vector)
25737fad103SWill Pazner            @test @witharray(a = diag_vector, a == fill(1.0, n))
25837fad103SWill Pazner
259bd9c22baSWill Pazner            @test showstr(op) == """
260bd9c22baSWill Pazner                CeedOperator
261bd9c22baSWill Pazner                  1 elements with 27 quadrature points each
262bd9c22baSWill Pazner                  2 fields
263bd9c22baSWill Pazner                  1 input field:
264bd9c22baSWill Pazner                    Input field 0:
265bd9c22baSWill Pazner                      Name: "input"
266bd9c22baSWill Pazner                      Size: 1
267bd9c22baSWill Pazner                      EvalMode: interpolation
268bd9c22baSWill Pazner                      Active vector
269bd9c22baSWill Pazner                  1 output field:
270bd9c22baSWill Pazner                    Output field 0:
271bd9c22baSWill Pazner                      Name: "output"
272bd9c22baSWill Pazner                      Size: 1
273bd9c22baSWill Pazner                      EvalMode: interpolation
274bd9c22baSWill Pazner                      Active vector"""
27537fad103SWill Pazner        end
27637fad103SWill Pazner
27737fad103SWill Pazner        @testset "ElemRestriction" begin
27837fad103SWill Pazner            c = Ceed()
27937fad103SWill Pazner            n = 10
28037fad103SWill Pazner            offsets = Vector{CeedInt}([0:n-1; n-1:2*n-2])
28137fad103SWill Pazner            lsize = 2*n - 1
28237fad103SWill Pazner            r = create_elem_restriction(c, 2, n, 1, lsize, lsize, offsets)
28337fad103SWill Pazner            @test getcompstride(r) == lsize
28437fad103SWill Pazner            @test getnumelements(r) == 2
28537fad103SWill Pazner            @test getelementsize(r) == n
28637fad103SWill Pazner            @test getlvectorsize(r) == lsize
28737fad103SWill Pazner            @test getnumcomponents(r) == 1
28837fad103SWill Pazner            @test length(create_lvector(r)) == lsize
28937fad103SWill Pazner            @test length(create_evector(r)) == 2*n
29037fad103SWill Pazner            lv, ev = create_vectors(r)
29137fad103SWill Pazner            @test length(lv) == lsize
29237fad103SWill Pazner            @test length(ev) == 2*n
29337fad103SWill Pazner            mult = getmultiplicity(r)
29437fad103SWill Pazner            mult2 = ones(lsize)
29537fad103SWill Pazner            mult2[n] = 2
29637fad103SWill Pazner            @test mult == mult2
29780a9ef05SNatalie Beams            rand_lv = rand(CeedScalar, lsize)
29837fad103SWill Pazner            rand_ev = [rand_lv[1:n]; rand_lv[n:end]]
29937fad103SWill Pazner            @test apply(r, rand_lv) == rand_ev
30037fad103SWill Pazner            @test apply(r, rand_ev; tmode=TRANSPOSE) == rand_lv.*mult
30137fad103SWill Pazner            @test showstr(r) == string(
30237fad103SWill Pazner                "CeedElemRestriction from (19, 1) to 2 elements ",
30337fad103SWill Pazner                "with 10 nodes each and component stride 19",
30437fad103SWill Pazner            )
30537fad103SWill Pazner
30637fad103SWill Pazner            strides = CeedInt[1, n, n]
30737fad103SWill Pazner            rs = create_elem_restriction_strided(c, 1, n, 1, n, strides)
30837fad103SWill Pazner            @test showstr(rs) == string(
30937fad103SWill Pazner                "CeedElemRestriction from (10, 1) to 1 elements ",
31037fad103SWill Pazner                "with 10 nodes each and strides [1, $n, $n]",
31137fad103SWill Pazner            )
31237fad103SWill Pazner
31337fad103SWill Pazner            @test ElemRestrictionNone()[] == LibCEED.C.CEED_ELEMRESTRICTION_NONE[]
31437fad103SWill Pazner        end
315bd9c22baSWill Pazner
316bd9c22baSWill Pazner        @testset "QFunction" begin
317bd9c22baSWill Pazner            c = Ceed()
318bd9c22baSWill Pazner            @test showstr(create_interior_qfunction(c, "Poisson3DApply")) == """
319bd9c22baSWill Pazner                 Gallery CeedQFunction - Poisson3DApply
320bd9c22baSWill Pazner                   2 input fields:
321bd9c22baSWill Pazner                     Input field 0:
322bd9c22baSWill Pazner                       Name: "du"
323bd9c22baSWill Pazner                       Size: 3
324bd9c22baSWill Pazner                       EvalMode: "gradient"
325bd9c22baSWill Pazner                     Input field 1:
326bd9c22baSWill Pazner                       Name: "qdata"
327bd9c22baSWill Pazner                       Size: 6
328bd9c22baSWill Pazner                       EvalMode: "none"
329bd9c22baSWill Pazner                   1 output field:
330bd9c22baSWill Pazner                     Output field 0:
331bd9c22baSWill Pazner                       Name: "dv"
332bd9c22baSWill Pazner                       Size: 3
333bd9c22baSWill Pazner                       EvalMode: "gradient\""""
334bd9c22baSWill Pazner
335bd9c22baSWill Pazner            id = create_identity_qfunction(c, 1, EVAL_INTERP, EVAL_INTERP)
336bd9c22baSWill Pazner            Q = 10
337bd9c22baSWill Pazner            v = rand(CeedScalar, Q)
338bd9c22baSWill Pazner            v1 = CeedVector(c, v)
339bd9c22baSWill Pazner            v2 = CeedVector(c, Q)
340bd9c22baSWill Pazner            apply!(id, Q, [v1], [v2])
341bd9c22baSWill Pazner            @test @witharray(a = v2, a == v)
342bd9c22baSWill Pazner
343bd9c22baSWill Pazner            @interior_qf id2 = (c, (a, :in, EVAL_INTERP), (b, :out, EVAL_INTERP), b .= a)
344bd9c22baSWill Pazner            v2[] = 0.0
345bd9c22baSWill Pazner            apply!(id2, Q, [v1], [v2])
346bd9c22baSWill Pazner            @test @witharray(a = v2, a == v)
347bd9c22baSWill Pazner
348bd9c22baSWill Pazner            ctxdata = CtxData(IOBuffer(), rand(CeedScalar, 3))
349bd9c22baSWill Pazner            ctx = Context(c, ctxdata)
350bd9c22baSWill Pazner            dim = 3
351bd9c22baSWill Pazner            @interior_qf qf = (
352bd9c22baSWill Pazner                c,
353bd9c22baSWill Pazner                dim=dim,
354bd9c22baSWill Pazner                ctxdata::CtxData,
355bd9c22baSWill Pazner                (a, :in, EVAL_GRAD, dim),
356bd9c22baSWill Pazner                (b, :in, EVAL_NONE),
357bd9c22baSWill Pazner                (c, :out, EVAL_INTERP),
358bd9c22baSWill Pazner                begin
359bd9c22baSWill Pazner                    c[] = b*sum(a)
360bd9c22baSWill Pazner                    show(ctxdata.io, MIME("text/plain"), ctxdata.x)
361bd9c22baSWill Pazner                end,
362bd9c22baSWill Pazner            )
363bd9c22baSWill Pazner            set_context!(qf, ctx)
364bd9c22baSWill Pazner            in_sz, out_sz = LibCEED.get_field_sizes(qf)
365bd9c22baSWill Pazner            @test in_sz == [dim, 1]
366bd9c22baSWill Pazner            @test out_sz == [1]
367bd9c22baSWill Pazner            v1 = rand(CeedScalar, dim)
368bd9c22baSWill Pazner            v2 = rand(CeedScalar, 1)
369bd9c22baSWill Pazner            cv1 = CeedVector(c, v1)
370bd9c22baSWill Pazner            cv2 = CeedVector(c, v2)
371bd9c22baSWill Pazner            cv3 = CeedVector(c, 1)
372bd9c22baSWill Pazner            apply!(qf, 1, [cv1, cv2], [cv3])
373bd9c22baSWill Pazner            @test String(take!(ctxdata.io)) == showstr(ctxdata.x)
374bd9c22baSWill Pazner            @test @witharray_read(v3 = cv3, v3[1] == v2[1]*sum(v1))
375bd9c22baSWill Pazner
376bd9c22baSWill Pazner            @test QFunctionNone()[] == LibCEED.C.CEED_QFUNCTION_NONE[]
377bd9c22baSWill Pazner        end
378*77bb289aSJed Brown        @testset "Basis" begin
379*77bb289aSJed Brown            @test BasisNone()[] == LibCEED.C.CEED_BASIS_NONE[]
380*77bb289aSJed Brown
381*77bb289aSJed Brown            c = Ceed()
382*77bb289aSJed Brown            dim = 3
383*77bb289aSJed Brown            ncomp = 1
384*77bb289aSJed Brown            p = 4
385*77bb289aSJed Brown            q = 6
386*77bb289aSJed Brown            b1 = create_tensor_h1_lagrange_basis(c, dim, ncomp, p, q, GAUSS_LOBATTO)
387*77bb289aSJed Brown
388*77bb289aSJed Brown            @test checkoutput(showstr(b1), "b1.out")
389*77bb289aSJed Brown
390*77bb289aSJed Brown            b1d = CeedScalar[1.0 0.0; 0.5 0.5; 0.0 1.0]
391*77bb289aSJed Brown            d1d = CeedScalar[-0.5 0.5; -0.5 0.5; -0.5 0.5]
392*77bb289aSJed Brown            q1d = CeedScalar[-1.0, 0.0, 1.0]
393*77bb289aSJed Brown            w1d = CeedScalar[1/3, 4/3, 1/3]
394*77bb289aSJed Brown            q, p = size(b1d)
395*77bb289aSJed Brown            d2d = zeros(CeedScalar, 2, q*q, p*p)
396*77bb289aSJed Brown            d2d[1, :, :] = kron(b1d, d1d)
397*77bb289aSJed Brown            d2d[2, :, :] = kron(d1d, b1d)
398*77bb289aSJed Brown
399*77bb289aSJed Brown            dim2 = 2
400*77bb289aSJed Brown            b2 = create_tensor_h1_basis(c, dim2, 1, p, q, b1d, d1d, q1d, w1d)
401*77bb289aSJed Brown            @test checkoutput(showstr(b2), "b2.out")
402*77bb289aSJed Brown
403*77bb289aSJed Brown            b3 = create_h1_basis(
404*77bb289aSJed Brown                c,
405*77bb289aSJed Brown                LINE,
406*77bb289aSJed Brown                1,
407*77bb289aSJed Brown                p,
408*77bb289aSJed Brown                q,
409*77bb289aSJed Brown                b1d,
410*77bb289aSJed Brown                reshape(d1d, 1, q, p),
411*77bb289aSJed Brown                reshape(q1d, 1, q),
412*77bb289aSJed Brown                w1d,
413*77bb289aSJed Brown            )
414*77bb289aSJed Brown            @test checkoutput(showstr(b3), "b3.out")
415*77bb289aSJed Brown
416*77bb289aSJed Brown            dim = 2
417*77bb289aSJed Brown            ncomp = 1
418*77bb289aSJed Brown            p1 = 4
419*77bb289aSJed Brown            q1 = 4
420*77bb289aSJed Brown            qref1 = Array{Float64}(undef, dim, q1)
421*77bb289aSJed Brown            qweight1 = Array{Float64}(undef, q1)
422*77bb289aSJed Brown            interp1, div1 = build_mats_hdiv(qref1, qweight1)
423*77bb289aSJed Brown            b1 = create_hdiv_basis(c, QUAD, ncomp, p1, q1, interp1, div1, qref1, qweight1)
424*77bb289aSJed Brown
425*77bb289aSJed Brown            u1 = ones(Float64, p1)
426*77bb289aSJed Brown            v1 = apply(b1, u1)
427*77bb289aSJed Brown
428*77bb289aSJed Brown            for i = 1:q1
429*77bb289aSJed Brown                @test v1[i] ≈ -1.0
430*77bb289aSJed Brown                @test v1[q1+i] ≈ 1.0
431*77bb289aSJed Brown            end
432*77bb289aSJed Brown
433*77bb289aSJed Brown            p2 = 3
434*77bb289aSJed Brown            q2 = 4
435*77bb289aSJed Brown            qref2 = Array{Float64}(undef, dim, q2)
436*77bb289aSJed Brown            qweight2 = Array{Float64}(undef, q2)
437*77bb289aSJed Brown            interp2, curl2 = build_mats_hcurl(qref2, qweight2)
438*77bb289aSJed Brown            b2 = create_hcurl_basis(
439*77bb289aSJed Brown                c,
440*77bb289aSJed Brown                TRIANGLE,
441*77bb289aSJed Brown                ncomp,
442*77bb289aSJed Brown                p2,
443*77bb289aSJed Brown                q2,
444*77bb289aSJed Brown                interp2,
445*77bb289aSJed Brown                curl2,
446*77bb289aSJed Brown                qref2,
447*77bb289aSJed Brown                qweight2,
448*77bb289aSJed Brown            )
449*77bb289aSJed Brown
450*77bb289aSJed Brown            u2 = [1.0, 2.0, 1.0]
451*77bb289aSJed Brown            v2 = apply(b2, u2)
452*77bb289aSJed Brown
453*77bb289aSJed Brown            for i = 1:q2
454*77bb289aSJed Brown                @test v2[i] ≈ 1.0
455*77bb289aSJed Brown            end
456*77bb289aSJed Brown
457*77bb289aSJed Brown            u2[1] = -1.0
458*77bb289aSJed Brown            u2[2] = 1.0
459*77bb289aSJed Brown            u2[3] = 2.0
460*77bb289aSJed Brown            v2 = apply(b2, u2)
461*77bb289aSJed Brown
462*77bb289aSJed Brown            for i = 1:q2
463*77bb289aSJed Brown                @test v2[q2+i] ≈ 1.0
464*77bb289aSJed Brown            end
465*77bb289aSJed Brown        end
466*77bb289aSJed Brown
467*77bb289aSJed Brown        @testset "ElemRestriction" begin
468*77bb289aSJed Brown            c = Ceed()
469*77bb289aSJed Brown            nelem = 3
470*77bb289aSJed Brown            elemsize = 2
471*77bb289aSJed Brown            offsets = Array{CeedInt}(undef, elemsize, nelem)
472*77bb289aSJed Brown            orients = Array{Bool}(undef, elemsize, nelem)
473*77bb289aSJed Brown            for i = 1:nelem
474*77bb289aSJed Brown                offsets[1, i] = i - 1
475*77bb289aSJed Brown                offsets[2, i] = i
476*77bb289aSJed Brown                # flip the dofs on element 1, 3, ...
477*77bb289aSJed Brown                orients[1, i] = (i - 1)%2 > 0
478*77bb289aSJed Brown                orients[2, i] = (i - 1)%2 > 0
479*77bb289aSJed Brown            end
480*77bb289aSJed Brown            r = create_elem_restriction_oriented(
481*77bb289aSJed Brown                c,
482*77bb289aSJed Brown                nelem,
483*77bb289aSJed Brown                elemsize,
484*77bb289aSJed Brown                1,
485*77bb289aSJed Brown                1,
486*77bb289aSJed Brown                nelem + 1,
487*77bb289aSJed Brown                offsets,
488*77bb289aSJed Brown                orients,
489*77bb289aSJed Brown            )
490*77bb289aSJed Brown
491*77bb289aSJed Brown            lv = Vector{CeedScalar}(undef, nelem + 1)
492*77bb289aSJed Brown            for i = 1:nelem+1
493*77bb289aSJed Brown                lv[i] = 10 + i - 1
494*77bb289aSJed Brown            end
495*77bb289aSJed Brown
496*77bb289aSJed Brown            ev = apply(r, lv)
497*77bb289aSJed Brown
498*77bb289aSJed Brown            for i = 1:nelem
499*77bb289aSJed Brown                for j = 1:elemsize
500*77bb289aSJed Brown                    k = j + elemsize*(i - 1)
501*77bb289aSJed Brown                    @test 10 + k÷2 == ev[k]*(-1)^((i - 1)%2)
502*77bb289aSJed Brown                end
503*77bb289aSJed Brown            end
504*77bb289aSJed Brown
505*77bb289aSJed Brown            curlorients = Array{CeedInt8}(undef, 3*elemsize, nelem)
506*77bb289aSJed Brown            for i = 1:nelem
507*77bb289aSJed Brown                curlorients[1, i] = curlorients[6, i] = 0
508*77bb289aSJed Brown                if (i - 1)%2 > 0
509*77bb289aSJed Brown                    # T = [0  -1]
510*77bb289aSJed Brown                    #     [-1  0]
511*77bb289aSJed Brown                    curlorients[2, i] = 0
512*77bb289aSJed Brown                    curlorients[3, i] = -1
513*77bb289aSJed Brown                    curlorients[4, i] = -1
514*77bb289aSJed Brown                    curlorients[5, i] = 0
515*77bb289aSJed Brown                else
516*77bb289aSJed Brown                    # T = I
517*77bb289aSJed Brown                    curlorients[2, i] = 1
518*77bb289aSJed Brown                    curlorients[3, i] = 0
519*77bb289aSJed Brown                    curlorients[4, i] = 0
520*77bb289aSJed Brown                    curlorients[5, i] = 1
521*77bb289aSJed Brown                end
522*77bb289aSJed Brown            end
523*77bb289aSJed Brown            r = create_elem_restriction_curl_oriented(
524*77bb289aSJed Brown                c,
525*77bb289aSJed Brown                nelem,
526*77bb289aSJed Brown                elemsize,
527*77bb289aSJed Brown                1,
528*77bb289aSJed Brown                1,
529*77bb289aSJed Brown                nelem + 1,
530*77bb289aSJed Brown                offsets,
531*77bb289aSJed Brown                curlorients,
532*77bb289aSJed Brown            )
533*77bb289aSJed Brown
534*77bb289aSJed Brown            ev = apply(r, lv)
535*77bb289aSJed Brown
536*77bb289aSJed Brown            for i = 1:nelem
537*77bb289aSJed Brown                for j = 1:elemsize
538*77bb289aSJed Brown                    k = j + elemsize*(i - 1)
539*77bb289aSJed Brown                    if (i - 1)%2 > 0
540*77bb289aSJed Brown                        @test j == 2 || 10 + i == -ev[k]
541*77bb289aSJed Brown                        @test j == 1 || 10 + i - 1 == -ev[k]
542*77bb289aSJed Brown                    else
543*77bb289aSJed Brown                        @test 10 + k÷2 == ev[k]
544*77bb289aSJed Brown                    end
545*77bb289aSJed Brown                end
546*77bb289aSJed Brown            end
547*77bb289aSJed Brown        end
54837fad103SWill Pazner    end
549f99607bdSWill Paznerend
550