xref: /libCEED/julia/LibCEED.jl/test/runtests.jl (revision 37fad103dc80356d29612d88537158f0d6682656)
1*37fad103SWill Paznerusing Test, LibCEED, LinearAlgebra, StaticArrays
2*37fad103SWill Pazner
3*37fad103SWill Paznerfunction iostr(f, x)
4*37fad103SWill Pazner    io = IOBuffer()
5*37fad103SWill Pazner    f(io, x)
6*37fad103SWill Pazner    String(take!(io))
7*37fad103SWill Paznerend
8*37fad103SWill Paznerfunction showstr(x)
9*37fad103SWill Pazner    iostr(x) do io, y
10*37fad103SWill Pazner        show(io, MIME("text/plain"), y)
11*37fad103SWill Pazner    end
12*37fad103SWill Paznerend
13*37fad103SWill Paznersummarystr(x) = iostr(summary, x)
14*37fad103SWill Paznergetoutput(fname) = chomp(read(joinpath(@__DIR__, "output", fname), String))
15*37fad103SWill Pazner
16*37fad103SWill Paznermutable struct CtxData
17*37fad103SWill Pazner    io::IOBuffer
18*37fad103SWill Pazner    x::Vector{Float64}
19*37fad103SWill Paznerend
20*37fad103SWill Pazner
21*37fad103SWill Pazner@testset "LibCEED" begin
22*37fad103SWill Pazner    @testset "Ceed" begin
23*37fad103SWill Pazner        res = "/cpu/self/ref/serial"
24*37fad103SWill Pazner        c = Ceed(res)
25*37fad103SWill Pazner        @test isdeterministic(c)
26*37fad103SWill Pazner        @test getresource(c) == res
27*37fad103SWill Pazner        @test !iscuda(c)
28*37fad103SWill Pazner        @test get_preferred_memtype(c) == MEM_HOST
29*37fad103SWill Pazner        @test_throws LibCEED.CeedError create_interior_qfunction(c, "")
30*37fad103SWill Pazner        @test showstr(c) == """
31*37fad103SWill Pazner            Ceed
32*37fad103SWill Pazner              Ceed Resource: $res
33*37fad103SWill Pazner              Preferred MemType: host"""
34*37fad103SWill Pazner    end
35*37fad103SWill Pazner
36*37fad103SWill Pazner    @testset "Context" begin
37*37fad103SWill Pazner        c = Ceed()
38*37fad103SWill Pazner        data = zeros(3)
39*37fad103SWill Pazner        ctx = Context(c, data)
40*37fad103SWill Pazner        @test showstr(ctx) == """
41*37fad103SWill Pazner            CeedQFunctionContext
42*37fad103SWill Pazner              Context Data Size: $(sizeof(data))"""
43*37fad103SWill Pazner        @test_throws Exception set_data!(ctx, MEM_HOST, OWN_POINTER, data)
44*37fad103SWill Pazner    end
45*37fad103SWill Pazner
46*37fad103SWill Pazner    @testset "CeedVector" begin
47*37fad103SWill Pazner        n = 10
48*37fad103SWill Pazner        c = Ceed()
49*37fad103SWill Pazner        v = CeedVector(c, n)
50*37fad103SWill Pazner        @test size(v) == (n,)
51*37fad103SWill Pazner        @test length(v) == n
52*37fad103SWill Pazner        @test axes(v) == (1:n,)
53*37fad103SWill Pazner        @test ndims(v) == 1
54*37fad103SWill Pazner        @test ndims(CeedVector) == 1
55*37fad103SWill Pazner
56*37fad103SWill Pazner        v[] = 0.0
57*37fad103SWill Pazner        @test @witharray(a = v, all(a .== 0.0))
58*37fad103SWill Pazner
59*37fad103SWill Pazner        v1 = rand(n)
60*37fad103SWill Pazner        v2 = CeedVector(c, v1)
61*37fad103SWill Pazner        @test @witharray_read(a = v2, mtype = MEM_HOST, a == v1)
62*37fad103SWill Pazner        @test Vector(v2) == v1
63*37fad103SWill Pazner        v[] = v1
64*37fad103SWill Pazner        for p ∈ [1, 2, Inf]
65*37fad103SWill Pazner            @test norm(v, p) ≈ norm(v1, p)
66*37fad103SWill Pazner        end
67*37fad103SWill Pazner        @test_throws Exception norm(v, 3)
68*37fad103SWill Pazner        @test witharray_read(sum, v) == sum(v1)
69*37fad103SWill Pazner        reciprocal!(v)
70*37fad103SWill Pazner        @test @witharray(a = v, mtype = MEM_HOST, all(a .== 1.0 ./ v1))
71*37fad103SWill Pazner
72*37fad103SWill Pazner        witharray(x -> x .= 1.0, v)
73*37fad103SWill Pazner        @test @witharray(a = v, all(a .== 1.0))
74*37fad103SWill Pazner
75*37fad103SWill Pazner        @test summarystr(v) == "$n-element CeedVector"
76*37fad103SWill Pazner        @test iostr(show, v) == @witharray_read(a = v, iostr(show, a))
77*37fad103SWill Pazner        io = IOBuffer()
78*37fad103SWill Pazner        summary(io, v)
79*37fad103SWill Pazner        println(io, ":")
80*37fad103SWill Pazner        @witharray_read(a = v, Base.print_array(io, a))
81*37fad103SWill Pazner        s1 = String(take!(io))
82*37fad103SWill Pazner        @test showstr(v) == s1
83*37fad103SWill Pazner
84*37fad103SWill Pazner        setarray!(v, MEM_HOST, USE_POINTER, v1)
85*37fad103SWill Pazner        syncarray!(v, MEM_HOST)
86*37fad103SWill Pazner        @test @witharray_read(a = v, a == v1)
87*37fad103SWill Pazner        p = takearray!(v, MEM_HOST)
88*37fad103SWill Pazner        @test p == pointer(v1)
89*37fad103SWill Pazner
90*37fad103SWill Pazner        m = rand(10, 10)
91*37fad103SWill Pazner        vm = CeedVector(c, vec(m))
92*37fad103SWill Pazner        @test @witharray_read(a = vm, size = size(m), a == m)
93*37fad103SWill Pazner
94*37fad103SWill Pazner        @test CeedVectorActive()[] == LibCEED.C.CEED_VECTOR_ACTIVE[]
95*37fad103SWill Pazner        @test CeedVectorNone()[] == LibCEED.C.CEED_VECTOR_NONE[]
96*37fad103SWill Pazner    end
97*37fad103SWill Pazner
98*37fad103SWill Pazner    @testset "Basis" begin
99*37fad103SWill Pazner        c = Ceed()
100*37fad103SWill Pazner        dim = 3
101*37fad103SWill Pazner        ncomp = 1
102*37fad103SWill Pazner        p = 4
103*37fad103SWill Pazner        q = 6
104*37fad103SWill Pazner        b1 = create_tensor_h1_lagrange_basis(c, dim, ncomp, p, q, GAUSS_LOBATTO)
105*37fad103SWill Pazner
106*37fad103SWill Pazner        @test showstr(b1) == getoutput("b1.out")
107*37fad103SWill Pazner        @test getdimension(b1) == 3
108*37fad103SWill Pazner        @test gettopology(b1) == HEX
109*37fad103SWill Pazner        @test getnumcomponents(b1) == ncomp
110*37fad103SWill Pazner        @test getnumnodes(b1) == p^dim
111*37fad103SWill Pazner        @test getnumnodes1d(b1) == p
112*37fad103SWill Pazner        @test getnumqpts(b1) == q^dim
113*37fad103SWill Pazner        @test getnumqpts1d(b1) == q
114*37fad103SWill Pazner
115*37fad103SWill Pazner        q1d, w1d = lobatto_quadrature(3, AbscissaAndWeights)
116*37fad103SWill Pazner        @test q1d ≈ [-1.0, 0.0, 1.0]
117*37fad103SWill Pazner        @test w1d ≈ [1/3, 4/3, 1/3]
118*37fad103SWill Pazner
119*37fad103SWill Pazner        q1d, w1d = gauss_quadrature(3)
120*37fad103SWill Pazner        @test q1d ≈ [-sqrt(3/5), 0.0, sqrt(3/5)]
121*37fad103SWill Pazner        @test w1d ≈ [5/9, 8/9, 5/9]
122*37fad103SWill Pazner
123*37fad103SWill Pazner        b1d = [1.0 0.0; 0.5 0.5; 0.0 1.0]
124*37fad103SWill Pazner        d1d = [-0.5 0.5; -0.5 0.5; -0.5 0.5]
125*37fad103SWill Pazner        q1d = [-1.0, 0.0, 1.0]
126*37fad103SWill Pazner        w1d = [1/3, 4/3, 1/3]
127*37fad103SWill Pazner        q, p = size(b1d)
128*37fad103SWill Pazner        d2d = zeros(2, q*q, p*p)
129*37fad103SWill Pazner        d2d[1, :, :] = kron(b1d, d1d)
130*37fad103SWill Pazner        d2d[2, :, :] = kron(d1d, b1d)
131*37fad103SWill Pazner
132*37fad103SWill Pazner        dim2 = 2
133*37fad103SWill Pazner        b2 = create_tensor_h1_basis(c, dim2, 1, p, q, b1d, d1d, q1d, w1d)
134*37fad103SWill Pazner        @test getinterp(b2) == kron(b1d, b1d)
135*37fad103SWill Pazner        @test getinterp1d(b2) == b1d
136*37fad103SWill Pazner        @test getgrad(b2) == d2d
137*37fad103SWill Pazner        @test getgrad1d(b2) == d1d
138*37fad103SWill Pazner        @test showstr(b2) == getoutput("b2.out")
139*37fad103SWill Pazner
140*37fad103SWill Pazner        b3 = create_h1_basis(c, LINE, 1, p, q, b1d, reshape(d1d, 1, q, p), q1d, w1d)
141*37fad103SWill Pazner        @test getqref(b3) == q1d
142*37fad103SWill Pazner        @test getqweights(b3) == w1d
143*37fad103SWill Pazner        @test showstr(b3) == getoutput("b3.out")
144*37fad103SWill Pazner
145*37fad103SWill Pazner        v = rand(2)
146*37fad103SWill Pazner        vq = apply(b3, v)
147*37fad103SWill Pazner        vd = apply(b3, v; emode=EVAL_GRAD)
148*37fad103SWill Pazner        @test vq ≈ b1d*v
149*37fad103SWill Pazner        @test vd ≈ d1d*v
150*37fad103SWill Pazner
151*37fad103SWill Pazner        @test BasisCollocated()[] == LibCEED.C.CEED_BASIS_COLLOCATED[]
152*37fad103SWill Pazner    end
153*37fad103SWill Pazner
154*37fad103SWill Pazner    @testset "Request" begin
155*37fad103SWill Pazner        @test RequestImmediate()[] == LibCEED.C.CEED_REQUEST_IMMEDIATE[]
156*37fad103SWill Pazner        @test RequestOrdered()[] == LibCEED.C.CEED_REQUEST_ORDERED[]
157*37fad103SWill Pazner    end
158*37fad103SWill Pazner
159*37fad103SWill Pazner    @testset "Misc" begin
160*37fad103SWill Pazner        for dim = 1:3
161*37fad103SWill Pazner            D = CeedDim(dim)
162*37fad103SWill Pazner            J = rand(dim, dim)
163*37fad103SWill Pazner            @test det(J, D) ≈ det(J)
164*37fad103SWill Pazner            J = J + J' # make symmetric
165*37fad103SWill Pazner            @test setvoigt(SMatrix{dim,dim}(J)) == setvoigt(J, D)
166*37fad103SWill Pazner            @test getvoigt(setvoigt(J, D)) == J
167*37fad103SWill Pazner            V = zeros(dim*(dim + 1)÷2)
168*37fad103SWill Pazner            setvoigt!(V, J, D)
169*37fad103SWill Pazner            @test V == setvoigt(J, D)
170*37fad103SWill Pazner            J2 = zeros(dim, dim)
171*37fad103SWill Pazner            getvoigt!(J2, V, D)
172*37fad103SWill Pazner            @test J2 == J
173*37fad103SWill Pazner        end
174*37fad103SWill Pazner    end
175*37fad103SWill Pazner
176*37fad103SWill Pazner    @testset "QFunction" begin
177*37fad103SWill Pazner        c = Ceed()
178*37fad103SWill Pazner
179*37fad103SWill Pazner        id = create_identity_qfunction(c, 1, EVAL_INTERP, EVAL_INTERP)
180*37fad103SWill Pazner        Q = 10
181*37fad103SWill Pazner        v = rand(Q)
182*37fad103SWill Pazner        v1 = CeedVector(c, v)
183*37fad103SWill Pazner        v2 = CeedVector(c, Q)
184*37fad103SWill Pazner        apply!(id, Q, [v1], [v2])
185*37fad103SWill Pazner        @test @witharray(a = v2, a == v)
186*37fad103SWill Pazner
187*37fad103SWill Pazner        @test showstr(create_interior_qfunction(c, "Poisson3DApply")) == """
188*37fad103SWill Pazner            Gallery CeedQFunction Poisson3DApply
189*37fad103SWill Pazner              2 Input Fields:
190*37fad103SWill Pazner                Input Field [0]:
191*37fad103SWill Pazner                  Name: "du"
192*37fad103SWill Pazner                  Size: 3
193*37fad103SWill Pazner                  EvalMode: "gradient"
194*37fad103SWill Pazner                Input Field [1]:
195*37fad103SWill Pazner                  Name: "qdata"
196*37fad103SWill Pazner                  Size: 6
197*37fad103SWill Pazner                  EvalMode: "none"
198*37fad103SWill Pazner              1 Output Field:
199*37fad103SWill Pazner                Output Field [0]:
200*37fad103SWill Pazner                  Name: "dv"
201*37fad103SWill Pazner                  Size: 3
202*37fad103SWill Pazner                  EvalMode: "gradient\""""
203*37fad103SWill Pazner
204*37fad103SWill Pazner        @interior_qf id2 = (c, (a, :in, EVAL_INTERP), (b, :out, EVAL_INTERP), b.=a)
205*37fad103SWill Pazner        v2[] = 0.0
206*37fad103SWill Pazner        apply!(id2, Q, [v1], [v2])
207*37fad103SWill Pazner        @test @witharray(a = v2, a == v)
208*37fad103SWill Pazner
209*37fad103SWill Pazner        ctxdata = CtxData(IOBuffer(), rand(3))
210*37fad103SWill Pazner        ctx = Context(c, ctxdata)
211*37fad103SWill Pazner        dim = 3
212*37fad103SWill Pazner        @interior_qf qf = (
213*37fad103SWill Pazner            c,
214*37fad103SWill Pazner            dim=dim,
215*37fad103SWill Pazner            ctxdata::CtxData,
216*37fad103SWill Pazner            (a, :in, EVAL_GRAD, dim),
217*37fad103SWill Pazner            (b, :in, EVAL_NONE),
218*37fad103SWill Pazner            (c, :out, EVAL_INTERP),
219*37fad103SWill Pazner            begin
220*37fad103SWill Pazner                c[] = b*sum(a)
221*37fad103SWill Pazner                show(ctxdata.io, MIME("text/plain"), ctxdata.x)
222*37fad103SWill Pazner            end,
223*37fad103SWill Pazner        )
224*37fad103SWill Pazner        set_context!(qf, ctx)
225*37fad103SWill Pazner        in_sz, out_sz = LibCEED.get_field_sizes(qf)
226*37fad103SWill Pazner        @test in_sz == [dim, 1]
227*37fad103SWill Pazner        @test out_sz == [1]
228*37fad103SWill Pazner        v1 = rand(dim)
229*37fad103SWill Pazner        v2 = rand(1)
230*37fad103SWill Pazner        cv1 = CeedVector(c, v1)
231*37fad103SWill Pazner        cv2 = CeedVector(c, v2)
232*37fad103SWill Pazner        cv3 = CeedVector(c, 1)
233*37fad103SWill Pazner        apply!(qf, 1, [cv1, cv2], [cv3])
234*37fad103SWill Pazner        @test String(take!(ctxdata.io)) == showstr(ctxdata.x)
235*37fad103SWill Pazner        @test @witharray_read(v3 = cv3, v3[1] == v2[1]*sum(v1))
236*37fad103SWill Pazner
237*37fad103SWill Pazner        @test QFunctionNone()[] == LibCEED.C.CEED_QFUNCTION_NONE[]
238*37fad103SWill Pazner    end
239*37fad103SWill Pazner
240*37fad103SWill Pazner    @testset "Operator" begin
241*37fad103SWill Pazner        c = Ceed()
242*37fad103SWill Pazner        @interior_qf id = (
243*37fad103SWill Pazner            c,
244*37fad103SWill Pazner            (input, :in, EVAL_INTERP),
245*37fad103SWill Pazner            (output, :out, EVAL_INTERP),
246*37fad103SWill Pazner            begin
247*37fad103SWill Pazner                output[] = input
248*37fad103SWill Pazner            end,
249*37fad103SWill Pazner        )
250*37fad103SWill Pazner        b = create_tensor_h1_lagrange_basis(c, 3, 1, 3, 3, GAUSS_LOBATTO)
251*37fad103SWill Pazner        n = getnumnodes(b)
252*37fad103SWill Pazner        offsets = Vector{CeedInt}(0:n-1)
253*37fad103SWill Pazner        r = create_elem_restriction(c, 1, n, 1, 1, n, offsets)
254*37fad103SWill Pazner        op = Operator(
255*37fad103SWill Pazner            c;
256*37fad103SWill Pazner            qf=id,
257*37fad103SWill Pazner            fields=[
258*37fad103SWill Pazner                (:input, r, b, CeedVectorActive()),
259*37fad103SWill Pazner                (:output, r, b, CeedVectorActive()),
260*37fad103SWill Pazner            ],
261*37fad103SWill Pazner        )
262*37fad103SWill Pazner        @test showstr(op) == """
263*37fad103SWill Pazner            CeedOperator
264*37fad103SWill Pazner              2 Fields
265*37fad103SWill Pazner              1 Input Field:
266*37fad103SWill Pazner                Input Field [0]:
267*37fad103SWill Pazner                  Name: "input"
268*37fad103SWill Pazner                  Active vector
269*37fad103SWill Pazner              1 Output Field:
270*37fad103SWill Pazner                Output Field [0]:
271*37fad103SWill Pazner                  Name: "output"
272*37fad103SWill Pazner                  Active vector"""
273*37fad103SWill Pazner
274*37fad103SWill Pazner        v = rand(n)
275*37fad103SWill Pazner        v1 = CeedVector(c, v)
276*37fad103SWill Pazner        v2 = CeedVector(c, n)
277*37fad103SWill Pazner        apply!(op, v1, v2)
278*37fad103SWill Pazner        @test @witharray_read(a1 = v1, @witharray_read(a2 = v2, a1 == a2))
279*37fad103SWill Pazner        apply_add!(op, v1, v2)
280*37fad103SWill Pazner        @test @witharray_read(a1 = v1, @witharray_read(a2 = v2, a1 + a1 == a2))
281*37fad103SWill Pazner
282*37fad103SWill Pazner        diag_vector = create_lvector(r)
283*37fad103SWill Pazner        LibCEED.assemble_diagonal!(op, diag_vector)
284*37fad103SWill Pazner        @test @witharray_read(a = diag_vector, a == ones(n))
285*37fad103SWill Pazner        # TODO: change this test after bug-fix in libCEED
286*37fad103SWill Pazner        diag_vector[] = 0.0
287*37fad103SWill Pazner        LibCEED.assemble_add_diagonal!(op, diag_vector)
288*37fad103SWill Pazner        @test @witharray(a = diag_vector, a == fill(1.0, n))
289*37fad103SWill Pazner
290*37fad103SWill Pazner        comp_op = create_composite_operator(c, [op])
291*37fad103SWill Pazner        apply!(comp_op, v1, v2)
292*37fad103SWill Pazner        @test @witharray_read(a1 = v1, @witharray_read(a2 = v2, a1 == a2))
293*37fad103SWill Pazner    end
294*37fad103SWill Pazner
295*37fad103SWill Pazner    @testset "ElemRestriction" begin
296*37fad103SWill Pazner        c = Ceed()
297*37fad103SWill Pazner        n = 10
298*37fad103SWill Pazner        offsets = Vector{CeedInt}([0:n-1; n-1:2*n-2])
299*37fad103SWill Pazner        lsize = 2*n - 1
300*37fad103SWill Pazner        r = create_elem_restriction(c, 2, n, 1, lsize, lsize, offsets)
301*37fad103SWill Pazner        @test getcompstride(r) == lsize
302*37fad103SWill Pazner        @test getnumelements(r) == 2
303*37fad103SWill Pazner        @test getelementsize(r) == n
304*37fad103SWill Pazner        @test getlvectorsize(r) == lsize
305*37fad103SWill Pazner        @test getnumcomponents(r) == 1
306*37fad103SWill Pazner        @test length(create_lvector(r)) == lsize
307*37fad103SWill Pazner        @test length(create_evector(r)) == 2*n
308*37fad103SWill Pazner        lv, ev = create_vectors(r)
309*37fad103SWill Pazner        @test length(lv) == lsize
310*37fad103SWill Pazner        @test length(ev) == 2*n
311*37fad103SWill Pazner        mult = getmultiplicity(r)
312*37fad103SWill Pazner        mult2 = ones(lsize)
313*37fad103SWill Pazner        mult2[n] = 2
314*37fad103SWill Pazner        @test mult == mult2
315*37fad103SWill Pazner        rand_lv = rand(lsize)
316*37fad103SWill Pazner        rand_ev = [rand_lv[1:n]; rand_lv[n:end]]
317*37fad103SWill Pazner        @test apply(r, rand_lv) == rand_ev
318*37fad103SWill Pazner        @test apply(r, rand_ev; tmode=TRANSPOSE) == rand_lv.*mult
319*37fad103SWill Pazner        @test showstr(r) == string(
320*37fad103SWill Pazner            "CeedElemRestriction from (19, 1) to 2 elements ",
321*37fad103SWill Pazner            "with 10 nodes each and component stride 19",
322*37fad103SWill Pazner        )
323*37fad103SWill Pazner
324*37fad103SWill Pazner        strides = CeedInt[1, n, n]
325*37fad103SWill Pazner        rs = create_elem_restriction_strided(c, 1, n, 1, n, strides)
326*37fad103SWill Pazner        @test showstr(rs) == string(
327*37fad103SWill Pazner            "CeedElemRestriction from (10, 1) to 1 elements ",
328*37fad103SWill Pazner            "with 10 nodes each and strides [1, $n, $n]",
329*37fad103SWill Pazner        )
330*37fad103SWill Pazner
331*37fad103SWill Pazner        @test ElemRestrictionNone()[] == LibCEED.C.CEED_ELEMRESTRICTION_NONE[]
332*37fad103SWill Pazner    end
333*37fad103SWill Paznerend
334