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