1*6cf3b68dSWill Paznerusing LibCEED, Printf 2*6cf3b68dSWill Pazner 3*6cf3b68dSWill Paznerinclude("common.jl") 4*6cf3b68dSWill Pazner 5*6cf3b68dSWill Paznerfunction transform_mesh_coords!(dim, mesh_size, mesh_coords) 6*6cf3b68dSWill Pazner @witharray coords = mesh_coords begin 7*6cf3b68dSWill Pazner if dim == 1 8*6cf3b68dSWill Pazner for i = 1:mesh_size 9*6cf3b68dSWill Pazner # map [0,1] to [0,1] varying the mesh density 10*6cf3b68dSWill Pazner coords[i] = 0.5 + 1.0/sqrt(3.0)*sin((2.0/3.0)*pi*(coords[i] - 0.5)) 11*6cf3b68dSWill Pazner end 12*6cf3b68dSWill Pazner exact_volume = 1.0 13*6cf3b68dSWill Pazner else 14*6cf3b68dSWill Pazner num_nodes = mesh_size÷dim 15*6cf3b68dSWill Pazner @inbounds @simd for i = 1:num_nodes 16*6cf3b68dSWill Pazner # map (x,y) from [0,1]x[0,1] to the quarter annulus with polar 17*6cf3b68dSWill Pazner # coordinates, (r,phi) in [1,2]x[0,pi/2] with area = 3/4*pi 18*6cf3b68dSWill Pazner u = coords[i] 19*6cf3b68dSWill Pazner v = coords[i+num_nodes] 20*6cf3b68dSWill Pazner u = 1.0 + u 21*6cf3b68dSWill Pazner v = pi/2*v 22*6cf3b68dSWill Pazner coords[i] = u*cos(v) 23*6cf3b68dSWill Pazner coords[i+num_nodes] = u*sin(v) 24*6cf3b68dSWill Pazner end 25*6cf3b68dSWill Pazner exact_volume = 3.0/4.0*pi 26*6cf3b68dSWill Pazner end 27*6cf3b68dSWill Pazner return exact_volume 28*6cf3b68dSWill Pazner end 29*6cf3b68dSWill Paznerend 30*6cf3b68dSWill Pazner 31*6cf3b68dSWill Paznerfunction run_ex1(; ceed_spec, dim, mesh_order, sol_order, num_qpts, prob_size, gallery) 32*6cf3b68dSWill Pazner ncompx = dim 33*6cf3b68dSWill Pazner prob_size < 0 && (prob_size = 256*1024) 34*6cf3b68dSWill Pazner 35*6cf3b68dSWill Pazner ceed = Ceed(ceed_spec) 36*6cf3b68dSWill Pazner mesh_basis = 37*6cf3b68dSWill Pazner create_tensor_h1_lagrange_basis(ceed, dim, ncompx, mesh_order + 1, num_qpts, GAUSS) 38*6cf3b68dSWill Pazner sol_basis = 39*6cf3b68dSWill Pazner create_tensor_h1_lagrange_basis(ceed, dim, 1, sol_order + 1, num_qpts, GAUSS) 40*6cf3b68dSWill Pazner 41*6cf3b68dSWill Pazner # Determine the mesh size based on the given approximate problem size. 42*6cf3b68dSWill Pazner nxyz = get_cartesian_mesh_size(dim, sol_order, prob_size) 43*6cf3b68dSWill Pazner println("Mesh size: ", nxyz) 44*6cf3b68dSWill Pazner 45*6cf3b68dSWill Pazner # Build CeedElemRestriction objects describing the mesh and solution discrete 46*6cf3b68dSWill Pazner # representations. 47*6cf3b68dSWill Pazner mesh_size, mesh_restr, _ = 48*6cf3b68dSWill Pazner build_cartesian_restriction(ceed, dim, nxyz, mesh_order, ncompx, num_qpts) 49*6cf3b68dSWill Pazner sol_size, sol_restr, sol_restr_i = build_cartesian_restriction( 50*6cf3b68dSWill Pazner ceed, 51*6cf3b68dSWill Pazner dim, 52*6cf3b68dSWill Pazner nxyz, 53*6cf3b68dSWill Pazner sol_order, 54*6cf3b68dSWill Pazner 1, 55*6cf3b68dSWill Pazner num_qpts, 56*6cf3b68dSWill Pazner mode=RestrictionAndStrided, 57*6cf3b68dSWill Pazner ) 58*6cf3b68dSWill Pazner println("Number of mesh nodes : ", div(mesh_size, dim)) 59*6cf3b68dSWill Pazner println("Number of solution nodes : ", sol_size) 60*6cf3b68dSWill Pazner 61*6cf3b68dSWill Pazner # Create a CeedVector with the mesh coordinates. 62*6cf3b68dSWill Pazner mesh_coords = CeedVector(ceed, mesh_size) 63*6cf3b68dSWill Pazner set_cartesian_mesh_coords!(dim, nxyz, mesh_order, mesh_coords) 64*6cf3b68dSWill Pazner # Apply a transformation to the mesh. 65*6cf3b68dSWill Pazner exact_vol = transform_mesh_coords!(dim, mesh_size, mesh_coords) 66*6cf3b68dSWill Pazner 67*6cf3b68dSWill Pazner # Create the Q-function that builds the mass operator (i.e. computes its 68*6cf3b68dSWill Pazner # quadrature data) and set its context data. 69*6cf3b68dSWill Pazner if !gallery 70*6cf3b68dSWill Pazner @interior_qf build_qfunc = ( 71*6cf3b68dSWill Pazner ceed, 72*6cf3b68dSWill Pazner dim=dim, 73*6cf3b68dSWill Pazner (J, :in, EVAL_GRAD, dim, dim), 74*6cf3b68dSWill Pazner (w, :in, EVAL_WEIGHT), 75*6cf3b68dSWill Pazner (qdata, :out, EVAL_NONE), 76*6cf3b68dSWill Pazner begin 77*6cf3b68dSWill Pazner qdata .= w*det(J) 78*6cf3b68dSWill Pazner end, 79*6cf3b68dSWill Pazner ) 80*6cf3b68dSWill Pazner else 81*6cf3b68dSWill Pazner build_qfunc = create_interior_qfunction(ceed, "Mass$(dim)DBuild") 82*6cf3b68dSWill Pazner end 83*6cf3b68dSWill Pazner 84*6cf3b68dSWill Pazner # Create the operator that builds the quadrature data for the mass operator. 85*6cf3b68dSWill Pazner build_oper = Operator( 86*6cf3b68dSWill Pazner ceed, 87*6cf3b68dSWill Pazner qf=build_qfunc, 88*6cf3b68dSWill Pazner fields=[ 89*6cf3b68dSWill Pazner (gallery ? :dx : :J, mesh_restr, mesh_basis, CeedVectorActive()), 90*6cf3b68dSWill Pazner (gallery ? :weights : :w, ElemRestrictionNone(), mesh_basis, CeedVectorNone()), 91*6cf3b68dSWill Pazner (:qdata, sol_restr_i, BasisCollocated(), CeedVectorActive()), 92*6cf3b68dSWill Pazner ], 93*6cf3b68dSWill Pazner ) 94*6cf3b68dSWill Pazner 95*6cf3b68dSWill Pazner # Compute the quadrature data for the mass operator. 96*6cf3b68dSWill Pazner elem_qpts = num_qpts^dim 97*6cf3b68dSWill Pazner num_elem = prod(nxyz) 98*6cf3b68dSWill Pazner qdata = CeedVector(ceed, num_elem*elem_qpts) 99*6cf3b68dSWill Pazner 100*6cf3b68dSWill Pazner print("Computing the quadrature data for the mass operator ...") 101*6cf3b68dSWill Pazner flush(stdout) 102*6cf3b68dSWill Pazner apply!(build_oper, mesh_coords, qdata) 103*6cf3b68dSWill Pazner println(" done.") 104*6cf3b68dSWill Pazner 105*6cf3b68dSWill Pazner # Create the Q-function that defines the action of the mass operator. 106*6cf3b68dSWill Pazner if !gallery 107*6cf3b68dSWill Pazner @interior_qf apply_qfunc = ( 108*6cf3b68dSWill Pazner ceed, 109*6cf3b68dSWill Pazner (u, :in, EVAL_INTERP), 110*6cf3b68dSWill Pazner (qdata, :in, EVAL_NONE), 111*6cf3b68dSWill Pazner (v, :out, EVAL_INTERP), 112*6cf3b68dSWill Pazner begin 113*6cf3b68dSWill Pazner v .= qdata*u 114*6cf3b68dSWill Pazner end, 115*6cf3b68dSWill Pazner ) 116*6cf3b68dSWill Pazner else 117*6cf3b68dSWill Pazner apply_qfunc = create_interior_qfunction(ceed, "MassApply") 118*6cf3b68dSWill Pazner end 119*6cf3b68dSWill Pazner 120*6cf3b68dSWill Pazner # Create the mass operator. 121*6cf3b68dSWill Pazner oper = Operator( 122*6cf3b68dSWill Pazner ceed, 123*6cf3b68dSWill Pazner qf=apply_qfunc, 124*6cf3b68dSWill Pazner fields=[ 125*6cf3b68dSWill Pazner (:u, sol_restr, sol_basis, CeedVectorActive()), 126*6cf3b68dSWill Pazner (:qdata, sol_restr_i, BasisCollocated(), qdata), 127*6cf3b68dSWill Pazner (:v, sol_restr, sol_basis, CeedVectorActive()), 128*6cf3b68dSWill Pazner ], 129*6cf3b68dSWill Pazner ) 130*6cf3b68dSWill Pazner 131*6cf3b68dSWill Pazner # Compute the mesh volume using the mass operator: vol = 1^T \cdot M \cdot 1 132*6cf3b68dSWill Pazner print("Computing the mesh volume using the formula: vol = 1^T.M.1 ...") 133*6cf3b68dSWill Pazner flush(stdout) 134*6cf3b68dSWill Pazner # Create auxiliary solution-size vectors. 135*6cf3b68dSWill Pazner u = CeedVector(ceed, sol_size) 136*6cf3b68dSWill Pazner v = CeedVector(ceed, sol_size) 137*6cf3b68dSWill Pazner # Initialize 'u' with ones. 138*6cf3b68dSWill Pazner u[] = 1.0 139*6cf3b68dSWill Pazner # Apply the mass operator: 'u' -> 'v'. 140*6cf3b68dSWill Pazner apply!(oper, u, v) 141*6cf3b68dSWill Pazner # Compute and print the sum of the entries of 'v' giving the mesh volume. 142*6cf3b68dSWill Pazner vol = witharray_read(sum, v, MEM_HOST) 143*6cf3b68dSWill Pazner 144*6cf3b68dSWill Pazner println(" done.") 145*6cf3b68dSWill Pazner @printf("Exact mesh volume : % .14g\n", exact_vol) 146*6cf3b68dSWill Pazner @printf("Computed mesh volume : % .14g\n", vol) 147*6cf3b68dSWill Pazner @printf("Volume error : % .14g\n", vol - exact_vol) 148*6cf3b68dSWill Paznerend 149*6cf3b68dSWill Pazner 150*6cf3b68dSWill Paznerrun_ex1( 151*6cf3b68dSWill Pazner ceed_spec="/cpu/self", 152*6cf3b68dSWill Pazner dim=3, 153*6cf3b68dSWill Pazner mesh_order=4, 154*6cf3b68dSWill Pazner sol_order=4, 155*6cf3b68dSWill Pazner num_qpts=4 + 2, 156*6cf3b68dSWill Pazner prob_size=-1, 157*6cf3b68dSWill Pazner gallery=false, 158*6cf3b68dSWill Pazner) 159