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