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