26 #include "slicot_dple.hpp"
27 #include "slicot_layer.hpp"
28 #include "slicot_la.hpp"
30 #include "../../core/casadi_misc.hpp"
31 #include "../../core/mx_function.hpp"
32 #include "../../core/sx_function.hpp"
41 int CASADI_DPLE_SLICOT_EXPORT
44 plugin->name =
"slicot";
46 plugin->version = CASADI_VERSION;
60 "User-defined linear solver class. Needed for sensitivities."}},
61 {
"linear_solver_options",
63 "Options to be passed to the linear solver."}},
66 "Numerical zero used in Periodic Schur decomposition with slicot."
67 "This option is needed when your systems has Floquet multipliers"
68 "zero or close to zero"}}
81 bool SlicotDple::has_loaded_ =
false;
87 casadi_warning(
"Loaded plugin with GPL license.");
92 linear_solver_ =
"csparse";
93 psd_num_zero_ = 1e-12;
96 for (
auto&& op : opts) {
97 if (op.first==
"linear_solver") {
98 linear_solver_ = op.second.as_string();
99 }
else if (op.first==
"linear_solver_options") {
100 linear_solver_options_ = op.second;
101 }
else if (op.first==
"psd_num_zero") {
102 psd_num_zero_ = op.second;
107 "pos_def option set to True: Solver only handles the indefinite case.");
109 "const_dim option set to False: Solver only handles the True case.");
147 casadi_int*& iw,
double*& w)
const {
154 m->VZ = w; w += n_*n_*
K_;
155 m->T = w; w += n_*n_*
K_;
156 m->Z = w; w += n_*n_*
K_;
157 m->X = w; w += n_*n_*
K_;
159 m->Xbar = w; w += n_*n_*
K_;
160 m->nnKa = w; w += n_*n_*
K_;
161 m->nnKb = w; w += n_*n_*
K_;
163 m->eig_real = w; w += n_;
164 m->eig_imag = w; w += n_;
166 m->F = w; w += 2*2*n_*
K_;
167 m->FF = w; w += 2*2*
K_;
169 m->A = w; w += 4*
K_*4+4*
K_;
173 m->partition = iw; iw+= n_+1;
192 for (casadi_int i=0;i<3;++i) {
193 casadi_int np = std::pow(2, i);
199 m->dpse_solvers[i].reserve(n_*(n_+1)/2);
200 for (casadi_int k=0;k<n_*(n_+1)/2;++k) {
201 m->dpse_solvers[i].push_back(
Linsol(
"solver", linear_solver_, sp));
209 casadi_int i, casadi_int j, casadi_int k, casadi_int r, casadi_int c)
const {
215 casadi_int* iw,
double* w,
void* mem)
const {
218 setup(mem, arg, res, iw, w);
224 m->dwork, m->eig_real, m->eig_imag, psd_num_zero_);
227 for (casadi_int i=0;i<n_;++i) {
228 double modulus = sqrt(m->eig_real[i]*m->eig_real[i]+m->eig_imag[i]*m->eig_imag[i]);
230 "SlicotDple: system is unstable."
231 "Found an eigenvalue " +
str(m->eig_real[i]) +
" + " +
232 str(m->eig_imag[i]) +
"j, with modulus " +
str(modulus) +
233 " (corresponding eps= " +
str(1-modulus) +
").\n" +
234 "Use options and 'error_unstable' and 'eps_unstable' to influence this message.");
239 casadi_int* p = m->partition;
242 casadi_int i = 0, j = 0;
244 while (i<n_ && m->
T[i+n_*j]!=0) i+=1;
252 for (casadi_int l=0;l<p_i-1;++l) {
255 for (casadi_int r=0;r<l+1;++r) {
257 casadi_int n1 = p[r+1]-p[r];
258 casadi_int n2 = p[l+1]-p[l];
259 casadi_int np = n1*n2;
261 casadi_assert_dev(n1-1+n2-1>=0);
263 Linsol & solver = m->dpse_solvers[n1-1+n2-1][((l+1)*l)/2+r];
267 std::fill(A, A+4*
K_*4+4*
K_, 1);
272 for (casadi_int ll=0;ll<np;++ll)
275 for (casadi_int k=0;k<
K_-1;++k) {
277 T+p[r]*n_ + p[r],
T+p[l]*n_ + p[l], A+np*(np+1)*((k+1)%
K_), n_, n_, np+1);
292 for (casadi_int d=0;d<
nrhs_;++d) {
295 for (casadi_int k=0;k<
K_;++k) {
296 double * nnKa = m->nnKa+k*n_*n_, * nnKb = m->nnKb+k*n_*n_;
299 std::fill(nnKa, nnKa+n_*n_, 0);
303 std::fill(nnKb, nnKb+n_*n_, 0);
308 std::fill(m->X, m->X+n_*n_*
K_, 0);
312 for (casadi_int l=0;l<p_i-1;++l) {
313 casadi_int n2 = p[l+1]-p[l];
317 std::fill(m->F, m->F+2*2*n_*
K_, 0);
321 for (casadi_int k=0;k<
K_;++k) {
322 double *
X = m->X+k*n_*n_, *
T = m->T+ k*n_*n_;
323 for (casadi_int i=0;i<l;++i)
324 for (casadi_int j=0;j<l;++j)
326 X+ p[i]*n_+ p[j],
T+p[l]*n_+ p[j], m->F + k*4*n_+4*i, n_, n_, 2);
330 for (casadi_int r=0;r<l+1;++r) {
331 casadi_int n1 = p[r+1]-p[r];
332 casadi_int np = n1*n2;
336 for (casadi_int k=0;k<
K_;++k) {
337 double *
X = m->X+k*n_*n_, *
T = m->T+ k*n_*n_;
338 for (casadi_int j=0;j<l;++j)
340 X+ p[r]*n_+ p[j],
T+p[l]*n_+ p[j], m->F + k*4*n_+4*r, n_, n_, 2);
347 std::fill(m->FF, m->FF+2*2*
K_, 0);
348 for (casadi_int k=0;k<
K_;++k) {
349 double *
X = m->X+k*n_*n_, *
T = m->T+ k*n_*n_;
350 for (casadi_int i=0;i<r;++i)
352 T+p[r]*n_ + p[i],
X+p[i]*n_ + p[l], m->FF+k*4, n_, n_, 2);
355 Linsol & solver = m->dpse_solvers[n1-1+n2-1][((l+1)*l)/2+r];
358 for (casadi_int k=0;k<
K_;++k)
362 for (casadi_int k=0;k<
K_;++k) {
363 double *B = m->B + np*((k+1)%
K_), *
T = m->T+ k*n_*n_;
364 for (casadi_int i=0;i<r+1;++i)
366 T+p[r]*n_+ p[i], m->F+k*4*n_+4*i, B, n_, 2, n2);
370 for (casadi_int k=0;k<
K_;++k)
372 m->FF+k*4, m->T + k*n_*n_+p[l]*n_+ p[l], m->B+np*((k+1)%
K_), 2, n_, n2);
376 solver.
solve(m->A, m->B, 1,
true);
381 for (casadi_int k=0;k<
K_;++k) {
382 double *
X = m->X+ k*n_*n_, *S = sol+ n1*n2*k;
394 for (casadi_int k=0;k<
K_;++k) {
395 std::fill(m->nnKa+k*n_*n_, m->nnKa+(k+1)*n_*n_, 0);
398 dense_mul_nn(n_, n_, n_, m->X + k*n_*n_, m->Z+ k*n_*n_, m->nnKa+ k*n_*n_);
400 dense_mul_tn(n_, n_, n_, m->Z + k*n_*n_, m->nnKa+ k*n_*n_,
410 double* t,
double * z,
411 double* dwork,
double* eig_real,
412 double *eig_imag,
double num_zero) {
413 casadi_int mem_base = std::max(n+K-2, 4*n);
414 casadi_int mem_needed = mem_base+(n-1)*K;
417 std::copy(a, a+n*n*K, z);
421 ret =
slicot_mb03vd(n, K, 1, n, z, n, n, dwork+mem_base, n-1, dwork);
422 casadi_assert(ret==0,
"mb03vd return code " +
str(ret));
423 std::copy(z, z+n*n*K, t);
425 ret =
slicot_mb03vy(n, K, 1, n, z, n, n, dwork+mem_base, n-1, dwork, mem_needed);
426 casadi_assert(ret==0,
"mb03vy return code " +
str(ret));
429 for (casadi_int k = 0;k<n*n*K;++k) {
431 if (fabs(r)<num_zero) r = 0.0;
435 ret =
slicot_mb03wd(
'S',
'V', n, K, 1, n, 1, n, t, n, n, z, n, n,
436 eig_real, eig_imag, dwork, mem_needed);
437 casadi_assert(ret==0,
"mb03wd return code " +
str(ret));
Sparsity A_
List of sparsities of A_i.
double eps_unstable_
Margin for instability detection.
bool error_unstable_
Throw an error when system is unstable.
void init(const Dict &opts) override
Initialize.
bool const_dim_
Constant dimensions.
casadi_int nrhs_
Number of right hand sides.
static const Options options_
Options.
Sparsity V_
List of sparsities of V_i.
bool pos_def_
Assume positive definiteness of P_i.
void alloc_iw(size_t sz_iw, bool persistent=false)
Ensure required length of iw field.
virtual void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const
Set the (persistent) work vectors.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
void setup(void *mem, const double **arg, double **res, casadi_int *iw, double *w) const
Set the (persistent and temporary) work vectors.
void nfact(const DM &A) const
Numeric factorization of the linear system.
DM solve(const DM &A, const DM &B, bool tr=false) const
void sfact(const DM &A) const
Symbolic factorization of the linear system, e.g. selecting pivots.
GenericMatrix< Matrix< Scalar > > B
Base class.
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
virtual int init_mem(void *mem) const
Initalize memory block.
void clear_mem()
Clear all memory (called from destructor)
static const std::string meta_doc
A documentation string.
~SlicotDple() override
Destructor.
int init_mem(void *mem) const override
Initalize memory block.
static Dple * creator(const std::string &name, const SpDict &st)
Create a new QP Solver.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Evaluate numerically.
static const Options options_
Options.
void init(const Dict &opts) override
Initialize.
static Sparsity diag(casadi_int nrow)
Create diagonal sparsity pattern *.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
static Sparsity band(casadi_int n, casadi_int p)
Create a single band in a square sparsity pattern.
int CASADI_DPLE_SLICOT_EXPORT casadi_register_dple_slicot(Dple::Plugin *plugin)
int slicot_mb03wd(char job, char compz, int n, int p, int ilo, int ihi, int iloz, int ihiz, double *h, int ldh1, int ldh2, double *z, int ldz1, int ldz2, double *wr, double *wi, double *dwork, int ldwork)
void slicot_periodic_schur(casadi_int n, casadi_int K, const double *a, double *t, double *z, double *dwork, double *eig_real, double *eig_imag, double num_zero)
int slicot_mb03vy(int n, int p, int ilo, int ihi, double *a, int lda1, int lda2, const double *tau, int ldtau, double *dwork, int ldwork)
int slicot_mb03vd(int n, int p, int ilo, int ihi, double *a, int lda1, int lda2, double *tau, int ldtau, double *dwork)
@ DPLE_A
A matrices (horzcat when const_dim, diagcat otherwise) [a].
@ DPLE_V
V matrices (horzcat when const_dim, diagcat otherwise) [v].
void dense_mul_nn(casadi_int n, casadi_int m, casadi_int l, const double *A, const double *B, double *C)
@ DPLE_P
Lyapunov matrix (horzcat when const_dim, diagcat otherwise) (Cholesky of P if pos_def) [p].
void dense_mul_tn(casadi_int n, casadi_int m, casadi_int l, const double *A, const double *B, double *C)
void dense_mul_nt(casadi_int n, casadi_int m, casadi_int l, const double *A, const double *B, double *C)
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void dense_copy_t_stride(casadi_int n, casadi_int m, const double *A, double *B, casadi_int strideA, casadi_int strideB)
void CASADI_DPLE_SLICOT_EXPORT casadi_load_dple_slicot()
void dense_kron_stride(casadi_int n, casadi_int m, const double *A, const double *B, double *C, casadi_int strideA, casadi_int strideB, casadi_int strideC)
std::map< std::string, Sparsity > SpDict
void dense_mul_nn_stride(casadi_int n, casadi_int m, casadi_int l, const double *A, const double *B, double *C, casadi_int strideA, casadi_int strideB, casadi_int strideC)
void dense_copy_stride(casadi_int n, casadi_int m, const double *A, double *B, casadi_int strideA, casadi_int strideB)
void dense_mul_nt_stride(casadi_int n, casadi_int m, casadi_int l, const double *A, const double *B, double *C, casadi_int strideA, casadi_int strideB, casadi_int strideC)
void casadi_trans(const T1 *x, const casadi_int *sp_x, T1 *y, const casadi_int *sp_y, casadi_int *tmp)
TRANS: y <- trans(x) , w work vector (length >= rows x)
std::vector< std::vector< Linsol > > dpse_solvers
Solvers for low-order Discrete Periodic Sylvester Equations.