xref: /libCEED/julia/LibCEED.jl/examples/ex2-surface.jl (revision 21f16bf6c2940c092555e126518ed0c98a2b88a9)
16cf3b68dSWill Paznerusing LibCEED, Printf, StaticArrays
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        @inbounds @simd for i = 1:mesh_size
86cf3b68dSWill Pazner            # map [0,1] to [0,1] varying the mesh density
96cf3b68dSWill Pazner            coords[i] = 0.5 + 1.0/sqrt(3.0)*sin((2.0/3.0)*pi*(coords[i] - 0.5))
106cf3b68dSWill Pazner        end
116cf3b68dSWill Pazner    end
126cf3b68dSWill Pazner    exact_sa = (dim == 1 ? 2 : dim == 2 ? 4 : 6)
136cf3b68dSWill Paznerend
146cf3b68dSWill Pazner
156cf3b68dSWill Paznerfunction run_ex2(; ceed_spec, dim, mesh_order, sol_order, num_qpts, prob_size, gallery)
166cf3b68dSWill Pazner    ncompx = dim
176cf3b68dSWill Pazner    prob_size < 0 && (prob_size = 256*1024)
186cf3b68dSWill Pazner
196cf3b68dSWill Pazner    mesh_order = max(mesh_order, sol_order)
206cf3b68dSWill Pazner    sol_order = mesh_order
216cf3b68dSWill Pazner
226cf3b68dSWill Pazner    ceed = Ceed(ceed_spec)
236cf3b68dSWill Pazner    mesh_basis =
246cf3b68dSWill Pazner        create_tensor_h1_lagrange_basis(ceed, dim, ncompx, mesh_order + 1, num_qpts, GAUSS)
256cf3b68dSWill Pazner    sol_basis =
266cf3b68dSWill Pazner        create_tensor_h1_lagrange_basis(ceed, dim, 1, sol_order + 1, num_qpts, GAUSS)
276cf3b68dSWill Pazner
286cf3b68dSWill Pazner    nxyz = get_cartesian_mesh_size(dim, sol_order, prob_size)
296cf3b68dSWill Pazner    println("Mesh size: ", nxyz)
306cf3b68dSWill Pazner
316cf3b68dSWill Pazner    # Build CeedElemRestriction objects describing the mesh and solution discrete
326cf3b68dSWill Pazner    # representations.
33*edb2538eSJeremy L Thompson    mesh_size, mesh_rstr, _ = build_cartesian_restriction(
346cf3b68dSWill Pazner        ceed,
356cf3b68dSWill Pazner        dim,
366cf3b68dSWill Pazner        nxyz,
376cf3b68dSWill Pazner        mesh_order,
386cf3b68dSWill Pazner        ncompx,
396cf3b68dSWill Pazner        num_qpts,
406cf3b68dSWill Pazner        mode=RestrictionOnly,
416cf3b68dSWill Pazner    )
42*edb2538eSJeremy L Thompson    sol_size, _, qdata_rstr_i = build_cartesian_restriction(
436cf3b68dSWill Pazner        ceed,
446cf3b68dSWill Pazner        dim,
456cf3b68dSWill Pazner        nxyz,
466cf3b68dSWill Pazner        sol_order,
476cf3b68dSWill Pazner        div(dim*(dim + 1), 2),
486cf3b68dSWill Pazner        num_qpts,
496cf3b68dSWill Pazner        mode=StridedOnly,
506cf3b68dSWill Pazner    )
51*edb2538eSJeremy L Thompson    sol_size, sol_rstr, sol_rstr_i = build_cartesian_restriction(
526cf3b68dSWill Pazner        ceed,
536cf3b68dSWill Pazner        dim,
546cf3b68dSWill Pazner        nxyz,
556cf3b68dSWill Pazner        sol_order,
566cf3b68dSWill Pazner        1,
576cf3b68dSWill Pazner        num_qpts,
586cf3b68dSWill Pazner        mode=RestrictionAndStrided,
596cf3b68dSWill Pazner    )
606cf3b68dSWill Pazner    println("Number of mesh nodes     : ", div(mesh_size, dim))
616cf3b68dSWill Pazner    println("Number of solution nodes : ", sol_size)
626cf3b68dSWill Pazner
636cf3b68dSWill Pazner    # Create a CeedVector with the mesh coordinates.
646cf3b68dSWill Pazner    mesh_coords = CeedVector(ceed, mesh_size)
656cf3b68dSWill Pazner    set_cartesian_mesh_coords!(dim, nxyz, mesh_order, mesh_coords)
666cf3b68dSWill Pazner
676cf3b68dSWill Pazner    # Apply a transformation to the mesh.
686cf3b68dSWill Pazner    exact_sa = transform_mesh_coords!(dim, mesh_size, mesh_coords)
696cf3b68dSWill Pazner
706cf3b68dSWill Pazner    # Create the Q-function that builds the diffusion operator (i.e. computes its
716cf3b68dSWill Pazner    # quadrature data) and set its context data.
726cf3b68dSWill Pazner    if !gallery
736cf3b68dSWill Pazner        @interior_qf build_qfunc = (
746cf3b68dSWill Pazner            ceed,
756cf3b68dSWill Pazner            dim=dim,
766cf3b68dSWill Pazner            (J, :in, EVAL_GRAD, dim, dim),
776cf3b68dSWill Pazner            (w, :in, EVAL_WEIGHT),
786cf3b68dSWill Pazner            (qdata, :out, EVAL_NONE, dim*(dim + 1)÷2),
796cf3b68dSWill Pazner            begin
806cf3b68dSWill Pazner                Jinv = inv(J)
816cf3b68dSWill Pazner                qdata .= setvoigt(w*det(J)*Jinv*Jinv')
826cf3b68dSWill Pazner            end,
836cf3b68dSWill Pazner        )
846cf3b68dSWill Pazner    else
856cf3b68dSWill Pazner        build_qfunc = create_interior_qfunction(ceed, "Poisson$(dim)DBuild")
866cf3b68dSWill Pazner    end
876cf3b68dSWill Pazner
886cf3b68dSWill Pazner    # Create the operator that builds the quadrature data for the diffusion
896cf3b68dSWill Pazner    # operator.
906cf3b68dSWill Pazner    build_oper = Operator(
916cf3b68dSWill Pazner        ceed,
926cf3b68dSWill Pazner        qf=build_qfunc,
936cf3b68dSWill Pazner        fields=[
94*edb2538eSJeremy L Thompson            (gallery ? :dx : :J, mesh_rstr, mesh_basis, CeedVectorActive()),
956cf3b68dSWill Pazner            (gallery ? :weights : :w, ElemRestrictionNone(), mesh_basis, CeedVectorNone()),
96*edb2538eSJeremy L Thompson            (:qdata, qdata_rstr_i, BasisNone(), CeedVectorActive()),
976cf3b68dSWill Pazner        ],
986cf3b68dSWill Pazner    )
996cf3b68dSWill Pazner
1006cf3b68dSWill Pazner    # Compute the quadrature data for the diffusion operator.
1016cf3b68dSWill Pazner    elem_qpts = num_qpts^dim
1026cf3b68dSWill Pazner    num_elem = prod(nxyz)
1036cf3b68dSWill Pazner    qdata = CeedVector(ceed, num_elem*elem_qpts*div(dim*(dim + 1), 2))
1046cf3b68dSWill Pazner    print("Computing the quadrature data for the diffusion operator ...")
1056cf3b68dSWill Pazner    flush(stdout)
1066cf3b68dSWill Pazner    apply!(build_oper, mesh_coords, qdata)
1076cf3b68dSWill Pazner    println(" done.")
1086cf3b68dSWill Pazner
1096cf3b68dSWill Pazner    # Create the Q-function that defines the action of the diffusion operator.
1106cf3b68dSWill Pazner    if !gallery
1116cf3b68dSWill Pazner        @interior_qf apply_qfunc = (
1126cf3b68dSWill Pazner            ceed,
1136cf3b68dSWill Pazner            dim=dim,
1146cf3b68dSWill Pazner            (du, :in, EVAL_GRAD, dim),
1156cf3b68dSWill Pazner            (qdata, :in, EVAL_NONE, dim*(dim + 1)÷2),
1166cf3b68dSWill Pazner            (dv, :out, EVAL_GRAD, dim),
1176cf3b68dSWill Pazner            begin
1186cf3b68dSWill Pazner                dXdxdXdxT = getvoigt(qdata)
1196cf3b68dSWill Pazner                dv .= dXdxdXdxT*du
1206cf3b68dSWill Pazner            end,
1216cf3b68dSWill Pazner        )
1226cf3b68dSWill Pazner    else
1236cf3b68dSWill Pazner        apply_qfunc = create_interior_qfunction(ceed, "Poisson$(dim)DApply")
1246cf3b68dSWill Pazner    end
1256cf3b68dSWill Pazner
1266cf3b68dSWill Pazner    # Create the diffusion operator.
1276cf3b68dSWill Pazner    oper = Operator(
1286cf3b68dSWill Pazner        ceed,
1296cf3b68dSWill Pazner        qf=apply_qfunc,
1306cf3b68dSWill Pazner        fields=[
131*edb2538eSJeremy L Thompson            (:du, sol_rstr, sol_basis, CeedVectorActive()),
132*edb2538eSJeremy L Thompson            (:qdata, qdata_rstr_i, BasisNone(), qdata),
133*edb2538eSJeremy L Thompson            (:dv, sol_rstr, sol_basis, CeedVectorActive()),
1346cf3b68dSWill Pazner        ],
1356cf3b68dSWill Pazner    )
1366cf3b68dSWill Pazner
1376cf3b68dSWill Pazner    # Compute the mesh surface area using the diff operator:
1386cf3b68dSWill Pazner    #                                             sa = 1^T \cdot abs( K \cdot x).
1396cf3b68dSWill Pazner    print("Computing the mesh surface area using the formula: sa = 1^T.|K.x| ...")
1406cf3b68dSWill Pazner    flush(stdout)
1416cf3b68dSWill Pazner
1426cf3b68dSWill Pazner    # Create auxiliary solution-size vectors.
1436cf3b68dSWill Pazner    u = CeedVector(ceed, sol_size)
1446cf3b68dSWill Pazner    v = CeedVector(ceed, sol_size)
1456cf3b68dSWill Pazner    # Initialize 'u' with sum of coordinates, x+y+z.
1469c774eddSJeremy L Thompson    u[] = 0.0
1476cf3b68dSWill Pazner    @witharray_read(
1486cf3b68dSWill Pazner        x_host = mesh_coords,
1496cf3b68dSWill Pazner        size = (mesh_size÷dim, dim),
1506cf3b68dSWill Pazner        @witharray(u_host = u, size = (sol_size, 1), sum!(u_host, x_host))
1516cf3b68dSWill Pazner    )
1526cf3b68dSWill Pazner
1536cf3b68dSWill Pazner    # Apply the diffusion operator: 'u' -> 'v'.
1546cf3b68dSWill Pazner    apply!(oper, u, v)
1556cf3b68dSWill Pazner    sa = witharray_read(x -> sum(abs, x), v, MEM_HOST)
1566cf3b68dSWill Pazner
1576cf3b68dSWill Pazner    println(" done.")
1586cf3b68dSWill Pazner    @printf("Exact mesh surface area    : % .14g\n", exact_sa)
1596cf3b68dSWill Pazner    @printf("Computed mesh surface area : % .14g\n", sa)
1606cf3b68dSWill Pazner    @printf("Surface area error         : % .14g\n", sa - exact_sa)
1616cf3b68dSWill Paznerend
1626cf3b68dSWill Pazner
1636cf3b68dSWill Paznerrun_ex2(
1646cf3b68dSWill Pazner    ceed_spec="/cpu/self",
1656cf3b68dSWill Pazner    dim=3,
1666cf3b68dSWill Pazner    mesh_order=4,
1676cf3b68dSWill Pazner    sol_order=4,
1686cf3b68dSWill Pazner    num_qpts=6,
1696cf3b68dSWill Pazner    prob_size=-1,
1706cf3b68dSWill Pazner    gallery=false,
1716cf3b68dSWill Pazner)
172