User interface
In this chapter, we start the other way around, and first have a look at the proposed user interfance. The full file lib.rs
is provided below. It mostly contains an enum and a helper function for solving the 2D Poisson problem.
Click here to view: lib.rs.
#![allow(unused)] fn main() { //! This file is part of the Poisson 2D crate. //!! It provides functionality for solving the 2D Poisson equation using finite element methods (FEM). //! //! The crate includes modules for elements, mesh, quadrature rules, and solvers. pub mod element; pub mod mesh; pub mod quadrature; pub mod solver; pub use solver::{assemble_and_solve_dense, assemble_and_solve_sparse}; pub use mesh::Mesh2d; pub use nalgebra::DVector; /// Enum representing the type of solver to use // ANCHOR: solver_type pub enum SolverType { Dense, Sparse, } // ANCHOR_END: solver_type /// Helper function for solving the 2D Poisson problem /// /// This function takes a mesh, boundary nodes, boundary function, source function, and solver type. /// Arguments: /// - `mesh`: The mesh representing the domain. /// - `boundary_nodes`: Indices of the nodes on the boundary. /// - `boundary_fn`: Function defining the boundary condition. /// - `source_fn`: Function defining the source term. /// - `solver_type`: Type of solver to use (Dense or Sparse). /// /// Returns: /// - A vector containing the solution at the mesh nodes. // ANCHOR: solve_poisson_2d pub fn solve_poisson_2d<F>( mesh: &Mesh2d, boundary_nodes: &[usize], boundary_fn: &F, source_fn: &F, solver_type: SolverType, ) -> DVector<f64> where F: Fn(f64, f64) -> f64, { match solver_type { SolverType::Dense => assemble_and_solve_dense(mesh, boundary_nodes, boundary_fn, source_fn), SolverType::Sparse => { assemble_and_solve_sparse(mesh, boundary_nodes, boundary_fn, source_fn) } } } // ANCHOR_END: solve_poisson_2d }
Solver type
In this example, we consider two types of finite element solvers:
- A dense solver which assembles dense matrices and uses a dense solver for the linear system.
- A sparse solver which assembles sparse matrices and uses a sparse solver for the linear system.
This is encoded by defining the following enumerate:
#![allow(unused)] fn main() { pub enum SolverType { Dense, Sparse, } }
It can be used to pick the solver type by passing SolverType::Dense
or SolverType::Sparse
to the helper function discussed below.
Helper function
The helper function that the user should call is shown below. It takes the following input arguments:
- A mesh, given as a
Mesh2d
struct implemented in the mesh.rs module. - The boundary nodes and the boundary function () for applying Dirichlet boundary conditions.
- The source function .
- And the solver type (
SolverType::Dense
orSolverType::Sparse
).
Based on the chosen solver type, the function either calls the dense or sparse methods thanks to pattern matching.
#![allow(unused)] fn main() { pub fn solve_poisson_2d<F>( mesh: &Mesh2d, boundary_nodes: &[usize], boundary_fn: &F, source_fn: &F, solver_type: SolverType, ) -> DVector<f64> where F: Fn(f64, f64) -> f64, { match solver_type { SolverType::Dense => assemble_and_solve_dense(mesh, boundary_nodes, boundary_fn, source_fn), SolverType::Sparse => { assemble_and_solve_sparse(mesh, boundary_nodes, boundary_fn, source_fn) } } } }