16cf3b68dSWill Paznerusing LibCEED, Printf 26cf3b68dSWill Pazner 36cf3b68dSWill Paznerinclude("common.jl") 46cf3b68dSWill Pazner 56cf3b68dSWill Paznerfunction transform_mesh_coords!(dim, mesh_size, mesh_coords) 66cf3b68dSWill Pazner @witharray coords = mesh_coords begin 76cf3b68dSWill Pazner if dim == 1 86cf3b68dSWill Pazner for i = 1:mesh_size 96cf3b68dSWill Pazner # map [0,1] to [0,1] varying the mesh density 106cf3b68dSWill Pazner coords[i] = 0.5 + 1.0/sqrt(3.0)*sin((2.0/3.0)*pi*(coords[i] - 0.5)) 116cf3b68dSWill Pazner end 126cf3b68dSWill Pazner exact_volume = 1.0 136cf3b68dSWill Pazner else 146cf3b68dSWill Pazner num_nodes = mesh_size÷dim 156cf3b68dSWill Pazner @inbounds @simd for i = 1:num_nodes 166cf3b68dSWill Pazner # map (x,y) from [0,1]x[0,1] to the quarter annulus with polar 176cf3b68dSWill Pazner # coordinates, (r,phi) in [1,2]x[0,pi/2] with area = 3/4*pi 186cf3b68dSWill Pazner u = coords[i] 196cf3b68dSWill Pazner v = coords[i+num_nodes] 206cf3b68dSWill Pazner u = 1.0 + u 216cf3b68dSWill Pazner v = pi/2*v 226cf3b68dSWill Pazner coords[i] = u*cos(v) 236cf3b68dSWill Pazner coords[i+num_nodes] = u*sin(v) 246cf3b68dSWill Pazner end 256cf3b68dSWill Pazner exact_volume = 3.0/4.0*pi 266cf3b68dSWill Pazner end 276cf3b68dSWill Pazner return exact_volume 286cf3b68dSWill Pazner end 296cf3b68dSWill Paznerend 306cf3b68dSWill Pazner 316cf3b68dSWill Paznerfunction run_ex1(; ceed_spec, dim, mesh_order, sol_order, num_qpts, prob_size, gallery) 326cf3b68dSWill Pazner ncompx = dim 336cf3b68dSWill Pazner prob_size < 0 && (prob_size = 256*1024) 346cf3b68dSWill Pazner 356cf3b68dSWill Pazner ceed = Ceed(ceed_spec) 366cf3b68dSWill Pazner mesh_basis = 376cf3b68dSWill Pazner create_tensor_h1_lagrange_basis(ceed, dim, ncompx, mesh_order + 1, num_qpts, GAUSS) 386cf3b68dSWill Pazner sol_basis = 396cf3b68dSWill Pazner create_tensor_h1_lagrange_basis(ceed, dim, 1, sol_order + 1, num_qpts, GAUSS) 406cf3b68dSWill Pazner 416cf3b68dSWill Pazner # Determine the mesh size based on the given approximate problem size. 426cf3b68dSWill Pazner nxyz = get_cartesian_mesh_size(dim, sol_order, prob_size) 436cf3b68dSWill Pazner println("Mesh size: ", nxyz) 446cf3b68dSWill Pazner 456cf3b68dSWill Pazner # Build CeedElemRestriction objects describing the mesh and solution discrete 466cf3b68dSWill Pazner # representations. 47*edb2538eSJeremy L Thompson mesh_size, mesh_rstr, _ = 486cf3b68dSWill Pazner build_cartesian_restriction(ceed, dim, nxyz, mesh_order, ncompx, num_qpts) 49*edb2538eSJeremy L Thompson sol_size, sol_rstr, sol_rstr_i = build_cartesian_restriction( 506cf3b68dSWill Pazner ceed, 516cf3b68dSWill Pazner dim, 526cf3b68dSWill Pazner nxyz, 536cf3b68dSWill Pazner sol_order, 546cf3b68dSWill Pazner 1, 556cf3b68dSWill Pazner num_qpts, 566cf3b68dSWill Pazner mode=RestrictionAndStrided, 576cf3b68dSWill Pazner ) 586cf3b68dSWill Pazner println("Number of mesh nodes : ", div(mesh_size, dim)) 596cf3b68dSWill Pazner println("Number of solution nodes : ", sol_size) 606cf3b68dSWill Pazner 616cf3b68dSWill Pazner # Create a CeedVector with the mesh coordinates. 626cf3b68dSWill Pazner mesh_coords = CeedVector(ceed, mesh_size) 636cf3b68dSWill Pazner set_cartesian_mesh_coords!(dim, nxyz, mesh_order, mesh_coords) 646cf3b68dSWill Pazner # Apply a transformation to the mesh. 656cf3b68dSWill Pazner exact_vol = transform_mesh_coords!(dim, mesh_size, mesh_coords) 666cf3b68dSWill Pazner 676cf3b68dSWill Pazner # Create the Q-function that builds the mass operator (i.e. computes its 686cf3b68dSWill Pazner # quadrature data) and set its context data. 696cf3b68dSWill Pazner if !gallery 706cf3b68dSWill Pazner @interior_qf build_qfunc = ( 716cf3b68dSWill Pazner ceed, 726cf3b68dSWill Pazner dim=dim, 736cf3b68dSWill Pazner (J, :in, EVAL_GRAD, dim, dim), 746cf3b68dSWill Pazner (w, :in, EVAL_WEIGHT), 756cf3b68dSWill Pazner (qdata, :out, EVAL_NONE), 766cf3b68dSWill Pazner begin 776cf3b68dSWill Pazner qdata .= w*det(J) 786cf3b68dSWill Pazner end, 796cf3b68dSWill Pazner ) 806cf3b68dSWill Pazner else 816cf3b68dSWill Pazner build_qfunc = create_interior_qfunction(ceed, "Mass$(dim)DBuild") 826cf3b68dSWill Pazner end 836cf3b68dSWill Pazner 846cf3b68dSWill Pazner # Create the operator that builds the quadrature data for the mass operator. 856cf3b68dSWill Pazner build_oper = Operator( 866cf3b68dSWill Pazner ceed, 876cf3b68dSWill Pazner qf=build_qfunc, 886cf3b68dSWill Pazner fields=[ 89*edb2538eSJeremy L Thompson (gallery ? :dx : :J, mesh_rstr, mesh_basis, CeedVectorActive()), 906cf3b68dSWill Pazner (gallery ? :weights : :w, ElemRestrictionNone(), mesh_basis, CeedVectorNone()), 91*edb2538eSJeremy L Thompson (:qdata, sol_rstr_i, BasisNone(), CeedVectorActive()), 926cf3b68dSWill Pazner ], 936cf3b68dSWill Pazner ) 946cf3b68dSWill Pazner 956cf3b68dSWill Pazner # Compute the quadrature data for the mass operator. 966cf3b68dSWill Pazner elem_qpts = num_qpts^dim 976cf3b68dSWill Pazner num_elem = prod(nxyz) 986cf3b68dSWill Pazner qdata = CeedVector(ceed, num_elem*elem_qpts) 996cf3b68dSWill Pazner 1006cf3b68dSWill Pazner print("Computing the quadrature data for the mass operator ...") 1016cf3b68dSWill Pazner flush(stdout) 1026cf3b68dSWill Pazner apply!(build_oper, mesh_coords, qdata) 1036cf3b68dSWill Pazner println(" done.") 1046cf3b68dSWill Pazner 1056cf3b68dSWill Pazner # Create the Q-function that defines the action of the mass operator. 1066cf3b68dSWill Pazner if !gallery 1076cf3b68dSWill Pazner @interior_qf apply_qfunc = ( 1086cf3b68dSWill Pazner ceed, 1096cf3b68dSWill Pazner (u, :in, EVAL_INTERP), 1106cf3b68dSWill Pazner (qdata, :in, EVAL_NONE), 1116cf3b68dSWill Pazner (v, :out, EVAL_INTERP), 1126cf3b68dSWill Pazner begin 1136cf3b68dSWill Pazner v .= qdata*u 1146cf3b68dSWill Pazner end, 1156cf3b68dSWill Pazner ) 1166cf3b68dSWill Pazner else 1176cf3b68dSWill Pazner apply_qfunc = create_interior_qfunction(ceed, "MassApply") 1186cf3b68dSWill Pazner end 1196cf3b68dSWill Pazner 1206cf3b68dSWill Pazner # Create the mass operator. 1216cf3b68dSWill Pazner oper = Operator( 1226cf3b68dSWill Pazner ceed, 1236cf3b68dSWill Pazner qf=apply_qfunc, 1246cf3b68dSWill Pazner fields=[ 125*edb2538eSJeremy L Thompson (:u, sol_rstr, sol_basis, CeedVectorActive()), 126*edb2538eSJeremy L Thompson (:qdata, sol_rstr_i, BasisNone(), qdata), 127*edb2538eSJeremy L Thompson (:v, sol_rstr, sol_basis, CeedVectorActive()), 1286cf3b68dSWill Pazner ], 1296cf3b68dSWill Pazner ) 1306cf3b68dSWill Pazner 1316cf3b68dSWill Pazner # Compute the mesh volume using the mass operator: vol = 1^T \cdot M \cdot 1 1326cf3b68dSWill Pazner print("Computing the mesh volume using the formula: vol = 1^T.M.1 ...") 1336cf3b68dSWill Pazner flush(stdout) 1346cf3b68dSWill Pazner # Create auxiliary solution-size vectors. 1356cf3b68dSWill Pazner u = CeedVector(ceed, sol_size) 1366cf3b68dSWill Pazner v = CeedVector(ceed, sol_size) 1376cf3b68dSWill Pazner # Initialize 'u' with ones. 1386cf3b68dSWill Pazner u[] = 1.0 1396cf3b68dSWill Pazner # Apply the mass operator: 'u' -> 'v'. 1406cf3b68dSWill Pazner apply!(oper, u, v) 1416cf3b68dSWill Pazner # Compute and print the sum of the entries of 'v' giving the mesh volume. 1426cf3b68dSWill Pazner vol = witharray_read(sum, v, MEM_HOST) 1436cf3b68dSWill Pazner 1446cf3b68dSWill Pazner println(" done.") 1456cf3b68dSWill Pazner @printf("Exact mesh volume : % .14g\n", exact_vol) 1466cf3b68dSWill Pazner @printf("Computed mesh volume : % .14g\n", vol) 1476cf3b68dSWill Pazner @printf("Volume error : % .14g\n", vol - exact_vol) 1486cf3b68dSWill Paznerend 1496cf3b68dSWill Pazner 1506cf3b68dSWill Paznerrun_ex1( 1516cf3b68dSWill Pazner ceed_spec="/cpu/self", 1526cf3b68dSWill Pazner dim=3, 1536cf3b68dSWill Pazner mesh_order=4, 1546cf3b68dSWill Pazner sol_order=4, 1556cf3b68dSWill Pazner num_qpts=4 + 2, 1566cf3b68dSWill Pazner prob_size=-1, 1576cf3b68dSWill Pazner gallery=false, 1586cf3b68dSWill Pazner) 159