1#![cfg_attr(
2 feature = "max_ortho_basis",
3 feature(const_fn_floating_point_arithmetic)
4)]
5#![doc = include_str!("../README.md")]
6
7pub mod fem_domain;
9
10pub mod fem_problem;
12
13pub mod prelude {
15 pub use crate::fem_domain::basis::hierarchical_basis_fns::poly::HierPoly;
16 #[cfg(feature = "max_ortho_basis")]
17 pub use crate::fem_domain::basis::shape_fns::max_ortho::MaxOrthoShapeFn;
18 pub use crate::fem_domain::domain::{
19 dof::{
20 basis_spec::{BSAddress, BasisSpec},
21 DoF,
22 },
23 fields::UniformFieldSpace,
24 mesh::{
25 elem::Elem,
26 h_refinement::{HRef, HRefError},
27 p_refinement::{PRef, Orders, PRefError},
28 Mesh,
29 },
30 ContinuityCondition, Domain,
31 };
32 pub use crate::fem_problem::galerkin::{galerkin_sample_gep_hcurl, GalerkinSamplingError};
33 pub use crate::fem_problem::integration::integrals::{curl_curl::CurlCurl, inner::L2Inner};
34 pub use crate::fem_problem::linalg::{
35 nalgebra_solve::{nalgebra_solve_gep, NalgebraGEPError},
36 slepc_solve::{slepc_solve_gep, SlepcGEPError},
37 EigenPair, GEP,
38 };
39}
40
41#[cfg(test)]
42mod tests {
43 use super::prelude::*;
44
45 #[test]
46 fn nalg_problem() {
47 let mut mesh = Mesh::from_file("./test_input/test_mesh_a.json").unwrap();
49 mesh.global_p_refinement(PRef::from(2, 2));
50
51 let domain = Domain::from_mesh(mesh, ContinuityCondition::HCurl);
53 let ndofs = domain.dofs.len();
54 println!("Domain constructed with {} Degrees of Freedom", ndofs);
55
56 let eigenproblem =
58 galerkin_sample_gep_hcurl::<HierPoly, CurlCurl, L2Inner>(&domain, Some([8, 8]))
59 .unwrap();
60
61 let solution = nalgebra_solve_gep(eigenproblem, 2.64).unwrap();
63 println!("Found eigenvalue: {:.15}", solution.value);
64
65 assert!((solution.value - 2.6479657_f64).abs() < 1e-6);
66 assert_eq!(solution.vector.len(), ndofs);
67
68 let mut field_space = UniformFieldSpace::new(&domain, [8, 8]);
69 let e_field_names = field_space
70 .xy_fields::<HierPoly>("E", solution.normalized_eigenvector())
71 .unwrap();
72 field_space
73 .expression_2arg(e_field_names, "E_mag", |ex, ey| {
74 (ex.powi(2) + ey.powi(2)).sqrt()
75 })
76 .unwrap();
77 field_space
78 .print_all_to_vtk("./test_output/mesh_b_fields.vtk")
79 .unwrap();
80 }
81
82 #[test]
83 fn slepc_problem() {
84 let mut mesh = Mesh::from_file("./test_input/test_mesh_b.json").unwrap();
86 mesh.global_p_refinement(PRef::from(3, 3));
87 mesh.global_h_refinement(HRef::T);
88 mesh.h_refine_elems(vec![6, 9, 12], HRef::T).unwrap();
89
90 let domain = Domain::from_mesh(mesh, ContinuityCondition::HCurl);
92 let ndofs = domain.dofs.len();
93 println!("Domain constructed with {} Degrees of Freedom", ndofs);
94
95 let eigenproblem =
97 galerkin_sample_gep_hcurl::<HierPoly, CurlCurl, L2Inner>(&domain, Some([8, 8]))
98 .unwrap();
99
100 let solution = slepc_solve_gep(eigenproblem, 1.475).unwrap();
102 println!("Found eigenvalue: {:.15}", solution.value);
103
104 assert!((solution.value - 1.4745880937_f64).abs() < 1e-9);
105 assert_eq!(solution.vector.len(), ndofs);
106
107 let mut field_space = UniformFieldSpace::new(&domain, [8, 8]);
108 let e_field_names = field_space
109 .xy_fields::<HierPoly>("E", solution.normalized_eigenvector())
110 .unwrap();
111 field_space
112 .expression_2arg(e_field_names, "E_mag", |ex, ey| {
113 (ex.powi(2) + ey.powi(2)).sqrt()
114 })
115 .unwrap();
116 field_space
117 .print_all_to_vtk("./test_output/mesh_b_fields.vtk")
118 .unwrap();
119 }
120}