#ode #data #solver #differential #problem #solving #traits

bin+lib odesolver

用于求解常微分方程的库

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

MIT/Apache

42KB
559

odesolver 是一个用于求解常微分方程的 rust 库。

该库有三个可能的接口,第一个是模块 solver_trait,其中用户在编译时知道问题的阶数(一个常微分方程组的常微分方程数量)。此接口使用 Rust 数组作为数据集合,并使用特性定义系统的行为。任何符合特性 ODESystem<N>Clone 的数据类型(系统)都可以求解,系统本身(作为一个数据类型)传递给 solver_ode 函数。由于编译器知道大小,它可以在栈上分配所需的内存,从而加快程序运行速度。此模块比其他模块快大约一个数量级(大约 10 倍)来解决问题。

第二个是模块 solver_vector,其中用户使用向量作为数据集合,内存分配在堆上。这允许在求解问题时具有更大的灵活性,因为不需要在编译时知道问题的阶数。在此模块中,不传递一个 系统,而是一个初始状态和获取状态微分(当给定实际状态和时间)的函数。

第三个是模块 solver_vector_trait,其中用户使用向量作为数据集合,内存分配在堆上。这允许在求解问题时具有更大的灵活性,因为不需要在编译时知道问题的阶数。但是,特性是展示的,以便任何数据类型都可以代表一个 系统(由常微分方程组成),只要它符合 ODESystemClone 的特性。

示例

示例 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