scirs2_integrate/dae/types.rs
1//! Types for DAE solver module
2//!
3//! This module defines the core types used by DAE solvers,
4//! including method enums, options, and results.
5
6use crate::common::IntegrateFloat;
7use crate::ode::ODEMethod;
8use scirs2_core::ndarray::Array1;
9
10/// DAE system type
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
12pub enum DAEType {
13 /// Semi-explicit index-1 DAE of the form:
14 /// x' = f(x, y, t)
15 /// 0 = g(x, y, t)
16 #[default]
17 SemiExplicit,
18
19 /// Fully implicit index-1 DAE of the form:
20 /// F(x', x, t) = 0
21 FullyImplicit,
22}
23
24/// DAE index classification
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
26pub enum DAEIndex {
27 /// Index-1 (differentiate once to get an ODE)
28 #[default]
29 Index1,
30 /// Index-2 (differentiate twice)
31 Index2,
32 /// Index-3 (differentiate three times)
33 Index3,
34 /// Higher-index (differentiate more than three times)
35 HigherIndex,
36}
37
38/// Options for controlling the behavior of DAE solvers
39#[derive(Debug, Clone)]
40pub struct DAEOptions<F: IntegrateFloat> {
41 /// The DAE system type
42 pub dae_type: DAEType,
43
44 /// The DAE index (classification)
45 pub index: DAEIndex,
46
47 /// The ODE solver method to use for the differential part
48 pub method: ODEMethod,
49
50 /// Relative tolerance for error control
51 pub rtol: F,
52
53 /// Absolute tolerance for error control
54 pub atol: F,
55
56 /// Initial step size (optional, if not provided, it will be estimated)
57 pub h0: Option<F>,
58
59 /// Maximum number of steps to take
60 pub max_steps: usize,
61
62 /// Maximum step size (optional)
63 pub max_step: Option<F>,
64
65 /// Minimum step size (optional)
66 pub min_step: Option<F>,
67
68 /// Maximum iterations for the nonlinear solver
69 pub max_newton_iterations: usize,
70
71 /// Tolerance for the nonlinear solver
72 pub newton_tol: F,
73
74 /// Maximum BDF order (optional, defaults to 5)
75 pub max_order: Option<usize>,
76}
77
78impl<F: IntegrateFloat> Default for DAEOptions<F> {
79 fn default() -> Self {
80 DAEOptions {
81 dae_type: DAEType::default(),
82 index: DAEIndex::default(),
83 method: ODEMethod::Radau, // Use Radau by default, as it's suitable for index-1 DAEs
84 rtol: F::from_f64(1e-3).unwrap(),
85 atol: F::from_f64(1e-6).unwrap(),
86 h0: None,
87 max_steps: 500,
88 max_step: None,
89 min_step: None,
90 max_newton_iterations: 10,
91 newton_tol: F::from_f64(1e-8).unwrap(),
92 max_order: None,
93 }
94 }
95}
96
97/// Result of DAE integration
98#[derive(Debug, Clone)]
99pub struct DAEResult<F: IntegrateFloat> {
100 /// Time points
101 pub t: Vec<F>,
102
103 /// Solution values for differential variables at time points
104 pub x: Vec<Array1<F>>,
105
106 /// Solution values for algebraic variables at time points
107 pub y: Vec<Array1<F>>,
108
109 /// Whether the integration was successful
110 pub success: bool,
111
112 /// Status message
113 pub message: Option<String>,
114
115 /// Number of function evaluations
116 pub n_eval: usize,
117
118 /// Number of constraint evaluations
119 pub n_constraint_eval: usize,
120
121 /// Number of steps taken
122 pub n_steps: usize,
123
124 /// Number of accepted steps
125 pub n_accepted: usize,
126
127 /// Number of rejected steps
128 pub n_rejected: usize,
129
130 /// Number of LU decompositions
131 pub n_lu: usize,
132
133 /// Number of Jacobian evaluations
134 pub n_jac: usize,
135
136 /// The solver method used
137 pub method: ODEMethod,
138
139 /// The DAE type
140 pub dae_type: DAEType,
141
142 /// The DAE index
143 pub index: DAEIndex,
144}