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