6 个版本
0.1.5 | 2023年2月2日 |
---|---|
0.1.4 | 2023年2月1日 |
0.1.3 | 2023年1月16日 |
0.1.2 | 2022年12月27日 |
#9 in #differential
42KB
559 行
odesolver 是一个用于求解常微分方程的 rust 库。
该库有三个可能的接口,第一个是模块 solver_trait
,其中用户在编译时知道问题的阶数(一个常微分方程组的常微分方程数量)。此接口使用 Rust 数组作为数据集合,并使用特性定义系统的行为。任何符合特性 ODESystem<N>
和 Clone
的数据类型(系统)都可以求解,系统本身(作为一个数据类型)传递给 solver_ode
函数。由于编译器知道大小,它可以在栈上分配所需的内存,从而加快程序运行速度。此模块比其他模块快大约一个数量级(大约 10 倍)来解决问题。
第二个是模块 solver_vector
,其中用户使用向量作为数据集合,内存分配在堆上。这允许在求解问题时具有更大的灵活性,因为不需要在编译时知道问题的阶数。在此模块中,不传递一个 系统,而是一个初始状态和获取状态微分(当给定实际状态和时间)的函数。
第三个是模块 solver_vector_trait
,其中用户使用向量作为数据集合,内存分配在堆上。这允许在求解问题时具有更大的灵活性,因为不需要在编译时知道问题的阶数。但是,特性是展示的,以便任何数据类型都可以代表一个 系统(由常微分方程组成),只要它符合 ODESystem
和 Clone
的特性。
示例
示例 solver_trait
use odesolver::solver_trait as ST;
const ORDER:usize = 2;
const ORDER_T:usize = ORDER + 1;
//always ORDER + 1, so that the exporting Data has an extra field for the time.
fn main() {
let initial_state = [3.0,2.0];
let tstart = 0.0;
let tend = 400.0;
let step = 0.0001;
let ratio_step_output = 100;
let odeparam = ST::ODEParam {time : tstart, tend
,step
,ratio_step_output
};
let sist = FSist1 { state : initial_state };
let file_trait = "./test_trait.txt".to_string();
let(data,_,_) = ST::solve_ode::<ORDER,ORDER_T,_>(sist, odeparam, ST::ODESolver::RK4);
ST::data_to_file(&data, file_trait, None).unwrap();
}
#[derive(Clone)]
struct FSist1<const N: usize> {
state : ST::State<N>,
}
impl ST::ODESystem<ORDER> for FSist1<ORDER> {
fn state (&self) -> &ST::State<ORDER>{
return &self.state;
}
fn dstate (&self, _time : f64) -> ST::DState<ORDER>{
let state = self.state;
let mut dstate = [0.0; ORDER];
dstate[0] = -0.5*state[0];
dstate[1] = -0.00001*state[1];
dstate
}
fn update_state(&mut self, state : ST::State<ORDER>) {
self.state = state;
}
}
示例 solver_vector
use odesolver::solver_vector as SV;
fn main() {
let initial_state = vec!(3.0,2.0);
let tstart = 0.0;
let tend = 400.0;
let step = 0.0001;
let ratio_step_output = 100;
let odeparam = SV::ODEParam {time : tstart, tend
,step
,ratio_step_output
};
let file_vec = "./test_vec.txt".to_string();
(data,_) = SV::solve_ode(system_function, odeparam, initial_state, SV::ODESolver::RK4);
SV::data_to_file(&data, file_vec, None).unwrap();
}
fn system_function (_time: f64, state: &SV::State) -> SV::DState {
let mut dstate = vec!(0.0;2);
dstate[0] = -0.5*state[0];
dstate[1] = -0.00001*state[1];
dstate
}
示例 solver_vector_trait
use odesolver::solver_vector_trait as SVT;
fn main() {
let initial_state = vec!(3.0,2.0);
// let initial_state = [3.0,2.0];
let tstart = 0.0;
let tend = 400.0;
let step = 0.0001;
let ratio_step_output = 100;
let odeparam = SVT::ODEParam {time : tstart, tend
,step
,ratio_step_output
};
let sist = FSist2 { state : initial_state };
let file_vec_trait = "./teste_vec_trait.txt".to_string();
let(data,_,_) = SVT::solve_ode::<_>(sist, odeparam, SVT::ODESolver::RK4);
SVT::data_to_file(&data, file_vec_trait, None).unwrap();
}
#[derive(Clone)]
struct FSist2 {
state : SVT::State,
}
impl SVT::ODESystem for FSist2 {
fn state (&self) -> &SVT::State{
return &self.state;
}
fn dstate (&self, _time : f64) -> SVT::DState{
let state = self.state();
let mut dstate = Vec::<f64>::new();
dstate.push(-0.5*state[0]); //[0]
dstate.push(-0.00001*state[1]); //[1]
dstate
}
fn update_state(&mut self, state : SVT::State) {
self.state = state;
}
}
依赖项
~15KB