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