Janus 2.0.0
High-performance C++20 dual-mode numerical framework
Loading...
Searching...
No Matches
FiniteDifference.hpp
Go to the documentation of this file.
1#pragma once
7
10#include <Eigen/Dense>
11#include <cmath>
12#include <string>
13#include <vector>
14
15namespace janus {
16
17// ============================================================================
18// Integration Method Enum
19// ============================================================================
20
30
47inline IntegrationMethod parse_integration_method(const std::string &method) {
48 if (method == "trapezoidal" || method == "trapezoid" || method == "midpoint") {
50 } else if (method == "forward_euler" || method == "forward euler") {
52 } else if (method == "backward_euler" || method == "backward euler" ||
53 method == "backwards_euler" || method == "backwards euler") {
55 }
56 throw InvalidArgument("Unknown integration method: " + method);
57}
58
59// ============================================================================
60// Low-Order Finite Difference Weights
61// ============================================================================
62
73template <typename Scalar> std::pair<Scalar, Scalar> forward_euler_weights(Scalar h) {
74 return {-Scalar(1) / h, Scalar(1) / h};
75}
76
87template <typename Scalar> std::pair<Scalar, Scalar> backward_euler_weights(Scalar h) {
88 return {-Scalar(1) / h, Scalar(1) / h};
89}
90
101template <typename Scalar> std::pair<Scalar, Scalar> central_difference_weights(Scalar h) {
102 return {-Scalar(1) / (Scalar(2) * h), Scalar(1) / (Scalar(2) * h)};
103}
104
115template <typename Scalar> std::pair<Scalar, Scalar> trapezoidal_weights(Scalar h) {
116 return {Scalar(0.5) * h, Scalar(0.5) * h};
117}
118
119// ============================================================================
120// Derivative Approximation Functions
121// ============================================================================
122
133template <typename Scalar>
135 Eigen::Index n = f.size();
136
137 if (n != x.size()) {
138 throw InvalidArgument("forward_difference: f and x must have same size");
139 }
140 if (n < 2) {
141 throw InvalidArgument("forward_difference: need at least 2 points");
142 }
143
144 JanusVector<Scalar> df = f.tail(n - 1) - f.head(n - 1);
145 JanusVector<Scalar> dx = x.tail(n - 1) - x.head(n - 1);
146
147 return (df.array() / dx.array()).matrix();
148}
149
160template <typename Scalar>
165
176template <typename Scalar>
178 Eigen::Index n = f.size();
179
180 if (n != x.size()) {
181 throw InvalidArgument("central_difference: f and x must have same size");
182 }
183 if (n < 3) {
184 throw InvalidArgument("central_difference: need at least 3 points");
185 }
186
187 JanusVector<Scalar> df = f.tail(n - 2) - f.head(n - 2);
188 JanusVector<Scalar> dx = x.tail(n - 2) - x.head(n - 2);
189
190 return (df.array() / dx.array()).matrix();
191}
192
208template <typename Scalar>
210 const JanusVector<Scalar> &xdot,
211 const JanusVector<Scalar> &t,
213 Eigen::Index n = x.size();
214
215 if (n != xdot.size() || n != t.size()) {
216 throw InvalidArgument("integration_defects: x, xdot, t must have same size");
217 }
218 if (n < 2) {
219 throw InvalidArgument("integration_defects: need at least 2 points");
220 }
221
222 JanusVector<Scalar> dx = x.tail(n - 1) - x.head(n - 1);
223 JanusVector<Scalar> dt = t.tail(n - 1) - t.head(n - 1);
224 JanusVector<Scalar> defects(n - 1);
225
226 switch (method) {
228 defects = dx - (xdot.head(n - 1).array() * dt.array()).matrix();
229 break;
230
232 defects = dx - (xdot.tail(n - 1).array() * dt.array()).matrix();
233 break;
234
237 defects =
238 dx -
239 (Scalar(0.5) * (xdot.head(n - 1) + xdot.tail(n - 1)).array() * dt.array()).matrix();
240 break;
241 }
242
243 return defects;
244}
245
257template <typename Scalar>
259 Scalar x0 = Scalar(0.0),
260 int derivative_degree = 1) {
261 if (derivative_degree < 0) {
262 throw InvalidArgument("finite_difference_coefficients: derivative_degree must be >= 0");
263 }
264
265 int n_points = static_cast<int>(x.size());
266 if (n_points < derivative_degree + 1) {
267 throw InvalidArgument(
268 "finite_difference_coefficients: need at least (derivative_degree + 1) grid points");
269 }
270
271 int N = n_points - 1;
272 int M = derivative_degree;
273
274 auto get_idx = [&](int m, int n, int v) { return m * (N + 1) * (N + 1) + n * (N + 1) + v; };
275
276 std::vector<Scalar> delta((M + 1) * (N + 1) * (N + 1), Scalar(0.0));
277 delta[get_idx(0, 0, 0)] = Scalar(1.0);
278
279 Scalar c1 = Scalar(1.0);
280
281 for (int n = 1; n <= N; ++n) {
282 Scalar c2 = Scalar(1.0);
283 for (int v = 0; v < n; ++v) {
284 Scalar c3 = x(n) - x(v);
285 c2 = c2 * c3;
286
287 for (int m = 0; m <= std::min(n, M); ++m) {
288 Scalar term1 = (x(n) - x0) * delta[get_idx(m, n - 1, v)];
289 Scalar term2 = Scalar(0.0);
290 if (m > 0) {
291 term2 = static_cast<Scalar>(m) * delta[get_idx(m - 1, n - 1, v)];
292 }
293 delta[get_idx(m, n, v)] = (term1 - term2) / c3;
294 }
295 }
296
297 for (int m = 0; m <= std::min(n, M); ++m) {
298 Scalar term1 = Scalar(0.0);
299 if (m > 0) {
300 term1 = static_cast<Scalar>(m) * delta[get_idx(m - 1, n - 1, n - 1)];
301 }
302 Scalar term2 = (x(n - 1) - x0) * delta[get_idx(m, n - 1, n - 1)];
303
304 delta[get_idx(m, n, n)] = (c1 / c2) * (term1 - term2);
305 }
306 c1 = c2;
307 }
308
309 JanusVector<Scalar> coeffs(n_points);
310 for (int i = 0; i < n_points; ++i) {
311 coeffs(i) = delta[get_idx(M, N, i)];
312 }
313
314 return coeffs;
315}
316
317} // namespace janus
Custom exception hierarchy for Janus framework.
Core type aliases for numeric and symbolic Eigen/CasADi interop.
Input validation failed (e.g., mismatched sizes, invalid parameters).
Definition JanusError.hpp:31
Definition Diagnostics.hpp:19
JanusVector< Scalar > central_difference(const JanusVector< Scalar > &f, const JanusVector< Scalar > &x)
Compute derivative using central difference.
Definition FiniteDifference.hpp:177
JanusVector< Scalar > forward_difference(const JanusVector< Scalar > &f, const JanusVector< Scalar > &x)
Compute derivative using forward difference.
Definition FiniteDifference.hpp:134
JanusVector< Scalar > finite_difference_coefficients(const JanusVector< Scalar > &x, Scalar x0=Scalar(0.0), int derivative_degree=1)
Computes finite difference coefficients for arbitrary grids.
Definition FiniteDifference.hpp:258
std::pair< Scalar, Scalar > forward_euler_weights(Scalar h)
Forward Euler (explicit) differentiation weights.
Definition FiniteDifference.hpp:73
std::pair< Scalar, Scalar > trapezoidal_weights(Scalar h)
Trapezoidal integration weights.
Definition FiniteDifference.hpp:115
JanusVector< Scalar > backward_difference(const JanusVector< Scalar > &f, const JanusVector< Scalar > &x)
Compute derivative using backward difference.
Definition FiniteDifference.hpp:161
IntegrationMethod
Integration/differentiation method for trajectory optimization.
Definition FiniteDifference.hpp:24
@ BackwardEuler
First-order backward difference: x[i+1] - x[i] = xdot[i+1] * dt.
Definition FiniteDifference.hpp:26
@ ForwardEuler
First-order forward difference: x[i+1] - x[i] = xdot[i] * dt.
Definition FiniteDifference.hpp:25
@ Midpoint
Alias for Trapezoidal (same formula).
Definition FiniteDifference.hpp:28
@ Trapezoidal
Second-order trapezoidal: x[i+1] - x[i] = 0.5 * (xdot[i] + xdot[i+1]) * dt.
Definition FiniteDifference.hpp:27
std::pair< Scalar, Scalar > central_difference_weights(Scalar h)
Central difference differentiation weights.
Definition FiniteDifference.hpp:101
std::pair< Scalar, Scalar > backward_euler_weights(Scalar h)
Backward Euler (implicit) differentiation weights.
Definition FiniteDifference.hpp:87
JanusVector< Scalar > integration_defects(const JanusVector< Scalar > &x, const JanusVector< Scalar > &xdot, const JanusVector< Scalar > &t, IntegrationMethod method=IntegrationMethod::Trapezoidal)
Compute integration defects for derivative constraints.
Definition FiniteDifference.hpp:209
IntegrationMethod parse_integration_method(const std::string &method)
Parse integration method from string.
Definition FiniteDifference.hpp:47
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > JanusVector
Dynamic-size column vector for both numeric and symbolic backends.
Definition JanusTypes.hpp:49