xref: /libCEED/examples/rust/ex1-volume-vector/src/main.rs (revision 3eb59678ecb8a0fe884fb9297a6048221d053835)
1*3eb59678SJeremy L Thompson // Copyright (c) 2017-2025, Lawrence Livermore National Security, LLC and other CEED contributors.
2*3eb59678SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3*3eb59678SJeremy L Thompson //
4*3eb59678SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5*3eb59678SJeremy L Thompson //
6*3eb59678SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7*3eb59678SJeremy L Thompson //
8*3eb59678SJeremy L Thompson //                             libCEED Example 3
9*3eb59678SJeremy L Thompson //
10*3eb59678SJeremy L Thompson // This example illustrates a simple usage of libCEED to compute the volume of a
11*3eb59678SJeremy L Thompson // 3D body using matrix-free application of a mass operator.  Arbitrary mesh and
12*3eb59678SJeremy L Thompson // solution orders in 1D, 2D and 3D are supported from the same code. This
13*3eb59678SJeremy L Thompson // calculation is executed in triplicate with a 3 component vector system.
14*3eb59678SJeremy L Thompson //
15*3eb59678SJeremy L Thompson // The example has no dependencies, and is designed to be self-contained. For
16*3eb59678SJeremy L Thompson // additional examples that use external discretization libraries (MFEM, PETSc,
17*3eb59678SJeremy L Thompson // etc.) see the subdirectories in libceed/examples.
18*3eb59678SJeremy L Thompson //
19*3eb59678SJeremy L Thompson // All libCEED objects use a Ceed device object constructed based on a command
20*3eb59678SJeremy L Thompson // line argument (-ceed).
21*3eb59678SJeremy L Thompson 
22*3eb59678SJeremy L Thompson use clap::Parser;
23*3eb59678SJeremy L Thompson use libceed::{
24*3eb59678SJeremy L Thompson     BasisOpt, Ceed, ElemRestrictionOpt, QFunctionInputs, QFunctionOpt, QFunctionOutputs, VectorOpt,
25*3eb59678SJeremy L Thompson };
26*3eb59678SJeremy L Thompson mod opt;
27*3eb59678SJeremy L Thompson mod transform;
28*3eb59678SJeremy L Thompson 
29*3eb59678SJeremy L Thompson // ----------------------------------------------------------------------------
30*3eb59678SJeremy L Thompson // Example 3
31*3eb59678SJeremy L Thompson // ----------------------------------------------------------------------------
32*3eb59678SJeremy L Thompson fn main() -> libceed::Result<()> {
33*3eb59678SJeremy L Thompson     let options = opt::Opt::parse();
34*3eb59678SJeremy L Thompson     example_1_vector(options)
35*3eb59678SJeremy L Thompson }
36*3eb59678SJeremy L Thompson 
37*3eb59678SJeremy L Thompson #[allow(clippy::erasing_op)]
38*3eb59678SJeremy L Thompson #[allow(clippy::identity_op)]
39*3eb59678SJeremy L Thompson fn example_1_vector(options: opt::Opt) -> libceed::Result<()> {
40*3eb59678SJeremy L Thompson     // Process command line arguments
41*3eb59678SJeremy L Thompson     let opt::Opt {
42*3eb59678SJeremy L Thompson         ceed_spec,
43*3eb59678SJeremy L Thompson         dim,
44*3eb59678SJeremy L Thompson         mesh_degree,
45*3eb59678SJeremy L Thompson         solution_degree,
46*3eb59678SJeremy L Thompson         num_qpts,
47*3eb59678SJeremy L Thompson         problem_size_requested,
48*3eb59678SJeremy L Thompson         test,
49*3eb59678SJeremy L Thompson         quiet,
50*3eb59678SJeremy L Thompson         gallery,
51*3eb59678SJeremy L Thompson     } = options;
52*3eb59678SJeremy L Thompson     assert!((0..=3).contains(&dim));
53*3eb59678SJeremy L Thompson     assert!(mesh_degree >= 1);
54*3eb59678SJeremy L Thompson     assert!(solution_degree >= 1);
55*3eb59678SJeremy L Thompson     assert!(num_qpts >= 1);
56*3eb59678SJeremy L Thompson     let ncomp_x = dim;
57*3eb59678SJeremy L Thompson     let problem_size: i64 = if problem_size_requested < 0 {
58*3eb59678SJeremy L Thompson         if test {
59*3eb59678SJeremy L Thompson             8 * 16
60*3eb59678SJeremy L Thompson         } else {
61*3eb59678SJeremy L Thompson             256 * 1024
62*3eb59678SJeremy L Thompson         }
63*3eb59678SJeremy L Thompson     } else {
64*3eb59678SJeremy L Thompson         problem_size_requested
65*3eb59678SJeremy L Thompson     };
66*3eb59678SJeremy L Thompson     let ncomp_u = 3;
67*3eb59678SJeremy L Thompson 
68*3eb59678SJeremy L Thompson     // Summary output
69*3eb59678SJeremy L Thompson     if !quiet {
70*3eb59678SJeremy L Thompson         println!("Selected options: [command line option] : <current value>");
71*3eb59678SJeremy L Thompson         println!("    Ceed specification [-c] : {}", ceed_spec);
72*3eb59678SJeremy L Thompson         println!("    Mesh dimension     [-d] : {}", dim);
73*3eb59678SJeremy L Thompson         println!("    Mesh degree        [-m] : {}", mesh_degree);
74*3eb59678SJeremy L Thompson         println!("    Solution degree    [-p] : {}", solution_degree);
75*3eb59678SJeremy L Thompson         println!("    Num. 1D quadr. pts [-q] : {}", num_qpts);
76*3eb59678SJeremy L Thompson         println!("    Approx. # unknowns [-s] : {}", problem_size);
77*3eb59678SJeremy L Thompson         println!(
78*3eb59678SJeremy L Thompson             "    QFunction source   [-g] : {}",
79*3eb59678SJeremy L Thompson             if gallery { "gallery" } else { "user closure" }
80*3eb59678SJeremy L Thompson         );
81*3eb59678SJeremy L Thompson     }
82*3eb59678SJeremy L Thompson 
83*3eb59678SJeremy L Thompson     // Initalize ceed context
84*3eb59678SJeremy L Thompson     let ceed = Ceed::init(&ceed_spec);
85*3eb59678SJeremy L Thompson 
86*3eb59678SJeremy L Thompson     // Mesh and solution bases
87*3eb59678SJeremy L Thompson     let basis_mesh = ceed.basis_tensor_H1_Lagrange(
88*3eb59678SJeremy L Thompson         dim,
89*3eb59678SJeremy L Thompson         ncomp_x,
90*3eb59678SJeremy L Thompson         mesh_degree + 1,
91*3eb59678SJeremy L Thompson         num_qpts,
92*3eb59678SJeremy L Thompson         libceed::QuadMode::Gauss,
93*3eb59678SJeremy L Thompson     )?;
94*3eb59678SJeremy L Thompson     let basis_solution = ceed.basis_tensor_H1_Lagrange(
95*3eb59678SJeremy L Thompson         dim,
96*3eb59678SJeremy L Thompson         ncomp_u,
97*3eb59678SJeremy L Thompson         solution_degree + 1,
98*3eb59678SJeremy L Thompson         num_qpts,
99*3eb59678SJeremy L Thompson         libceed::QuadMode::Gauss,
100*3eb59678SJeremy L Thompson     )?;
101*3eb59678SJeremy L Thompson 
102*3eb59678SJeremy L Thompson     // Determine mesh size from approximate problem size
103*3eb59678SJeremy L Thompson     let num_xyz = mesh::cartesian_mesh_size(dim, solution_degree, problem_size);
104*3eb59678SJeremy L Thompson     if !quiet {
105*3eb59678SJeremy L Thompson         print!("\nMesh size                   : nx = {}", num_xyz[0]);
106*3eb59678SJeremy L Thompson         if dim > 1 {
107*3eb59678SJeremy L Thompson             print!(", ny = {}", num_xyz[1]);
108*3eb59678SJeremy L Thompson         }
109*3eb59678SJeremy L Thompson         if dim > 2 {
110*3eb59678SJeremy L Thompson             print!(", nz = {}", num_xyz[2]);
111*3eb59678SJeremy L Thompson         }
112*3eb59678SJeremy L Thompson         println!();
113*3eb59678SJeremy L Thompson     }
114*3eb59678SJeremy L Thompson 
115*3eb59678SJeremy L Thompson     // Build ElemRestriction objects describing the mesh and solution discrete
116*3eb59678SJeremy L Thompson     // representations
117*3eb59678SJeremy L Thompson     let (rstr_mesh, _) =
118*3eb59678SJeremy L Thompson         mesh::build_cartesian_restriction(&ceed, dim, num_xyz, mesh_degree, ncomp_x, num_qpts)?;
119*3eb59678SJeremy L Thompson     let (_, rstr_qdata) =
120*3eb59678SJeremy L Thompson         mesh::build_cartesian_restriction(&ceed, dim, num_xyz, solution_degree, 1, num_qpts)?;
121*3eb59678SJeremy L Thompson     let (rstr_solution, _) =
122*3eb59678SJeremy L Thompson         mesh::build_cartesian_restriction(&ceed, dim, num_xyz, solution_degree, ncomp_u, num_qpts)?;
123*3eb59678SJeremy L Thompson     let mesh_size = rstr_mesh.lvector_size();
124*3eb59678SJeremy L Thompson     let solution_size = rstr_solution.lvector_size();
125*3eb59678SJeremy L Thompson     if !quiet {
126*3eb59678SJeremy L Thompson         println!("Number of mesh nodes        : {}", mesh_size / dim);
127*3eb59678SJeremy L Thompson         println!("Number of solution nodes    : {}", solution_size);
128*3eb59678SJeremy L Thompson     }
129*3eb59678SJeremy L Thompson 
130*3eb59678SJeremy L Thompson     // Create a Vector with the mesh coordinates
131*3eb59678SJeremy L Thompson     let mut mesh_coords = mesh::cartesian_mesh_coords(&ceed, dim, num_xyz, mesh_degree, mesh_size)?;
132*3eb59678SJeremy L Thompson 
133*3eb59678SJeremy L Thompson     // Apply a transformation to the mesh coordinates
134*3eb59678SJeremy L Thompson     let exact_volume = transform::transform_mesh_coordinates(dim, mesh_size, &mut mesh_coords)?;
135*3eb59678SJeremy L Thompson 
136*3eb59678SJeremy L Thompson     // QFunction that builds the quadrature data for the mass operator
137*3eb59678SJeremy L Thompson     // -- QFunction from user closure
138*3eb59678SJeremy L Thompson     let build_mass = move |[jacobian, weights, ..]: QFunctionInputs,
139*3eb59678SJeremy L Thompson                            [qdata, ..]: QFunctionOutputs| {
140*3eb59678SJeremy L Thompson         // Build quadrature data
141*3eb59678SJeremy L Thompson         match dim {
142*3eb59678SJeremy L Thompson             1 => qdata
143*3eb59678SJeremy L Thompson                 .iter_mut()
144*3eb59678SJeremy L Thompson                 .zip(jacobian.iter().zip(weights.iter()))
145*3eb59678SJeremy L Thompson                 .for_each(|(qdata, (j, weight))| *qdata = j * weight),
146*3eb59678SJeremy L Thompson             2 => {
147*3eb59678SJeremy L Thompson                 let q = qdata.len();
148*3eb59678SJeremy L Thompson                 qdata.iter_mut().zip(weights.iter()).enumerate().for_each(
149*3eb59678SJeremy L Thompson                     |(i, (qdata, weight))| {
150*3eb59678SJeremy L Thompson                         *qdata = (jacobian[i + q * 0] * jacobian[i + q * 3]
151*3eb59678SJeremy L Thompson                             - jacobian[i + q * 1] * jacobian[i + q * 2])
152*3eb59678SJeremy L Thompson                             * weight
153*3eb59678SJeremy L Thompson                     },
154*3eb59678SJeremy L Thompson                 );
155*3eb59678SJeremy L Thompson             }
156*3eb59678SJeremy L Thompson             3 => {
157*3eb59678SJeremy L Thompson                 let q = qdata.len();
158*3eb59678SJeremy L Thompson                 qdata.iter_mut().zip(weights.iter()).enumerate().for_each(
159*3eb59678SJeremy L Thompson                     |(i, (qdata, weight))| {
160*3eb59678SJeremy L Thompson                         *qdata = (jacobian[i + q * 0]
161*3eb59678SJeremy L Thompson                             * (jacobian[i + q * 4] * jacobian[i + q * 8]
162*3eb59678SJeremy L Thompson                                 - jacobian[i + q * 5] * jacobian[i + q * 7])
163*3eb59678SJeremy L Thompson                             - jacobian[i + q * 1]
164*3eb59678SJeremy L Thompson                                 * (jacobian[i + q * 3] * jacobian[i + q * 8]
165*3eb59678SJeremy L Thompson                                     - jacobian[i + q * 5] * jacobian[i + q * 6])
166*3eb59678SJeremy L Thompson                             + jacobian[i + q * 2]
167*3eb59678SJeremy L Thompson                                 * (jacobian[i + q * 3] * jacobian[i + q * 7]
168*3eb59678SJeremy L Thompson                                     - jacobian[i + q * 4] * jacobian[i + q * 6]))
169*3eb59678SJeremy L Thompson                             * weight
170*3eb59678SJeremy L Thompson                     },
171*3eb59678SJeremy L Thompson                 );
172*3eb59678SJeremy L Thompson             }
173*3eb59678SJeremy L Thompson             _ => unreachable!(),
174*3eb59678SJeremy L Thompson         };
175*3eb59678SJeremy L Thompson 
176*3eb59678SJeremy L Thompson         // Return clean error code
177*3eb59678SJeremy L Thompson         0
178*3eb59678SJeremy L Thompson     };
179*3eb59678SJeremy L Thompson     let qf_build_closure = ceed
180*3eb59678SJeremy L Thompson         .q_function_interior(1, Box::new(build_mass))?
181*3eb59678SJeremy L Thompson         .input("dx", ncomp_x * dim, libceed::EvalMode::Grad)?
182*3eb59678SJeremy L Thompson         .input("weights", 1, libceed::EvalMode::Weight)?
183*3eb59678SJeremy L Thompson         .output("qdata", 1, libceed::EvalMode::None)?;
184*3eb59678SJeremy L Thompson     // -- QFunction from gallery
185*3eb59678SJeremy L Thompson     let qf_build_named = {
186*3eb59678SJeremy L Thompson         let name = format!("Mass{}DBuild", dim);
187*3eb59678SJeremy L Thompson         ceed.q_function_interior_by_name(&name)?
188*3eb59678SJeremy L Thompson     };
189*3eb59678SJeremy L Thompson     // -- QFunction for use with Operator
190*3eb59678SJeremy L Thompson     let qf_build = if gallery {
191*3eb59678SJeremy L Thompson         QFunctionOpt::SomeQFunctionByName(&qf_build_named)
192*3eb59678SJeremy L Thompson     } else {
193*3eb59678SJeremy L Thompson         QFunctionOpt::SomeQFunction(&qf_build_closure)
194*3eb59678SJeremy L Thompson     };
195*3eb59678SJeremy L Thompson 
196*3eb59678SJeremy L Thompson     // Operator that build the quadrature data for the mass operator
197*3eb59678SJeremy L Thompson     let op_build = ceed
198*3eb59678SJeremy L Thompson         .operator(qf_build, QFunctionOpt::None, QFunctionOpt::None)?
199*3eb59678SJeremy L Thompson         .name("build qdata")?
200*3eb59678SJeremy L Thompson         .field("dx", &rstr_mesh, &basis_mesh, VectorOpt::Active)?
201*3eb59678SJeremy L Thompson         .field(
202*3eb59678SJeremy L Thompson             "weights",
203*3eb59678SJeremy L Thompson             ElemRestrictionOpt::None,
204*3eb59678SJeremy L Thompson             &basis_mesh,
205*3eb59678SJeremy L Thompson             VectorOpt::None,
206*3eb59678SJeremy L Thompson         )?
207*3eb59678SJeremy L Thompson         .field("qdata", &rstr_qdata, BasisOpt::None, VectorOpt::Active)?
208*3eb59678SJeremy L Thompson         .check()?;
209*3eb59678SJeremy L Thompson 
210*3eb59678SJeremy L Thompson     // Compute the quadrature data for the mass operator
211*3eb59678SJeremy L Thompson     let elem_qpts = num_qpts.pow(dim as u32);
212*3eb59678SJeremy L Thompson     let num_elem: usize = num_xyz.iter().take(dim).product();
213*3eb59678SJeremy L Thompson     let mut qdata = ceed.vector(num_elem * elem_qpts)?;
214*3eb59678SJeremy L Thompson     op_build.apply(&mesh_coords, &mut qdata)?;
215*3eb59678SJeremy L Thompson 
216*3eb59678SJeremy L Thompson     // QFunction that applies the mass operator
217*3eb59678SJeremy L Thompson     // -- QFunction from user closure
218*3eb59678SJeremy L Thompson     let apply_mass = move |[u, qdata, ..]: QFunctionInputs, [v, ..]: QFunctionOutputs| {
219*3eb59678SJeremy L Thompson         let q = qdata.len();
220*3eb59678SJeremy L Thompson         // Apply mass operator
221*3eb59678SJeremy L Thompson         for c in 0..ncomp_u {
222*3eb59678SJeremy L Thompson             v.iter_mut()
223*3eb59678SJeremy L Thompson                 .skip(c * q)
224*3eb59678SJeremy L Thompson                 .zip(u.iter().skip(c * q).zip(qdata.iter()))
225*3eb59678SJeremy L Thompson                 .for_each(|(v, (u, w))| *v = u * w);
226*3eb59678SJeremy L Thompson         }
227*3eb59678SJeremy L Thompson         // Return clean error code
228*3eb59678SJeremy L Thompson         0
229*3eb59678SJeremy L Thompson     };
230*3eb59678SJeremy L Thompson     let qf_mass_closure = ceed
231*3eb59678SJeremy L Thompson         .q_function_interior(1, Box::new(apply_mass))?
232*3eb59678SJeremy L Thompson         .input("u", ncomp_u, libceed::EvalMode::Interp)?
233*3eb59678SJeremy L Thompson         .input("qdata", 1, libceed::EvalMode::None)?
234*3eb59678SJeremy L Thompson         .output("v", ncomp_u, libceed::EvalMode::Interp)?;
235*3eb59678SJeremy L Thompson     // -- QFunction from gallery
236*3eb59678SJeremy L Thompson     let qf_mass_named = ceed.q_function_interior_by_name("Vector3MassApply")?;
237*3eb59678SJeremy L Thompson     // -- QFunction for use with Operator
238*3eb59678SJeremy L Thompson     let qf_mass = if gallery {
239*3eb59678SJeremy L Thompson         QFunctionOpt::SomeQFunctionByName(&qf_mass_named)
240*3eb59678SJeremy L Thompson     } else {
241*3eb59678SJeremy L Thompson         QFunctionOpt::SomeQFunction(&qf_mass_closure)
242*3eb59678SJeremy L Thompson     };
243*3eb59678SJeremy L Thompson 
244*3eb59678SJeremy L Thompson     // Mass Operator
245*3eb59678SJeremy L Thompson     let op_mass = ceed
246*3eb59678SJeremy L Thompson         .operator(qf_mass, QFunctionOpt::None, QFunctionOpt::None)?
247*3eb59678SJeremy L Thompson         .name("mass")?
248*3eb59678SJeremy L Thompson         .field("u", &rstr_solution, &basis_solution, VectorOpt::Active)?
249*3eb59678SJeremy L Thompson         .field("qdata", &rstr_qdata, BasisOpt::None, &qdata)?
250*3eb59678SJeremy L Thompson         .field("v", &rstr_solution, &basis_solution, VectorOpt::Active)?
251*3eb59678SJeremy L Thompson         .check()?;
252*3eb59678SJeremy L Thompson 
253*3eb59678SJeremy L Thompson     // Solution vectors
254*3eb59678SJeremy L Thompson     let mut u = ceed.vector(solution_size)?;
255*3eb59678SJeremy L Thompson     let mut v = ceed.vector(solution_size)?;
256*3eb59678SJeremy L Thompson 
257*3eb59678SJeremy L Thompson     // Initialize u with component index
258*3eb59678SJeremy L Thompson     u.set_value(0.0)?;
259*3eb59678SJeremy L Thompson     for c in 0..ncomp_u {
260*3eb59678SJeremy L Thompson         let q = solution_size / ncomp_u;
261*3eb59678SJeremy L Thompson         u.view_mut()?.iter_mut().skip(c * q).take(q).for_each(|u| {
262*3eb59678SJeremy L Thompson             *u = (c + 1) as libceed::Scalar;
263*3eb59678SJeremy L Thompson         });
264*3eb59678SJeremy L Thompson     }
265*3eb59678SJeremy L Thompson 
266*3eb59678SJeremy L Thompson     // Apply the mass operator
267*3eb59678SJeremy L Thompson     op_mass.apply(&u, &mut v)?;
268*3eb59678SJeremy L Thompson 
269*3eb59678SJeremy L Thompson     // Compute the mesh volume
270*3eb59678SJeremy L Thompson     let volume: libceed::Scalar = v.view()?.iter().sum::<libceed::Scalar>()
271*3eb59678SJeremy L Thompson         / ((ncomp_u * (ncomp_u + 1)) / 2) as libceed::Scalar;
272*3eb59678SJeremy L Thompson 
273*3eb59678SJeremy L Thompson     // Output results
274*3eb59678SJeremy L Thompson     if !quiet {
275*3eb59678SJeremy L Thompson         println!("Exact mesh volume           : {:.12}", exact_volume);
276*3eb59678SJeremy L Thompson         println!("Computed mesh volume        : {:.12}", volume);
277*3eb59678SJeremy L Thompson         println!(
278*3eb59678SJeremy L Thompson             "Volume error                : {:.12e}",
279*3eb59678SJeremy L Thompson             volume - exact_volume
280*3eb59678SJeremy L Thompson         );
281*3eb59678SJeremy L Thompson     }
282*3eb59678SJeremy L Thompson     let tolerance = match dim {
283*3eb59678SJeremy L Thompson         1 => 200.0 * libceed::EPSILON,
284*3eb59678SJeremy L Thompson         _ => 1E-5,
285*3eb59678SJeremy L Thompson     };
286*3eb59678SJeremy L Thompson     let error = (volume - exact_volume).abs();
287*3eb59678SJeremy L Thompson     if error > tolerance {
288*3eb59678SJeremy L Thompson         println!("Volume error too large: {:.12e}", error);
289*3eb59678SJeremy L Thompson         return Err(libceed::Error {
290*3eb59678SJeremy L Thompson             message: format!(
291*3eb59678SJeremy L Thompson                 "Volume error too large - expected: {:.12e}, actual: {:.12e}",
292*3eb59678SJeremy L Thompson                 tolerance, error
293*3eb59678SJeremy L Thompson             ),
294*3eb59678SJeremy L Thompson         });
295*3eb59678SJeremy L Thompson     }
296*3eb59678SJeremy L Thompson     Ok(())
297*3eb59678SJeremy L Thompson }
298*3eb59678SJeremy L Thompson 
299*3eb59678SJeremy L Thompson // ----------------------------------------------------------------------------
300*3eb59678SJeremy L Thompson // Tests
301*3eb59678SJeremy L Thompson // ----------------------------------------------------------------------------
302*3eb59678SJeremy L Thompson #[cfg(test)]
303*3eb59678SJeremy L Thompson mod tests {
304*3eb59678SJeremy L Thompson     use super::*;
305*3eb59678SJeremy L Thompson 
306*3eb59678SJeremy L Thompson     #[test]
307*3eb59678SJeremy L Thompson     fn example_1_vector_1d() {
308*3eb59678SJeremy L Thompson         let options = opt::Opt {
309*3eb59678SJeremy L Thompson             ceed_spec: "/cpu/self/ref/serial".to_string(),
310*3eb59678SJeremy L Thompson             dim: 1,
311*3eb59678SJeremy L Thompson             mesh_degree: 4,
312*3eb59678SJeremy L Thompson             solution_degree: 4,
313*3eb59678SJeremy L Thompson             num_qpts: 6,
314*3eb59678SJeremy L Thompson             problem_size_requested: -1,
315*3eb59678SJeremy L Thompson             test: true,
316*3eb59678SJeremy L Thompson             quiet: true,
317*3eb59678SJeremy L Thompson             gallery: false,
318*3eb59678SJeremy L Thompson         };
319*3eb59678SJeremy L Thompson         assert!(example_1_vector(options).is_ok());
320*3eb59678SJeremy L Thompson     }
321*3eb59678SJeremy L Thompson 
322*3eb59678SJeremy L Thompson     #[test]
323*3eb59678SJeremy L Thompson     fn example_1_vector_2d() {
324*3eb59678SJeremy L Thompson         let options = opt::Opt {
325*3eb59678SJeremy L Thompson             ceed_spec: "/cpu/self/ref/serial".to_string(),
326*3eb59678SJeremy L Thompson             dim: 2,
327*3eb59678SJeremy L Thompson             mesh_degree: 4,
328*3eb59678SJeremy L Thompson             solution_degree: 4,
329*3eb59678SJeremy L Thompson             num_qpts: 6,
330*3eb59678SJeremy L Thompson             problem_size_requested: -1,
331*3eb59678SJeremy L Thompson             test: true,
332*3eb59678SJeremy L Thompson             quiet: true,
333*3eb59678SJeremy L Thompson             gallery: false,
334*3eb59678SJeremy L Thompson         };
335*3eb59678SJeremy L Thompson         assert!(example_1_vector(options).is_ok());
336*3eb59678SJeremy L Thompson     }
337*3eb59678SJeremy L Thompson 
338*3eb59678SJeremy L Thompson     #[test]
339*3eb59678SJeremy L Thompson     fn example_1_vector_3d() {
340*3eb59678SJeremy L Thompson         let options = opt::Opt {
341*3eb59678SJeremy L Thompson             ceed_spec: "/cpu/self/ref/serial".to_string(),
342*3eb59678SJeremy L Thompson             dim: 3,
343*3eb59678SJeremy L Thompson             mesh_degree: 4,
344*3eb59678SJeremy L Thompson             solution_degree: 4,
345*3eb59678SJeremy L Thompson             num_qpts: 6,
346*3eb59678SJeremy L Thompson             problem_size_requested: -1,
347*3eb59678SJeremy L Thompson             test: true,
348*3eb59678SJeremy L Thompson             quiet: false,
349*3eb59678SJeremy L Thompson             gallery: false,
350*3eb59678SJeremy L Thompson         };
351*3eb59678SJeremy L Thompson         assert!(example_1_vector(options).is_ok());
352*3eb59678SJeremy L Thompson     }
353*3eb59678SJeremy L Thompson 
354*3eb59678SJeremy L Thompson     #[test]
355*3eb59678SJeremy L Thompson     fn example_1_vector_1d_gallery() {
356*3eb59678SJeremy L Thompson         let options = opt::Opt {
357*3eb59678SJeremy L Thompson             ceed_spec: "/cpu/self/ref/serial".to_string(),
358*3eb59678SJeremy L Thompson             dim: 1,
359*3eb59678SJeremy L Thompson             mesh_degree: 4,
360*3eb59678SJeremy L Thompson             solution_degree: 4,
361*3eb59678SJeremy L Thompson             num_qpts: 6,
362*3eb59678SJeremy L Thompson             problem_size_requested: -1,
363*3eb59678SJeremy L Thompson             test: true,
364*3eb59678SJeremy L Thompson             quiet: true,
365*3eb59678SJeremy L Thompson             gallery: true,
366*3eb59678SJeremy L Thompson         };
367*3eb59678SJeremy L Thompson         assert!(example_1_vector(options).is_ok());
368*3eb59678SJeremy L Thompson     }
369*3eb59678SJeremy L Thompson 
370*3eb59678SJeremy L Thompson     #[test]
371*3eb59678SJeremy L Thompson     fn example_1_vector_2d_gallery() {
372*3eb59678SJeremy L Thompson         let options = opt::Opt {
373*3eb59678SJeremy L Thompson             ceed_spec: "/cpu/self/ref/serial".to_string(),
374*3eb59678SJeremy L Thompson             dim: 2,
375*3eb59678SJeremy L Thompson             mesh_degree: 4,
376*3eb59678SJeremy L Thompson             solution_degree: 4,
377*3eb59678SJeremy L Thompson             num_qpts: 6,
378*3eb59678SJeremy L Thompson             problem_size_requested: -1,
379*3eb59678SJeremy L Thompson             test: true,
380*3eb59678SJeremy L Thompson             quiet: true,
381*3eb59678SJeremy L Thompson             gallery: true,
382*3eb59678SJeremy L Thompson         };
383*3eb59678SJeremy L Thompson         assert!(example_1_vector(options).is_ok());
384*3eb59678SJeremy L Thompson     }
385*3eb59678SJeremy L Thompson 
386*3eb59678SJeremy L Thompson     #[test]
387*3eb59678SJeremy L Thompson     fn example_1_vector_3d_gallery() {
388*3eb59678SJeremy L Thompson         let options = opt::Opt {
389*3eb59678SJeremy L Thompson             ceed_spec: "/cpu/self/ref/serial".to_string(),
390*3eb59678SJeremy L Thompson             dim: 3,
391*3eb59678SJeremy L Thompson             mesh_degree: 4,
392*3eb59678SJeremy L Thompson             solution_degree: 4,
393*3eb59678SJeremy L Thompson             num_qpts: 6,
394*3eb59678SJeremy L Thompson             problem_size_requested: -1,
395*3eb59678SJeremy L Thompson             test: true,
396*3eb59678SJeremy L Thompson             quiet: true,
397*3eb59678SJeremy L Thompson             gallery: true,
398*3eb59678SJeremy L Thompson         };
399*3eb59678SJeremy L Thompson         assert!(example_1_vector(options).is_ok());
400*3eb59678SJeremy L Thompson     }
401*3eb59678SJeremy L Thompson }
402*3eb59678SJeremy L Thompson 
403*3eb59678SJeremy L Thompson // ----------------------------------------------------------------------------
404