pub mod assembly;
pub mod basis;
pub use assembly::{solve_vem, VemSolution};
pub use basis::{polygon_centroid_and_diameter, scaled_monomials_values};
#[derive(Debug, Clone)]
pub struct VemConfig {
pub polynomial_degree: usize,
pub stabilization: f64,
}
impl Default for VemConfig {
fn default() -> Self {
VemConfig {
polynomial_degree: 1,
stabilization: 1.0,
}
}
}
#[derive(Debug, Clone)]
pub struct PolygonalMesh {
pub vertices: Vec<[f64; 2]>,
pub elements: Vec<Vec<usize>>,
pub boundary_vertices: Vec<usize>,
}
impl PolygonalMesh {
pub fn new(vertices: Vec<[f64; 2]>, elements: Vec<Vec<usize>>) -> Self {
use std::collections::HashMap;
let mut edge_count: HashMap<[usize; 2], usize> = HashMap::new();
for elem in &elements {
let n = elem.len();
for i in 0..n {
let a = elem[i];
let b = elem[(i + 1) % n];
let edge = [a.min(b), a.max(b)];
*edge_count.entry(edge).or_insert(0) += 1;
}
}
let mut boundary_set = std::collections::HashSet::new();
for (edge, &count) in &edge_count {
if count == 1 {
boundary_set.insert(edge[0]);
boundary_set.insert(edge[1]);
}
}
let mut boundary_vertices: Vec<usize> = boundary_set.into_iter().collect();
boundary_vertices.sort();
PolygonalMesh {
vertices,
elements,
boundary_vertices,
}
}
pub fn n_vertices(&self) -> usize {
self.vertices.len()
}
pub fn n_elements(&self) -> usize {
self.elements.len()
}
pub fn is_boundary_vertex(&self, v_idx: usize) -> bool {
self.boundary_vertices.contains(&v_idx)
}
pub fn element_vertices(&self, elem_idx: usize) -> Vec<[f64; 2]> {
self.elements[elem_idx]
.iter()
.map(|&v| self.vertices[v])
.collect()
}
}
#[derive(Debug, Clone)]
pub struct VemDof {
pub n_dofs: usize,
pub vertex_to_dof: Vec<usize>,
}
impl VemDof {
pub fn new(mesh: &PolygonalMesh) -> Self {
let n = mesh.n_vertices();
VemDof {
n_dofs: n,
vertex_to_dof: (0..n).collect(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_polygonal_mesh_square() {
let vertices = vec![
[0.0, 0.0],
[1.0, 0.0],
[1.0, 1.0],
[0.0, 1.0],
[0.5, 0.5], ];
let elements = vec![vec![0, 1, 4], vec![1, 2, 4], vec![2, 3, 4], vec![3, 0, 4]];
let mesh = PolygonalMesh::new(vertices, elements);
assert_eq!(mesh.n_vertices(), 5);
assert_eq!(mesh.n_elements(), 4);
assert!(mesh.is_boundary_vertex(0));
assert!(mesh.is_boundary_vertex(1));
assert!(!mesh.is_boundary_vertex(4));
}
#[test]
fn test_vem_config_default() {
let cfg = VemConfig::default();
assert_eq!(cfg.polynomial_degree, 1);
assert!((cfg.stabilization - 1.0).abs() < 1e-15);
}
#[test]
fn test_polygon_centroid_square() {
use crate::pde::vem::basis::polygon_centroid_and_diameter;
let verts = [[0.0_f64, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]];
let (centroid, diameter) = polygon_centroid_and_diameter(&verts);
assert!((centroid[0] - 0.5).abs() < 1e-12, "cx={}", centroid[0]);
assert!((centroid[1] - 0.5).abs() < 1e-12, "cy={}", centroid[1]);
let expected_diam = 2.0_f64.sqrt();
assert!(
(diameter - expected_diam).abs() < 1e-12,
"diam={}",
diameter
);
}
}