1*6cf3b68dSWill Paznerusing LibCEED.C, Printf, UnsafeArrays 2*6cf3b68dSWill Paznerusing LibCEED.C: CeedInt, CeedScalar 3*6cf3b68dSWill Pazner 4*6cf3b68dSWill Pazner# A structure used to pass additional data to f_build_mass 5*6cf3b68dSWill Paznermutable struct BuildContextC 6*6cf3b68dSWill Pazner dim::CeedInt 7*6cf3b68dSWill Pazner space_dim::CeedInt 8*6cf3b68dSWill Paznerend 9*6cf3b68dSWill Pazner 10*6cf3b68dSWill Pazner# libCEED Q-function for building quadrature data for a mass operator 11*6cf3b68dSWill Paznerfunction f_build_mass_c( 12*6cf3b68dSWill Pazner ctx_ptr::Ptr{Cvoid}, 13*6cf3b68dSWill Pazner Q::CeedInt, 14*6cf3b68dSWill Pazner in_ptr::Ptr{Ptr{CeedScalar}}, 15*6cf3b68dSWill Pazner out_ptr::Ptr{Ptr{CeedScalar}}, 16*6cf3b68dSWill Pazner) 17*6cf3b68dSWill Pazner # in[0] is Jacobians with shape [dim, nc=dim, Q] 18*6cf3b68dSWill Pazner # in[1] is quadrature weights, size (Q) 19*6cf3b68dSWill Pazner ctx = unsafe_load(Ptr{BuildContextC}(ctx_ptr)) 20*6cf3b68dSWill Pazner J = UnsafeArray(unsafe_load(in_ptr, 1), (Int(Q), Int(ctx.dim^2))) 21*6cf3b68dSWill Pazner w = UnsafeArray(unsafe_load(in_ptr, 2), (Int(Q),)) 22*6cf3b68dSWill Pazner qdata = UnsafeArray(unsafe_load(out_ptr, 1), (Int(Q),)) 23*6cf3b68dSWill Pazner if ctx.dim == 1 24*6cf3b68dSWill Pazner @inbounds @simd for i = 1:Q 25*6cf3b68dSWill Pazner qdata[i] = J[i]*w[i] 26*6cf3b68dSWill Pazner end 27*6cf3b68dSWill Pazner elseif ctx.dim == 2 28*6cf3b68dSWill Pazner @inbounds @simd for i = 1:Q 29*6cf3b68dSWill Pazner qdata[i] = (J[i, 1]*J[i, 4] - J[i, 2]*J[i, 3])*w[i] 30*6cf3b68dSWill Pazner end 31*6cf3b68dSWill Pazner elseif ctx.dim == 3 32*6cf3b68dSWill Pazner @inbounds @simd for i = 1:Q 33*6cf3b68dSWill Pazner qdata[i] = 34*6cf3b68dSWill Pazner ( 35*6cf3b68dSWill Pazner J[i, 1]*(J[i, 5]*J[i, 9] - J[i, 6]*J[i, 8]) - 36*6cf3b68dSWill Pazner J[i, 2]*(J[i, 4]*J[i, 9] - J[i, 6]*J[i, 7]) + 37*6cf3b68dSWill Pazner J[i, 3]*(J[i, 4]*J[i, 8] - J[i, 5]*J[i, 7]) 38*6cf3b68dSWill Pazner )*w[i] 39*6cf3b68dSWill Pazner end 40*6cf3b68dSWill Pazner else 41*6cf3b68dSWill Pazner error("Bad dimension") 42*6cf3b68dSWill Pazner end 43*6cf3b68dSWill Pazner return CeedInt(0) 44*6cf3b68dSWill Paznerend 45*6cf3b68dSWill Pazner 46*6cf3b68dSWill Pazner# libCEED Q-function for applying a mass operator 47*6cf3b68dSWill Paznerfunction f_apply_mass_c( 48*6cf3b68dSWill Pazner ctx, 49*6cf3b68dSWill Pazner Q::CeedInt, 50*6cf3b68dSWill Pazner in_ptr::Ptr{Ptr{CeedScalar}}, 51*6cf3b68dSWill Pazner out_ptr::Ptr{Ptr{CeedScalar}}, 52*6cf3b68dSWill Pazner) 53*6cf3b68dSWill Pazner u = UnsafeArray(unsafe_load(in_ptr, 1), (Int(Q),)) 54*6cf3b68dSWill Pazner qdata = UnsafeArray(unsafe_load(in_ptr, 2), (Int(Q),)) 55*6cf3b68dSWill Pazner v = UnsafeArray(unsafe_load(out_ptr, 1), (Int(Q),)) 56*6cf3b68dSWill Pazner @inbounds @simd for i = 1:Q 57*6cf3b68dSWill Pazner v[i] = qdata[i]*u[i] 58*6cf3b68dSWill Pazner end 59*6cf3b68dSWill Pazner return CeedInt(0) 60*6cf3b68dSWill Paznerend 61*6cf3b68dSWill Pazner 62*6cf3b68dSWill Paznerfunction get_cartesian_mesh_size_c(dim, order, prob_size) 63*6cf3b68dSWill Pazner dims = zeros(Int, dim) 64*6cf3b68dSWill Pazner # Use the approximate formula: 65*6cf3b68dSWill Pazner # prob_size ~ num_elem * order^dim 66*6cf3b68dSWill Pazner num_elem = div(prob_size, order^dim) 67*6cf3b68dSWill Pazner s = 0 # find s: num_elem/2 < 2^s <= num_elem 68*6cf3b68dSWill Pazner while num_elem > 1 69*6cf3b68dSWill Pazner num_elem = div(num_elem, 2) 70*6cf3b68dSWill Pazner s += 1 71*6cf3b68dSWill Pazner end 72*6cf3b68dSWill Pazner r = s%dim 73*6cf3b68dSWill Pazner for d = 1:dim 74*6cf3b68dSWill Pazner sd = div(s, dim) 75*6cf3b68dSWill Pazner if r > 0 76*6cf3b68dSWill Pazner sd += 1 77*6cf3b68dSWill Pazner r -= 1 78*6cf3b68dSWill Pazner end 79*6cf3b68dSWill Pazner dims[d] = 2^sd 80*6cf3b68dSWill Pazner end 81*6cf3b68dSWill Pazner dims 82*6cf3b68dSWill Paznerend 83*6cf3b68dSWill Pazner 84*6cf3b68dSWill Paznerfunction build_cartesian_restriction_c( 85*6cf3b68dSWill Pazner ceed, 86*6cf3b68dSWill Pazner dim, 87*6cf3b68dSWill Pazner nxyz, 88*6cf3b68dSWill Pazner order, 89*6cf3b68dSWill Pazner ncomp, 90*6cf3b68dSWill Pazner num_qpts; 91*6cf3b68dSWill Pazner form_strided=false, 92*6cf3b68dSWill Pazner) 93*6cf3b68dSWill Pazner p = order 94*6cf3b68dSWill Pazner pp1 = p + 1 95*6cf3b68dSWill Pazner nnodes = pp1^dim # number of scal. nodes per element 96*6cf3b68dSWill Pazner elem_qpts = num_qpts^dim # number of qpts per element 97*6cf3b68dSWill Pazner num_elem = 1 98*6cf3b68dSWill Pazner scalar_size = 1 99*6cf3b68dSWill Pazner 100*6cf3b68dSWill Pazner nd = p*nxyz .+ 1 101*6cf3b68dSWill Pazner num_elem = prod(nxyz) 102*6cf3b68dSWill Pazner scalar_size = prod(nd) 103*6cf3b68dSWill Pazner size = scalar_size*ncomp 104*6cf3b68dSWill Pazner 105*6cf3b68dSWill Pazner # elem: 0 1 n-1 106*6cf3b68dSWill Pazner # |---*-...-*---|---*-...-*---|- ... -|--...--| 107*6cf3b68dSWill Pazner # nnodes: 0 1 p-1 p p+1 2*p n*p 108*6cf3b68dSWill Pazner 109*6cf3b68dSWill Pazner el_nodes = zeros(C.CeedInt, num_elem*nnodes) 110*6cf3b68dSWill Pazner exyz = zeros(Int, dim) 111*6cf3b68dSWill Pazner @inbounds for e = 0:(num_elem-1) 112*6cf3b68dSWill Pazner re = e 113*6cf3b68dSWill Pazner for d = 1:dim 114*6cf3b68dSWill Pazner exyz[d] = re%nxyz[d] 115*6cf3b68dSWill Pazner re = div(re, nxyz[d]) 116*6cf3b68dSWill Pazner end 117*6cf3b68dSWill Pazner for lnodes = 0:(nnodes-1) 118*6cf3b68dSWill Pazner gnodes = 0 119*6cf3b68dSWill Pazner gnodes_stride = 1 120*6cf3b68dSWill Pazner rnodes = lnodes 121*6cf3b68dSWill Pazner for d = 1:dim 122*6cf3b68dSWill Pazner gnodes += (exyz[d]*p + rnodes%pp1)*gnodes_stride 123*6cf3b68dSWill Pazner gnodes_stride *= nd[d] 124*6cf3b68dSWill Pazner rnodes = div(rnodes, pp1) 125*6cf3b68dSWill Pazner end 126*6cf3b68dSWill Pazner el_nodes[e*nnodes+lnodes+1] = gnodes 127*6cf3b68dSWill Pazner end 128*6cf3b68dSWill Pazner end 129*6cf3b68dSWill Pazner 130*6cf3b68dSWill Pazner restr = Ref{C.CeedElemRestriction}() 131*6cf3b68dSWill Pazner C.CeedElemRestrictionCreate( 132*6cf3b68dSWill Pazner ceed[], 133*6cf3b68dSWill Pazner num_elem, 134*6cf3b68dSWill Pazner nnodes, 135*6cf3b68dSWill Pazner ncomp, 136*6cf3b68dSWill Pazner scalar_size, 137*6cf3b68dSWill Pazner ncomp*scalar_size, 138*6cf3b68dSWill Pazner C.CEED_MEM_HOST, 139*6cf3b68dSWill Pazner C.CEED_COPY_VALUES, 140*6cf3b68dSWill Pazner el_nodes, 141*6cf3b68dSWill Pazner restr, 142*6cf3b68dSWill Pazner ) 143*6cf3b68dSWill Pazner if form_strided 144*6cf3b68dSWill Pazner restr_i = Ref{C.CeedElemRestriction}() 145*6cf3b68dSWill Pazner err = C.CeedElemRestrictionCreateStrided( 146*6cf3b68dSWill Pazner ceed[], 147*6cf3b68dSWill Pazner num_elem, 148*6cf3b68dSWill Pazner elem_qpts, 149*6cf3b68dSWill Pazner ncomp, 150*6cf3b68dSWill Pazner ncomp*elem_qpts*num_elem, 151*6cf3b68dSWill Pazner C.CEED_STRIDES_BACKEND[], 152*6cf3b68dSWill Pazner restr_i, 153*6cf3b68dSWill Pazner ) 154*6cf3b68dSWill Pazner return size, restr, restr_i 155*6cf3b68dSWill Pazner else 156*6cf3b68dSWill Pazner return size, restr 157*6cf3b68dSWill Pazner end 158*6cf3b68dSWill Paznerend 159*6cf3b68dSWill Pazner 160*6cf3b68dSWill Paznerfunction set_cartesian_mesh_coords_c(dim, nxyz, mesh_order, mesh_coords) 161*6cf3b68dSWill Pazner p = mesh_order 162*6cf3b68dSWill Pazner nd = p*nxyz .+ 1 163*6cf3b68dSWill Pazner num_elem = prod(nxyz) 164*6cf3b68dSWill Pazner scalar_size = prod(nd) 165*6cf3b68dSWill Pazner 166*6cf3b68dSWill Pazner coords_ref = Ref{Ptr{C.CeedScalar}}() 167*6cf3b68dSWill Pazner C.CeedVectorGetArray(mesh_coords[], C.CEED_MEM_HOST, coords_ref) 168*6cf3b68dSWill Pazner coords = unsafe_wrap(Array, coords_ref[], scalar_size*dim) 169*6cf3b68dSWill Pazner 170*6cf3b68dSWill Pazner nodes = zeros(C.CeedScalar, p + 1) 171*6cf3b68dSWill Pazner # The H1 basis uses Lobatto quadrature points as nodes. 172*6cf3b68dSWill Pazner C.CeedLobattoQuadrature(p + 1, nodes, C_NULL) # nodes are in [-1,1] 173*6cf3b68dSWill Pazner nodes = 0.5 .+ 0.5*nodes 174*6cf3b68dSWill Pazner for gsnodes = 0:(scalar_size-1) 175*6cf3b68dSWill Pazner rnodes = gsnodes 176*6cf3b68dSWill Pazner for d = 1:dim 177*6cf3b68dSWill Pazner d1d = rnodes%nd[d] 178*6cf3b68dSWill Pazner coords[gsnodes+scalar_size*(d-1)+1] = (div(d1d, p) + nodes[d1d%p+1])/nxyz[d] 179*6cf3b68dSWill Pazner rnodes = div(rnodes, nd[d]) 180*6cf3b68dSWill Pazner end 181*6cf3b68dSWill Pazner end 182*6cf3b68dSWill Pazner C.CeedVectorRestoreArray(mesh_coords[], coords_ref) 183*6cf3b68dSWill Paznerend 184*6cf3b68dSWill Pazner 185*6cf3b68dSWill Paznerfunction transform_mesh_coords_c(dim, mesh_size, mesh_coords) 186*6cf3b68dSWill Pazner coords_ref = Ref{Ptr{C.CeedScalar}}() 187*6cf3b68dSWill Pazner C.CeedVectorGetArray(mesh_coords[], C.CEED_MEM_HOST, coords_ref) 188*6cf3b68dSWill Pazner coords = unsafe_wrap(Array, coords_ref[], mesh_size) 189*6cf3b68dSWill Pazner 190*6cf3b68dSWill Pazner if dim == 1 191*6cf3b68dSWill Pazner for i = 1:mesh_size 192*6cf3b68dSWill Pazner # map [0,1] to [0,1] varying the mesh density 193*6cf3b68dSWill Pazner coords[i] = 0.5 + 1.0/sqrt(3.0)*sin((2.0/3.0)*pi*(coords[i] - 0.5)) 194*6cf3b68dSWill Pazner end 195*6cf3b68dSWill Pazner exact_volume = 1 196*6cf3b68dSWill Pazner else 197*6cf3b68dSWill Pazner num_nodes = div(mesh_size, dim) 198*6cf3b68dSWill Pazner for i = 1:num_nodes 199*6cf3b68dSWill Pazner # map (x,y) from [0,1]x[0,1] to the quarter annulus with polar 200*6cf3b68dSWill Pazner # coordinates, (r,phi) in [1,2]x[0,pi/2] with area = 3/4*pi 201*6cf3b68dSWill Pazner u = coords[i] 202*6cf3b68dSWill Pazner v = coords[i+num_nodes] 203*6cf3b68dSWill Pazner u = 1.0 + u 204*6cf3b68dSWill Pazner v = pi/2*v 205*6cf3b68dSWill Pazner coords[i] = u*cos(v) 206*6cf3b68dSWill Pazner coords[i+num_nodes] = u*sin(v) 207*6cf3b68dSWill Pazner end 208*6cf3b68dSWill Pazner exact_volume = 3.0/4.0*pi 209*6cf3b68dSWill Pazner end 210*6cf3b68dSWill Pazner 211*6cf3b68dSWill Pazner C.CeedVectorRestoreArray(mesh_coords[], coords_ref) 212*6cf3b68dSWill Pazner return exact_volume 213*6cf3b68dSWill Paznerend 214*6cf3b68dSWill Pazner 215*6cf3b68dSWill Paznerfunction run_ex1_c(; ceed_spec, dim, mesh_order, sol_order, num_qpts, prob_size) 216*6cf3b68dSWill Pazner ncompx = dim 217*6cf3b68dSWill Pazner prob_size < 0 && (prob_size = 256*1024) 218*6cf3b68dSWill Pazner 219*6cf3b68dSWill Pazner gallery = false 220*6cf3b68dSWill Pazner 221*6cf3b68dSWill Pazner ceed = Ref{C.Ceed}() 222*6cf3b68dSWill Pazner C.CeedInit(ceed_spec, ceed) 223*6cf3b68dSWill Pazner 224*6cf3b68dSWill Pazner mesh_basis = Ref{C.CeedBasis}() 225*6cf3b68dSWill Pazner sol_basis = Ref{C.CeedBasis}() 226*6cf3b68dSWill Pazner C.CeedBasisCreateTensorH1Lagrange( 227*6cf3b68dSWill Pazner ceed[], 228*6cf3b68dSWill Pazner dim, 229*6cf3b68dSWill Pazner ncompx, 230*6cf3b68dSWill Pazner mesh_order + 1, 231*6cf3b68dSWill Pazner num_qpts, 232*6cf3b68dSWill Pazner C.CEED_GAUSS, 233*6cf3b68dSWill Pazner mesh_basis, 234*6cf3b68dSWill Pazner ) 235*6cf3b68dSWill Pazner C.CeedBasisCreateTensorH1Lagrange( 236*6cf3b68dSWill Pazner ceed[], 237*6cf3b68dSWill Pazner dim, 238*6cf3b68dSWill Pazner 1, 239*6cf3b68dSWill Pazner sol_order + 1, 240*6cf3b68dSWill Pazner num_qpts, 241*6cf3b68dSWill Pazner C.CEED_GAUSS, 242*6cf3b68dSWill Pazner sol_basis, 243*6cf3b68dSWill Pazner ) 244*6cf3b68dSWill Pazner 245*6cf3b68dSWill Pazner # Determine the mesh size based on the given approximate problem size. 246*6cf3b68dSWill Pazner nxyz = get_cartesian_mesh_size_c(dim, sol_order, prob_size) 247*6cf3b68dSWill Pazner println("Mesh size: ", nxyz) 248*6cf3b68dSWill Pazner 249*6cf3b68dSWill Pazner # Build CeedElemRestriction objects describing the mesh and solution discrete 250*6cf3b68dSWill Pazner # representations. 251*6cf3b68dSWill Pazner mesh_size, mesh_restr = 252*6cf3b68dSWill Pazner build_cartesian_restriction_c(ceed, dim, nxyz, mesh_order, ncompx, num_qpts) 253*6cf3b68dSWill Pazner sol_size, sol_restr, sol_restr_i = build_cartesian_restriction_c( 254*6cf3b68dSWill Pazner ceed, 255*6cf3b68dSWill Pazner dim, 256*6cf3b68dSWill Pazner nxyz, 257*6cf3b68dSWill Pazner sol_order, 258*6cf3b68dSWill Pazner 1, 259*6cf3b68dSWill Pazner num_qpts, 260*6cf3b68dSWill Pazner form_strided=true, 261*6cf3b68dSWill Pazner ) 262*6cf3b68dSWill Pazner println("Number of mesh nodes : ", div(mesh_size, dim)) 263*6cf3b68dSWill Pazner println("Number of solution nodes : ", sol_size) 264*6cf3b68dSWill Pazner 265*6cf3b68dSWill Pazner # Create a C.CeedVector with the mesh coordinates. 266*6cf3b68dSWill Pazner mesh_coords = Ref{C.CeedVector}() 267*6cf3b68dSWill Pazner C.CeedVectorCreate(ceed[], mesh_size, mesh_coords) 268*6cf3b68dSWill Pazner set_cartesian_mesh_coords_c(dim, nxyz, mesh_order, mesh_coords) 269*6cf3b68dSWill Pazner # Apply a transformation to the mesh. 270*6cf3b68dSWill Pazner exact_vol = transform_mesh_coords_c(dim, mesh_size, mesh_coords) 271*6cf3b68dSWill Pazner 272*6cf3b68dSWill Pazner # Create the Q-function that builds the mass operator (i.e. computes its 273*6cf3b68dSWill Pazner # quadrature data) and set its context data. 274*6cf3b68dSWill Pazner build_qfunc = Ref{C.CeedQFunction}() 275*6cf3b68dSWill Pazner 276*6cf3b68dSWill Pazner build_ctx = BuildContextC(dim, dim) 277*6cf3b68dSWill Pazner qf_ctx = Ref{C.CeedQFunctionContext}() 278*6cf3b68dSWill Pazner C.CeedQFunctionContextCreate(ceed[], qf_ctx) 279*6cf3b68dSWill Pazner C.CeedQFunctionContextSetData( 280*6cf3b68dSWill Pazner qf_ctx[], 281*6cf3b68dSWill Pazner C.CEED_MEM_HOST, 282*6cf3b68dSWill Pazner C.CEED_USE_POINTER, 283*6cf3b68dSWill Pazner sizeof(build_ctx), 284*6cf3b68dSWill Pazner pointer_from_objref(build_ctx), 285*6cf3b68dSWill Pazner ) 286*6cf3b68dSWill Pazner 287*6cf3b68dSWill Pazner if !gallery 288*6cf3b68dSWill Pazner qf_build_mass = @cfunction( 289*6cf3b68dSWill Pazner f_build_mass_c, 290*6cf3b68dSWill Pazner C.CeedInt, 291*6cf3b68dSWill Pazner (Ptr{Cvoid}, C.CeedInt, Ptr{Ptr{C.CeedScalar}}, Ptr{Ptr{C.CeedScalar}}) 292*6cf3b68dSWill Pazner ) 293*6cf3b68dSWill Pazner # This creates the QFunction directly. 294*6cf3b68dSWill Pazner C.CeedQFunctionCreateInterior(ceed[], 1, qf_build_mass, "julia", build_qfunc) 295*6cf3b68dSWill Pazner C.CeedQFunctionAddInput(build_qfunc[], "dx", ncompx*dim, C.CEED_EVAL_GRAD) 296*6cf3b68dSWill Pazner C.CeedQFunctionAddInput(build_qfunc[], "weights", 1, C.CEED_EVAL_WEIGHT) 297*6cf3b68dSWill Pazner C.CeedQFunctionAddOutput(build_qfunc[], "qdata", 1, C.CEED_EVAL_NONE) 298*6cf3b68dSWill Pazner C.CeedQFunctionSetContext(build_qfunc[], qf_ctx[]) 299*6cf3b68dSWill Pazner else 300*6cf3b68dSWill Pazner # This creates the QFunction via the gallery. 301*6cf3b68dSWill Pazner name = "Mass$(dim)DBuild" 302*6cf3b68dSWill Pazner C.CeedQFunctionCreateInteriorByName(ceed[], name, build_qfunc) 303*6cf3b68dSWill Pazner end 304*6cf3b68dSWill Pazner 305*6cf3b68dSWill Pazner # Create the operator that builds the quadrature data for the mass operator. 306*6cf3b68dSWill Pazner build_oper = Ref{C.CeedOperator}() 307*6cf3b68dSWill Pazner C.CeedOperatorCreate( 308*6cf3b68dSWill Pazner ceed[], 309*6cf3b68dSWill Pazner build_qfunc[], 310*6cf3b68dSWill Pazner C.CEED_QFUNCTION_NONE[], 311*6cf3b68dSWill Pazner C.CEED_QFUNCTION_NONE[], 312*6cf3b68dSWill Pazner build_oper, 313*6cf3b68dSWill Pazner ) 314*6cf3b68dSWill Pazner C.CeedOperatorSetField( 315*6cf3b68dSWill Pazner build_oper[], 316*6cf3b68dSWill Pazner "dx", 317*6cf3b68dSWill Pazner mesh_restr[], 318*6cf3b68dSWill Pazner mesh_basis[], 319*6cf3b68dSWill Pazner C.CEED_VECTOR_ACTIVE[], 320*6cf3b68dSWill Pazner ) 321*6cf3b68dSWill Pazner C.CeedOperatorSetField( 322*6cf3b68dSWill Pazner build_oper[], 323*6cf3b68dSWill Pazner "weights", 324*6cf3b68dSWill Pazner C.CEED_ELEMRESTRICTION_NONE[], 325*6cf3b68dSWill Pazner mesh_basis[], 326*6cf3b68dSWill Pazner C.CEED_VECTOR_NONE[], 327*6cf3b68dSWill Pazner ) 328*6cf3b68dSWill Pazner C.CeedOperatorSetField( 329*6cf3b68dSWill Pazner build_oper[], 330*6cf3b68dSWill Pazner "qdata", 331*6cf3b68dSWill Pazner sol_restr_i[], 332*6cf3b68dSWill Pazner C.CEED_BASIS_COLLOCATED[], 333*6cf3b68dSWill Pazner C.CEED_VECTOR_ACTIVE[], 334*6cf3b68dSWill Pazner ) 335*6cf3b68dSWill Pazner 336*6cf3b68dSWill Pazner # Compute the quadrature data for the mass operator. 337*6cf3b68dSWill Pazner qdata = Ref{C.CeedVector}() 338*6cf3b68dSWill Pazner elem_qpts = num_qpts^dim 339*6cf3b68dSWill Pazner num_elem = prod(nxyz) 340*6cf3b68dSWill Pazner C.CeedVectorCreate(ceed[], num_elem*elem_qpts, qdata) 341*6cf3b68dSWill Pazner 342*6cf3b68dSWill Pazner print("Computing the quadrature data for the mass operator ...") 343*6cf3b68dSWill Pazner flush(stdout) 344*6cf3b68dSWill Pazner GC.@preserve build_ctx C.CeedOperatorApply( 345*6cf3b68dSWill Pazner build_oper[], 346*6cf3b68dSWill Pazner mesh_coords[], 347*6cf3b68dSWill Pazner qdata[], 348*6cf3b68dSWill Pazner C.CEED_REQUEST_IMMEDIATE[], 349*6cf3b68dSWill Pazner ) 350*6cf3b68dSWill Pazner println(" done.") 351*6cf3b68dSWill Pazner 352*6cf3b68dSWill Pazner # Create the Q-function that defines the action of the mass operator. 353*6cf3b68dSWill Pazner apply_qfunc = Ref{C.CeedQFunction}() 354*6cf3b68dSWill Pazner if !gallery 355*6cf3b68dSWill Pazner qf_apply_mass = @cfunction( 356*6cf3b68dSWill Pazner f_apply_mass_c, 357*6cf3b68dSWill Pazner C.CeedInt, 358*6cf3b68dSWill Pazner (Ptr{Cvoid}, C.CeedInt, Ptr{Ptr{C.CeedScalar}}, Ptr{Ptr{C.CeedScalar}}) 359*6cf3b68dSWill Pazner ) 360*6cf3b68dSWill Pazner # This creates the QFunction directly. 361*6cf3b68dSWill Pazner C.CeedQFunctionCreateInterior(ceed[], 1, qf_apply_mass, "julia", apply_qfunc) 362*6cf3b68dSWill Pazner C.CeedQFunctionAddInput(apply_qfunc[], "u", 1, C.CEED_EVAL_INTERP) 363*6cf3b68dSWill Pazner C.CeedQFunctionAddInput(apply_qfunc[], "qdata", 1, C.CEED_EVAL_NONE) 364*6cf3b68dSWill Pazner C.CeedQFunctionAddOutput(apply_qfunc[], "v", 1, C.CEED_EVAL_INTERP) 365*6cf3b68dSWill Pazner else 366*6cf3b68dSWill Pazner # This creates the QFunction via the gallery. 367*6cf3b68dSWill Pazner C.CeedQFunctionCreateInteriorByName(ceed[], "MassApply", apply_qfunc) 368*6cf3b68dSWill Pazner end 369*6cf3b68dSWill Pazner 370*6cf3b68dSWill Pazner # Create the mass operator. 371*6cf3b68dSWill Pazner oper = Ref{C.CeedOperator}() 372*6cf3b68dSWill Pazner C.CeedOperatorCreate( 373*6cf3b68dSWill Pazner ceed[], 374*6cf3b68dSWill Pazner apply_qfunc[], 375*6cf3b68dSWill Pazner C.CEED_QFUNCTION_NONE[], 376*6cf3b68dSWill Pazner C.CEED_QFUNCTION_NONE[], 377*6cf3b68dSWill Pazner oper, 378*6cf3b68dSWill Pazner ) 379*6cf3b68dSWill Pazner C.CeedOperatorSetField(oper[], "u", sol_restr[], sol_basis[], C.CEED_VECTOR_ACTIVE[]) 380*6cf3b68dSWill Pazner C.CeedOperatorSetField( 381*6cf3b68dSWill Pazner oper[], 382*6cf3b68dSWill Pazner "qdata", 383*6cf3b68dSWill Pazner sol_restr_i[], 384*6cf3b68dSWill Pazner C.CEED_BASIS_COLLOCATED[], 385*6cf3b68dSWill Pazner qdata[], 386*6cf3b68dSWill Pazner ) 387*6cf3b68dSWill Pazner C.CeedOperatorSetField(oper[], "v", sol_restr[], sol_basis[], C.CEED_VECTOR_ACTIVE[]) 388*6cf3b68dSWill Pazner 389*6cf3b68dSWill Pazner # Compute the mesh volume using the mass operator: vol = 1^T \cdot M \cdot 1 390*6cf3b68dSWill Pazner print("Computing the mesh volume using the formula: vol = 1^T.M.1 ...") 391*6cf3b68dSWill Pazner flush(stdout) 392*6cf3b68dSWill Pazner # Create auxiliary solution-size vectors. 393*6cf3b68dSWill Pazner u = Ref{C.CeedVector}() 394*6cf3b68dSWill Pazner v = Ref{C.CeedVector}() 395*6cf3b68dSWill Pazner C.CeedVectorCreate(ceed[], sol_size, u) 396*6cf3b68dSWill Pazner C.CeedVectorCreate(ceed[], sol_size, v) 397*6cf3b68dSWill Pazner 398*6cf3b68dSWill Pazner # Initialize 'u' with ones. 399*6cf3b68dSWill Pazner C.CeedVectorSetValue(u[], 1.0) 400*6cf3b68dSWill Pazner 401*6cf3b68dSWill Pazner # Apply the mass operator: 'u' -> 'v'. 402*6cf3b68dSWill Pazner C.CeedOperatorApply(oper[], u[], v[], C.CEED_REQUEST_IMMEDIATE[]) 403*6cf3b68dSWill Pazner 404*6cf3b68dSWill Pazner # Compute and print the sum of the entries of 'v' giving the mesh volume. 405*6cf3b68dSWill Pazner v_host_ref = Ref{Ptr{C.CeedScalar}}() 406*6cf3b68dSWill Pazner C.CeedVectorGetArrayRead(v[], C.CEED_MEM_HOST, v_host_ref) 407*6cf3b68dSWill Pazner v_host = unsafe_wrap(Array, v_host_ref[], sol_size) 408*6cf3b68dSWill Pazner vol = sum(v_host) 409*6cf3b68dSWill Pazner C.CeedVectorRestoreArrayRead(v[], v_host_ref) 410*6cf3b68dSWill Pazner 411*6cf3b68dSWill Pazner println(" done.") 412*6cf3b68dSWill Pazner @printf("Exact mesh volume : % .14g\n", exact_vol) 413*6cf3b68dSWill Pazner @printf("Computed mesh volume : % .14g\n", vol) 414*6cf3b68dSWill Pazner @printf("Volume error : % .14g\n", vol - exact_vol) 415*6cf3b68dSWill Pazner 416*6cf3b68dSWill Pazner # Free dynamically allocated memory. 417*6cf3b68dSWill Pazner C.CeedVectorDestroy(u) 418*6cf3b68dSWill Pazner C.CeedVectorDestroy(v) 419*6cf3b68dSWill Pazner C.CeedVectorDestroy(qdata) 420*6cf3b68dSWill Pazner C.CeedVectorDestroy(mesh_coords) 421*6cf3b68dSWill Pazner C.CeedOperatorDestroy(oper) 422*6cf3b68dSWill Pazner C.CeedQFunctionDestroy(apply_qfunc) 423*6cf3b68dSWill Pazner C.CeedOperatorDestroy(build_oper) 424*6cf3b68dSWill Pazner C.CeedQFunctionDestroy(build_qfunc) 425*6cf3b68dSWill Pazner C.CeedElemRestrictionDestroy(sol_restr) 426*6cf3b68dSWill Pazner C.CeedElemRestrictionDestroy(mesh_restr) 427*6cf3b68dSWill Pazner C.CeedElemRestrictionDestroy(sol_restr_i) 428*6cf3b68dSWill Pazner C.CeedBasisDestroy(sol_basis) 429*6cf3b68dSWill Pazner C.CeedBasisDestroy(mesh_basis) 430*6cf3b68dSWill Pazner C.CeedDestroy(ceed) 431*6cf3b68dSWill Paznerend 432*6cf3b68dSWill Pazner 433*6cf3b68dSWill Paznerrun_ex1_c( 434*6cf3b68dSWill Pazner ceed_spec="/cpu/self", 435*6cf3b68dSWill Pazner dim=3, 436*6cf3b68dSWill Pazner mesh_order=4, 437*6cf3b68dSWill Pazner sol_order=4, 438*6cf3b68dSWill Pazner num_qpts=4 + 2, 439*6cf3b68dSWill Pazner prob_size=-1, 440*6cf3b68dSWill Pazner) 441