16cf3b68dSWill Paznerusing LibCEED.C, Printf, UnsafeArrays 26cf3b68dSWill Paznerusing LibCEED.C: CeedInt, CeedScalar 36cf3b68dSWill Pazner 46cf3b68dSWill Pazner# A structure used to pass additional data to f_build_mass 56cf3b68dSWill Paznermutable struct BuildContextC 66cf3b68dSWill Pazner dim::CeedInt 76cf3b68dSWill Pazner space_dim::CeedInt 86cf3b68dSWill Paznerend 96cf3b68dSWill Pazner 106cf3b68dSWill Pazner# libCEED Q-function for building quadrature data for a mass operator 116cf3b68dSWill Paznerfunction f_build_mass_c( 126cf3b68dSWill Pazner ctx_ptr::Ptr{Cvoid}, 136cf3b68dSWill Pazner Q::CeedInt, 146cf3b68dSWill Pazner in_ptr::Ptr{Ptr{CeedScalar}}, 156cf3b68dSWill Pazner out_ptr::Ptr{Ptr{CeedScalar}}, 166cf3b68dSWill Pazner) 176cf3b68dSWill Pazner # in[0] is Jacobians with shape [dim, nc=dim, Q] 186cf3b68dSWill Pazner # in[1] is quadrature weights, size (Q) 196cf3b68dSWill Pazner ctx = unsafe_load(Ptr{BuildContextC}(ctx_ptr)) 206cf3b68dSWill Pazner J = UnsafeArray(unsafe_load(in_ptr, 1), (Int(Q), Int(ctx.dim^2))) 216cf3b68dSWill Pazner w = UnsafeArray(unsafe_load(in_ptr, 2), (Int(Q),)) 226cf3b68dSWill Pazner qdata = UnsafeArray(unsafe_load(out_ptr, 1), (Int(Q),)) 236cf3b68dSWill Pazner if ctx.dim == 1 246cf3b68dSWill Pazner @inbounds @simd for i = 1:Q 256cf3b68dSWill Pazner qdata[i] = J[i]*w[i] 266cf3b68dSWill Pazner end 276cf3b68dSWill Pazner elseif ctx.dim == 2 286cf3b68dSWill Pazner @inbounds @simd for i = 1:Q 296cf3b68dSWill Pazner qdata[i] = (J[i, 1]*J[i, 4] - J[i, 2]*J[i, 3])*w[i] 306cf3b68dSWill Pazner end 316cf3b68dSWill Pazner elseif ctx.dim == 3 326cf3b68dSWill Pazner @inbounds @simd for i = 1:Q 336cf3b68dSWill Pazner qdata[i] = 346cf3b68dSWill Pazner ( 356cf3b68dSWill Pazner J[i, 1]*(J[i, 5]*J[i, 9] - J[i, 6]*J[i, 8]) - 366cf3b68dSWill Pazner J[i, 2]*(J[i, 4]*J[i, 9] - J[i, 6]*J[i, 7]) + 376cf3b68dSWill Pazner J[i, 3]*(J[i, 4]*J[i, 8] - J[i, 5]*J[i, 7]) 386cf3b68dSWill Pazner )*w[i] 396cf3b68dSWill Pazner end 406cf3b68dSWill Pazner else 416cf3b68dSWill Pazner error("Bad dimension") 426cf3b68dSWill Pazner end 436cf3b68dSWill Pazner return CeedInt(0) 446cf3b68dSWill Paznerend 456cf3b68dSWill Pazner 466cf3b68dSWill Pazner# libCEED Q-function for applying a mass operator 476cf3b68dSWill Paznerfunction f_apply_mass_c( 486cf3b68dSWill Pazner ctx, 496cf3b68dSWill Pazner Q::CeedInt, 506cf3b68dSWill Pazner in_ptr::Ptr{Ptr{CeedScalar}}, 516cf3b68dSWill Pazner out_ptr::Ptr{Ptr{CeedScalar}}, 526cf3b68dSWill Pazner) 536cf3b68dSWill Pazner u = UnsafeArray(unsafe_load(in_ptr, 1), (Int(Q),)) 546cf3b68dSWill Pazner qdata = UnsafeArray(unsafe_load(in_ptr, 2), (Int(Q),)) 556cf3b68dSWill Pazner v = UnsafeArray(unsafe_load(out_ptr, 1), (Int(Q),)) 566cf3b68dSWill Pazner @inbounds @simd for i = 1:Q 576cf3b68dSWill Pazner v[i] = qdata[i]*u[i] 586cf3b68dSWill Pazner end 596cf3b68dSWill Pazner return CeedInt(0) 606cf3b68dSWill Paznerend 616cf3b68dSWill Pazner 626cf3b68dSWill Paznerfunction get_cartesian_mesh_size_c(dim, order, prob_size) 636cf3b68dSWill Pazner dims = zeros(Int, dim) 646cf3b68dSWill Pazner # Use the approximate formula: 656cf3b68dSWill Pazner # prob_size ~ num_elem * order^dim 666cf3b68dSWill Pazner num_elem = div(prob_size, order^dim) 676cf3b68dSWill Pazner s = 0 # find s: num_elem/2 < 2^s <= num_elem 686cf3b68dSWill Pazner while num_elem > 1 696cf3b68dSWill Pazner num_elem = div(num_elem, 2) 706cf3b68dSWill Pazner s += 1 716cf3b68dSWill Pazner end 726cf3b68dSWill Pazner r = s%dim 736cf3b68dSWill Pazner for d = 1:dim 746cf3b68dSWill Pazner sd = div(s, dim) 756cf3b68dSWill Pazner if r > 0 766cf3b68dSWill Pazner sd += 1 776cf3b68dSWill Pazner r -= 1 786cf3b68dSWill Pazner end 796cf3b68dSWill Pazner dims[d] = 2^sd 806cf3b68dSWill Pazner end 816cf3b68dSWill Pazner dims 826cf3b68dSWill Paznerend 836cf3b68dSWill Pazner 846cf3b68dSWill Paznerfunction build_cartesian_restriction_c( 856cf3b68dSWill Pazner ceed, 866cf3b68dSWill Pazner dim, 876cf3b68dSWill Pazner nxyz, 886cf3b68dSWill Pazner order, 896cf3b68dSWill Pazner ncomp, 906cf3b68dSWill Pazner num_qpts; 916cf3b68dSWill Pazner form_strided=false, 926cf3b68dSWill Pazner) 936cf3b68dSWill Pazner p = order 946cf3b68dSWill Pazner pp1 = p + 1 956cf3b68dSWill Pazner nnodes = pp1^dim # number of scal. nodes per element 966cf3b68dSWill Pazner elem_qpts = num_qpts^dim # number of qpts per element 976cf3b68dSWill Pazner num_elem = 1 986cf3b68dSWill Pazner scalar_size = 1 996cf3b68dSWill Pazner 1006cf3b68dSWill Pazner nd = p*nxyz .+ 1 1016cf3b68dSWill Pazner num_elem = prod(nxyz) 1026cf3b68dSWill Pazner scalar_size = prod(nd) 1036cf3b68dSWill Pazner size = scalar_size*ncomp 1046cf3b68dSWill Pazner 1056cf3b68dSWill Pazner # elem: 0 1 n-1 1066cf3b68dSWill Pazner # |---*-...-*---|---*-...-*---|- ... -|--...--| 1076cf3b68dSWill Pazner # nnodes: 0 1 p-1 p p+1 2*p n*p 1086cf3b68dSWill Pazner 1096cf3b68dSWill Pazner el_nodes = zeros(C.CeedInt, num_elem*nnodes) 1106cf3b68dSWill Pazner exyz = zeros(Int, dim) 1116cf3b68dSWill Pazner @inbounds for e = 0:(num_elem-1) 1126cf3b68dSWill Pazner re = e 1136cf3b68dSWill Pazner for d = 1:dim 1146cf3b68dSWill Pazner exyz[d] = re%nxyz[d] 1156cf3b68dSWill Pazner re = div(re, nxyz[d]) 1166cf3b68dSWill Pazner end 1176cf3b68dSWill Pazner for lnodes = 0:(nnodes-1) 1186cf3b68dSWill Pazner gnodes = 0 1196cf3b68dSWill Pazner gnodes_stride = 1 1206cf3b68dSWill Pazner rnodes = lnodes 1216cf3b68dSWill Pazner for d = 1:dim 1226cf3b68dSWill Pazner gnodes += (exyz[d]*p + rnodes%pp1)*gnodes_stride 1236cf3b68dSWill Pazner gnodes_stride *= nd[d] 1246cf3b68dSWill Pazner rnodes = div(rnodes, pp1) 1256cf3b68dSWill Pazner end 1266cf3b68dSWill Pazner el_nodes[e*nnodes+lnodes+1] = gnodes 1276cf3b68dSWill Pazner end 1286cf3b68dSWill Pazner end 1296cf3b68dSWill Pazner 130*edb2538eSJeremy L Thompson rstr = Ref{C.CeedElemRestriction}() 1316cf3b68dSWill Pazner C.CeedElemRestrictionCreate( 1326cf3b68dSWill Pazner ceed[], 1336cf3b68dSWill Pazner num_elem, 1346cf3b68dSWill Pazner nnodes, 1356cf3b68dSWill Pazner ncomp, 1366cf3b68dSWill Pazner scalar_size, 1376cf3b68dSWill Pazner ncomp*scalar_size, 1386cf3b68dSWill Pazner C.CEED_MEM_HOST, 1396cf3b68dSWill Pazner C.CEED_COPY_VALUES, 1406cf3b68dSWill Pazner el_nodes, 141*edb2538eSJeremy L Thompson rstr, 1426cf3b68dSWill Pazner ) 1436cf3b68dSWill Pazner if form_strided 144*edb2538eSJeremy L Thompson rstr_i = Ref{C.CeedElemRestriction}() 1456cf3b68dSWill Pazner err = C.CeedElemRestrictionCreateStrided( 1466cf3b68dSWill Pazner ceed[], 1476cf3b68dSWill Pazner num_elem, 1486cf3b68dSWill Pazner elem_qpts, 1496cf3b68dSWill Pazner ncomp, 1506cf3b68dSWill Pazner ncomp*elem_qpts*num_elem, 1516cf3b68dSWill Pazner C.CEED_STRIDES_BACKEND[], 152*edb2538eSJeremy L Thompson rstr_i, 1536cf3b68dSWill Pazner ) 154*edb2538eSJeremy L Thompson return size, rstr, rstr_i 1556cf3b68dSWill Pazner else 156*edb2538eSJeremy L Thompson return size, rstr 1576cf3b68dSWill Pazner end 1586cf3b68dSWill Paznerend 1596cf3b68dSWill Pazner 1606cf3b68dSWill Paznerfunction set_cartesian_mesh_coords_c(dim, nxyz, mesh_order, mesh_coords) 1616cf3b68dSWill Pazner p = mesh_order 1626cf3b68dSWill Pazner nd = p*nxyz .+ 1 1636cf3b68dSWill Pazner num_elem = prod(nxyz) 1646cf3b68dSWill Pazner scalar_size = prod(nd) 1656cf3b68dSWill Pazner 1666cf3b68dSWill Pazner coords_ref = Ref{Ptr{C.CeedScalar}}() 1676cf3b68dSWill Pazner C.CeedVectorGetArray(mesh_coords[], C.CEED_MEM_HOST, coords_ref) 1686cf3b68dSWill Pazner coords = unsafe_wrap(Array, coords_ref[], scalar_size*dim) 1696cf3b68dSWill Pazner 1706cf3b68dSWill Pazner nodes = zeros(C.CeedScalar, p + 1) 1716cf3b68dSWill Pazner # The H1 basis uses Lobatto quadrature points as nodes. 1726cf3b68dSWill Pazner C.CeedLobattoQuadrature(p + 1, nodes, C_NULL) # nodes are in [-1,1] 1736cf3b68dSWill Pazner nodes = 0.5 .+ 0.5*nodes 1746cf3b68dSWill Pazner for gsnodes = 0:(scalar_size-1) 1756cf3b68dSWill Pazner rnodes = gsnodes 1766cf3b68dSWill Pazner for d = 1:dim 1776cf3b68dSWill Pazner d1d = rnodes%nd[d] 1786cf3b68dSWill Pazner coords[gsnodes+scalar_size*(d-1)+1] = (div(d1d, p) + nodes[d1d%p+1])/nxyz[d] 1796cf3b68dSWill Pazner rnodes = div(rnodes, nd[d]) 1806cf3b68dSWill Pazner end 1816cf3b68dSWill Pazner end 1826cf3b68dSWill Pazner C.CeedVectorRestoreArray(mesh_coords[], coords_ref) 1836cf3b68dSWill Paznerend 1846cf3b68dSWill Pazner 1856cf3b68dSWill Paznerfunction transform_mesh_coords_c(dim, mesh_size, mesh_coords) 1866cf3b68dSWill Pazner coords_ref = Ref{Ptr{C.CeedScalar}}() 1876cf3b68dSWill Pazner C.CeedVectorGetArray(mesh_coords[], C.CEED_MEM_HOST, coords_ref) 1886cf3b68dSWill Pazner coords = unsafe_wrap(Array, coords_ref[], mesh_size) 1896cf3b68dSWill Pazner 1906cf3b68dSWill Pazner if dim == 1 1916cf3b68dSWill Pazner for i = 1:mesh_size 1926cf3b68dSWill Pazner # map [0,1] to [0,1] varying the mesh density 1936cf3b68dSWill Pazner coords[i] = 0.5 + 1.0/sqrt(3.0)*sin((2.0/3.0)*pi*(coords[i] - 0.5)) 1946cf3b68dSWill Pazner end 1956cf3b68dSWill Pazner exact_volume = 1 1966cf3b68dSWill Pazner else 1976cf3b68dSWill Pazner num_nodes = div(mesh_size, dim) 1986cf3b68dSWill Pazner for i = 1:num_nodes 1996cf3b68dSWill Pazner # map (x,y) from [0,1]x[0,1] to the quarter annulus with polar 2006cf3b68dSWill Pazner # coordinates, (r,phi) in [1,2]x[0,pi/2] with area = 3/4*pi 2016cf3b68dSWill Pazner u = coords[i] 2026cf3b68dSWill Pazner v = coords[i+num_nodes] 2036cf3b68dSWill Pazner u = 1.0 + u 2046cf3b68dSWill Pazner v = pi/2*v 2056cf3b68dSWill Pazner coords[i] = u*cos(v) 2066cf3b68dSWill Pazner coords[i+num_nodes] = u*sin(v) 2076cf3b68dSWill Pazner end 2086cf3b68dSWill Pazner exact_volume = 3.0/4.0*pi 2096cf3b68dSWill Pazner end 2106cf3b68dSWill Pazner 2116cf3b68dSWill Pazner C.CeedVectorRestoreArray(mesh_coords[], coords_ref) 2126cf3b68dSWill Pazner return exact_volume 2136cf3b68dSWill Paznerend 2146cf3b68dSWill Pazner 2156cf3b68dSWill Paznerfunction run_ex1_c(; ceed_spec, dim, mesh_order, sol_order, num_qpts, prob_size) 2166cf3b68dSWill Pazner ncompx = dim 2176cf3b68dSWill Pazner prob_size < 0 && (prob_size = 256*1024) 2186cf3b68dSWill Pazner 2196cf3b68dSWill Pazner gallery = false 2206cf3b68dSWill Pazner 2216cf3b68dSWill Pazner ceed = Ref{C.Ceed}() 2226cf3b68dSWill Pazner C.CeedInit(ceed_spec, ceed) 2236cf3b68dSWill Pazner 2246cf3b68dSWill Pazner mesh_basis = Ref{C.CeedBasis}() 2256cf3b68dSWill Pazner sol_basis = Ref{C.CeedBasis}() 2266cf3b68dSWill Pazner C.CeedBasisCreateTensorH1Lagrange( 2276cf3b68dSWill Pazner ceed[], 2286cf3b68dSWill Pazner dim, 2296cf3b68dSWill Pazner ncompx, 2306cf3b68dSWill Pazner mesh_order + 1, 2316cf3b68dSWill Pazner num_qpts, 2326cf3b68dSWill Pazner C.CEED_GAUSS, 2336cf3b68dSWill Pazner mesh_basis, 2346cf3b68dSWill Pazner ) 2356cf3b68dSWill Pazner C.CeedBasisCreateTensorH1Lagrange( 2366cf3b68dSWill Pazner ceed[], 2376cf3b68dSWill Pazner dim, 2386cf3b68dSWill Pazner 1, 2396cf3b68dSWill Pazner sol_order + 1, 2406cf3b68dSWill Pazner num_qpts, 2416cf3b68dSWill Pazner C.CEED_GAUSS, 2426cf3b68dSWill Pazner sol_basis, 2436cf3b68dSWill Pazner ) 2446cf3b68dSWill Pazner 2456cf3b68dSWill Pazner # Determine the mesh size based on the given approximate problem size. 2466cf3b68dSWill Pazner nxyz = get_cartesian_mesh_size_c(dim, sol_order, prob_size) 2476cf3b68dSWill Pazner println("Mesh size: ", nxyz) 2486cf3b68dSWill Pazner 2496cf3b68dSWill Pazner # Build CeedElemRestriction objects describing the mesh and solution discrete 2506cf3b68dSWill Pazner # representations. 251*edb2538eSJeremy L Thompson mesh_size, mesh_rstr = 2526cf3b68dSWill Pazner build_cartesian_restriction_c(ceed, dim, nxyz, mesh_order, ncompx, num_qpts) 253*edb2538eSJeremy L Thompson sol_size, sol_rstr, sol_rstr_i = build_cartesian_restriction_c( 2546cf3b68dSWill Pazner ceed, 2556cf3b68dSWill Pazner dim, 2566cf3b68dSWill Pazner nxyz, 2576cf3b68dSWill Pazner sol_order, 2586cf3b68dSWill Pazner 1, 2596cf3b68dSWill Pazner num_qpts, 2606cf3b68dSWill Pazner form_strided=true, 2616cf3b68dSWill Pazner ) 2626cf3b68dSWill Pazner println("Number of mesh nodes : ", div(mesh_size, dim)) 2636cf3b68dSWill Pazner println("Number of solution nodes : ", sol_size) 2646cf3b68dSWill Pazner 2656cf3b68dSWill Pazner # Create a C.CeedVector with the mesh coordinates. 2666cf3b68dSWill Pazner mesh_coords = Ref{C.CeedVector}() 2676cf3b68dSWill Pazner C.CeedVectorCreate(ceed[], mesh_size, mesh_coords) 2686cf3b68dSWill Pazner set_cartesian_mesh_coords_c(dim, nxyz, mesh_order, mesh_coords) 2696cf3b68dSWill Pazner # Apply a transformation to the mesh. 2706cf3b68dSWill Pazner exact_vol = transform_mesh_coords_c(dim, mesh_size, mesh_coords) 2716cf3b68dSWill Pazner 2726cf3b68dSWill Pazner # Create the Q-function that builds the mass operator (i.e. computes its 2736cf3b68dSWill Pazner # quadrature data) and set its context data. 2746cf3b68dSWill Pazner build_qfunc = Ref{C.CeedQFunction}() 2756cf3b68dSWill Pazner 2766cf3b68dSWill Pazner build_ctx = BuildContextC(dim, dim) 2776cf3b68dSWill Pazner qf_ctx = Ref{C.CeedQFunctionContext}() 2786cf3b68dSWill Pazner C.CeedQFunctionContextCreate(ceed[], qf_ctx) 2796cf3b68dSWill Pazner C.CeedQFunctionContextSetData( 2806cf3b68dSWill Pazner qf_ctx[], 2816cf3b68dSWill Pazner C.CEED_MEM_HOST, 2826cf3b68dSWill Pazner C.CEED_USE_POINTER, 2836cf3b68dSWill Pazner sizeof(build_ctx), 2846cf3b68dSWill Pazner pointer_from_objref(build_ctx), 2856cf3b68dSWill Pazner ) 2866cf3b68dSWill Pazner 2876cf3b68dSWill Pazner if !gallery 2886cf3b68dSWill Pazner qf_build_mass = @cfunction( 2896cf3b68dSWill Pazner f_build_mass_c, 2906cf3b68dSWill Pazner C.CeedInt, 2916cf3b68dSWill Pazner (Ptr{Cvoid}, C.CeedInt, Ptr{Ptr{C.CeedScalar}}, Ptr{Ptr{C.CeedScalar}}) 2926cf3b68dSWill Pazner ) 2936cf3b68dSWill Pazner # This creates the QFunction directly. 2946cf3b68dSWill Pazner C.CeedQFunctionCreateInterior(ceed[], 1, qf_build_mass, "julia", build_qfunc) 2956cf3b68dSWill Pazner C.CeedQFunctionAddInput(build_qfunc[], "dx", ncompx*dim, C.CEED_EVAL_GRAD) 2966cf3b68dSWill Pazner C.CeedQFunctionAddInput(build_qfunc[], "weights", 1, C.CEED_EVAL_WEIGHT) 2976cf3b68dSWill Pazner C.CeedQFunctionAddOutput(build_qfunc[], "qdata", 1, C.CEED_EVAL_NONE) 2986cf3b68dSWill Pazner C.CeedQFunctionSetContext(build_qfunc[], qf_ctx[]) 2996cf3b68dSWill Pazner else 3006cf3b68dSWill Pazner # This creates the QFunction via the gallery. 3016cf3b68dSWill Pazner name = "Mass$(dim)DBuild" 3026cf3b68dSWill Pazner C.CeedQFunctionCreateInteriorByName(ceed[], name, build_qfunc) 3036cf3b68dSWill Pazner end 3046cf3b68dSWill Pazner 3056cf3b68dSWill Pazner # Create the operator that builds the quadrature data for the mass operator. 3066cf3b68dSWill Pazner build_oper = Ref{C.CeedOperator}() 3076cf3b68dSWill Pazner C.CeedOperatorCreate( 3086cf3b68dSWill Pazner ceed[], 3096cf3b68dSWill Pazner build_qfunc[], 3106cf3b68dSWill Pazner C.CEED_QFUNCTION_NONE[], 3116cf3b68dSWill Pazner C.CEED_QFUNCTION_NONE[], 3126cf3b68dSWill Pazner build_oper, 3136cf3b68dSWill Pazner ) 3146cf3b68dSWill Pazner C.CeedOperatorSetField( 3156cf3b68dSWill Pazner build_oper[], 3166cf3b68dSWill Pazner "dx", 317*edb2538eSJeremy L Thompson mesh_rstr[], 3186cf3b68dSWill Pazner mesh_basis[], 3196cf3b68dSWill Pazner C.CEED_VECTOR_ACTIVE[], 3206cf3b68dSWill Pazner ) 3216cf3b68dSWill Pazner C.CeedOperatorSetField( 3226cf3b68dSWill Pazner build_oper[], 3236cf3b68dSWill Pazner "weights", 3246cf3b68dSWill Pazner C.CEED_ELEMRESTRICTION_NONE[], 3256cf3b68dSWill Pazner mesh_basis[], 3266cf3b68dSWill Pazner C.CEED_VECTOR_NONE[], 3276cf3b68dSWill Pazner ) 3286cf3b68dSWill Pazner C.CeedOperatorSetField( 3296cf3b68dSWill Pazner build_oper[], 3306cf3b68dSWill Pazner "qdata", 331*edb2538eSJeremy L Thompson sol_rstr_i[], 332356036faSJeremy L Thompson C.CEED_BASIS_NONE[], 3336cf3b68dSWill Pazner C.CEED_VECTOR_ACTIVE[], 3346cf3b68dSWill Pazner ) 3356cf3b68dSWill Pazner 3366cf3b68dSWill Pazner # Compute the quadrature data for the mass operator. 3376cf3b68dSWill Pazner qdata = Ref{C.CeedVector}() 3386cf3b68dSWill Pazner elem_qpts = num_qpts^dim 3396cf3b68dSWill Pazner num_elem = prod(nxyz) 3406cf3b68dSWill Pazner C.CeedVectorCreate(ceed[], num_elem*elem_qpts, qdata) 3416cf3b68dSWill Pazner 3426cf3b68dSWill Pazner print("Computing the quadrature data for the mass operator ...") 3436cf3b68dSWill Pazner flush(stdout) 3446cf3b68dSWill Pazner GC.@preserve build_ctx C.CeedOperatorApply( 3456cf3b68dSWill Pazner build_oper[], 3466cf3b68dSWill Pazner mesh_coords[], 3476cf3b68dSWill Pazner qdata[], 3486cf3b68dSWill Pazner C.CEED_REQUEST_IMMEDIATE[], 3496cf3b68dSWill Pazner ) 3506cf3b68dSWill Pazner println(" done.") 3516cf3b68dSWill Pazner 3526cf3b68dSWill Pazner # Create the Q-function that defines the action of the mass operator. 3536cf3b68dSWill Pazner apply_qfunc = Ref{C.CeedQFunction}() 3546cf3b68dSWill Pazner if !gallery 3556cf3b68dSWill Pazner qf_apply_mass = @cfunction( 3566cf3b68dSWill Pazner f_apply_mass_c, 3576cf3b68dSWill Pazner C.CeedInt, 3586cf3b68dSWill Pazner (Ptr{Cvoid}, C.CeedInt, Ptr{Ptr{C.CeedScalar}}, Ptr{Ptr{C.CeedScalar}}) 3596cf3b68dSWill Pazner ) 3606cf3b68dSWill Pazner # This creates the QFunction directly. 3616cf3b68dSWill Pazner C.CeedQFunctionCreateInterior(ceed[], 1, qf_apply_mass, "julia", apply_qfunc) 3626cf3b68dSWill Pazner C.CeedQFunctionAddInput(apply_qfunc[], "u", 1, C.CEED_EVAL_INTERP) 3636cf3b68dSWill Pazner C.CeedQFunctionAddInput(apply_qfunc[], "qdata", 1, C.CEED_EVAL_NONE) 3646cf3b68dSWill Pazner C.CeedQFunctionAddOutput(apply_qfunc[], "v", 1, C.CEED_EVAL_INTERP) 3656cf3b68dSWill Pazner else 3666cf3b68dSWill Pazner # This creates the QFunction via the gallery. 3676cf3b68dSWill Pazner C.CeedQFunctionCreateInteriorByName(ceed[], "MassApply", apply_qfunc) 3686cf3b68dSWill Pazner end 3696cf3b68dSWill Pazner 3706cf3b68dSWill Pazner # Create the mass operator. 3716cf3b68dSWill Pazner oper = Ref{C.CeedOperator}() 3726cf3b68dSWill Pazner C.CeedOperatorCreate( 3736cf3b68dSWill Pazner ceed[], 3746cf3b68dSWill Pazner apply_qfunc[], 3756cf3b68dSWill Pazner C.CEED_QFUNCTION_NONE[], 3766cf3b68dSWill Pazner C.CEED_QFUNCTION_NONE[], 3776cf3b68dSWill Pazner oper, 3786cf3b68dSWill Pazner ) 379*edb2538eSJeremy L Thompson C.CeedOperatorSetField(oper[], "u", sol_rstr[], sol_basis[], C.CEED_VECTOR_ACTIVE[]) 380*edb2538eSJeremy L Thompson C.CeedOperatorSetField(oper[], "qdata", sol_rstr_i[], C.CEED_BASIS_NONE[], qdata[]) 381*edb2538eSJeremy L Thompson C.CeedOperatorSetField(oper[], "v", sol_rstr[], sol_basis[], C.CEED_VECTOR_ACTIVE[]) 3826cf3b68dSWill Pazner 3836cf3b68dSWill Pazner # Compute the mesh volume using the mass operator: vol = 1^T \cdot M \cdot 1 3846cf3b68dSWill Pazner print("Computing the mesh volume using the formula: vol = 1^T.M.1 ...") 3856cf3b68dSWill Pazner flush(stdout) 3866cf3b68dSWill Pazner # Create auxiliary solution-size vectors. 3876cf3b68dSWill Pazner u = Ref{C.CeedVector}() 3886cf3b68dSWill Pazner v = Ref{C.CeedVector}() 3896cf3b68dSWill Pazner C.CeedVectorCreate(ceed[], sol_size, u) 3906cf3b68dSWill Pazner C.CeedVectorCreate(ceed[], sol_size, v) 3916cf3b68dSWill Pazner 3926cf3b68dSWill Pazner # Initialize 'u' with ones. 3936cf3b68dSWill Pazner C.CeedVectorSetValue(u[], 1.0) 3946cf3b68dSWill Pazner 3956cf3b68dSWill Pazner # Apply the mass operator: 'u' -> 'v'. 3966cf3b68dSWill Pazner C.CeedOperatorApply(oper[], u[], v[], C.CEED_REQUEST_IMMEDIATE[]) 3976cf3b68dSWill Pazner 3986cf3b68dSWill Pazner # Compute and print the sum of the entries of 'v' giving the mesh volume. 3996cf3b68dSWill Pazner v_host_ref = Ref{Ptr{C.CeedScalar}}() 4006cf3b68dSWill Pazner C.CeedVectorGetArrayRead(v[], C.CEED_MEM_HOST, v_host_ref) 4016cf3b68dSWill Pazner v_host = unsafe_wrap(Array, v_host_ref[], sol_size) 4026cf3b68dSWill Pazner vol = sum(v_host) 4036cf3b68dSWill Pazner C.CeedVectorRestoreArrayRead(v[], v_host_ref) 4046cf3b68dSWill Pazner 4056cf3b68dSWill Pazner println(" done.") 4066cf3b68dSWill Pazner @printf("Exact mesh volume : % .14g\n", exact_vol) 4076cf3b68dSWill Pazner @printf("Computed mesh volume : % .14g\n", vol) 4086cf3b68dSWill Pazner @printf("Volume error : % .14g\n", vol - exact_vol) 4096cf3b68dSWill Pazner 4106cf3b68dSWill Pazner # Free dynamically allocated memory. 4116cf3b68dSWill Pazner C.CeedVectorDestroy(u) 4126cf3b68dSWill Pazner C.CeedVectorDestroy(v) 4136cf3b68dSWill Pazner C.CeedVectorDestroy(qdata) 4146cf3b68dSWill Pazner C.CeedVectorDestroy(mesh_coords) 4156cf3b68dSWill Pazner C.CeedOperatorDestroy(oper) 4166cf3b68dSWill Pazner C.CeedQFunctionDestroy(apply_qfunc) 4176cf3b68dSWill Pazner C.CeedOperatorDestroy(build_oper) 4186cf3b68dSWill Pazner C.CeedQFunctionDestroy(build_qfunc) 419*edb2538eSJeremy L Thompson C.CeedElemRestrictionDestroy(sol_rstr) 420*edb2538eSJeremy L Thompson C.CeedElemRestrictionDestroy(mesh_rstr) 421*edb2538eSJeremy L Thompson C.CeedElemRestrictionDestroy(sol_rstr_i) 4226cf3b68dSWill Pazner C.CeedBasisDestroy(sol_basis) 4236cf3b68dSWill Pazner C.CeedBasisDestroy(mesh_basis) 4246cf3b68dSWill Pazner C.CeedDestroy(ceed) 4256cf3b68dSWill Paznerend 4266cf3b68dSWill Pazner 4276cf3b68dSWill Paznerrun_ex1_c( 4286cf3b68dSWill Pazner ceed_spec="/cpu/self", 4296cf3b68dSWill Pazner dim=3, 4306cf3b68dSWill Pazner mesh_order=4, 4316cf3b68dSWill Pazner sol_order=4, 4326cf3b68dSWill Pazner num_qpts=4 + 2, 4336cf3b68dSWill Pazner prob_size=-1, 4346cf3b68dSWill Pazner) 435