xref: /libCEED/julia/LibCEED.jl/examples/ex1-volume.jl (revision 21f16bf6c2940c092555e126518ed0c98a2b88a9)
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