bspline_impl.hpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #ifndef CASADI_BSPLINE_IMPL_HPP
27 #define CASADI_BSPLINE_IMPL_HPP
28 
29 #include "bspline.hpp"
30 #include "interpolant_impl.hpp"
31 #include "casadi_low.hpp"
32 
33 namespace casadi {
34 
35  template<class M>
36  M BSplineCommon::derivative_coeff(casadi_int i, const M& coeffs) const {
37  casadi_int n_dims = degree_.size();
38 
39  casadi_int n_knots = offset_[i+1]-offset_[i];
40  casadi_int n = n_knots-degree_[i]-1;
41  DM knots = std::vector<double>(get_ptr(knots_)+offset_[i], get_ptr(knots_)+offset_[i+1]);
42  DM delta_knots = knots(range(1+degree_[i], n_knots-1))
43  - knots(range(1, n_knots-degree_[i]-1));
44  Sparsity sp_diag = vertsplit(Sparsity::diag(n), {0, n-1, n})[0];
45  Sparsity sp_band = vertsplit(Sparsity::band(n, -1), {0, n-1, n})[0];
46  DM delta_knots_inv = 1/delta_knots;
47  DM T = DM(sp_diag, -delta_knots_inv) + DM(sp_band, delta_knots_inv);
48  T*= degree_[i];
49 
50  std::vector<casadi_int> coeffs_dims_new = coeffs_dims_;
51  coeffs_dims_new[i+1] = T.size1();
52 
53  // Apply transformation T on axis i
54 
55  // Bring axis i to the back
56  std::vector<casadi_int> order = range(n_dims+1);
57  std::swap(order.back(), order[i+1]);
58  std::vector<casadi_int> mapping = tensor_permute_mapping(coeffs_dims_, order);
59  M coeff_matrix = coeffs.nz(mapping); // NOLINT(cppcoreguidelines-slicing)
60 
61  // Cast as matrix
62  coeff_matrix = reshape(coeff_matrix, -1, T.size2());
63 
64  // Apply the transformation matrix from the right
65  coeff_matrix = mtimes(coeff_matrix, T.T());
66 
67  // Bring axis i back to the original place
68  mapping = tensor_permute_mapping(permute(coeffs_dims_new, order), order);
69  coeff_matrix = coeff_matrix.nz(mapping); // NOLINT(cppcoreguidelines-slicing)
70 
71  // Return the flat vector
72  return coeff_matrix;
73  }
74 
75  template<class T>
76  MX BSplineCommon::jac(const MX& x, const T& coeffs) const {
77  casadi_int n_dims = degree_.size();
78  std::vector<MX> parts;
79 
80  Dict opts;
81  std::vector<std::string> lookup_mode;
82  for (auto e : lookup_mode_) lookup_mode.push_back(Low::lookup_mode_from_enum(e));
83  opts["lookup_mode"] = lookup_mode;
84 
85  // Loop over dimensions
86  for (casadi_int k=0;k<n_dims;++k) {
87  std::vector< std::vector<double> > knots;
88  std::vector< casadi_int> degree;
89  for (casadi_int i=0;i<degree_.size();++i) {
90  if (i==k) {
91  knots.push_back(
92  std::vector<double>(get_ptr(knots_)+offset_[i]+1, get_ptr(knots_)+offset_[i+1]-1));
93  degree.push_back(degree_[i]-1);
94  } else {
95  knots.push_back(
96  std::vector<double>(get_ptr(knots_)+offset_[i], get_ptr(knots_)+offset_[i+1]));
97  degree.push_back(degree_[i]);
98  }
99  }
100  MX d = MX::bspline(x, derivative_coeff(k, coeffs), knots, degree, m_, opts);
101  parts.push_back(d);
102  }
103 
104  return horzcat(parts);
105  }
106 
107 } // namespace casadi
108 
109 #endif // CASADI_BSPLINE_IMPL_HPP
static Sparsity band(casadi_int n, casadi_int p)
Create a single band in a square sparsity pattern.
static Sparsity diag(casadi_int nrow)
Create diagonal sparsity pattern *.
Definition: sparsity.hpp:183
friend MX bspline(const MX &x, const DM &coeffs, const std::vector< std::vector< double > > &knots, const std::vector< casadi_int > &degree, casadi_int m, const Dict &opts=Dict())
Definition: mx.hpp:761
The casadi namespace.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
Matrix< double > DM
Definition: dm_fwd.hpp:33