blob: 299efa55fdddd2e39f5748c1a8a0a509250aeb22 [file] [log] [blame]
/**************************************************************************************************
* *
* This file is part of HPIPM. *
* *
* HPIPM -- High Performance Interior Point Method. *
* Copyright (C) 2017 by Gianluca Frison. *
* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. *
* All rights reserved. *
* *
* HPMPC is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* HPMPC is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with HPMPC; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
* *
* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de *
* *
**************************************************************************************************/
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <blasfeo_target.h>
#include <blasfeo_common.h>
#include <blasfeo_d_blas.h>
#include <blasfeo_d_aux.h>
#include "../include/hpipm_d_ocp_qp.h"
#include "../include/hpipm_d_ocp_qp_sol.h"
#include "../include/hpipm_d_dense_qp.h"
#include "../include/hpipm_d_dense_qp_sol.h"
#include "../include/hpipm_d_cond.h"
#include "../include/hpipm_d_cond_aux.h"
void d_compute_qp_size_ocp2dense(int N, int *nx, int *nu, int *nb, int **idxb, int *ng, int *nvc, int *nec, int *nbc, int *ngc)
{
int ii, jj;
nvc[0] = 0;
nec[0] = 0;
nbc[0] = 0;
ngc[0] = 0;
// first stage
nvc[0] += nx[0]+nu[0];
nbc[0] += nb[0];
ngc[0] += ng[0];
// remaining stages
for(ii=1; ii<=N; ii++)
{
nvc[0] += nu[ii];
for(jj=0; jj<nb[ii]; jj++)
{
if(idxb[ii][jj]<nu[ii]) // input constraint
{
nbc[0]++;
}
else // state constraint
{
ngc[0]++;
}
}
ngc[0] += ng[ii];
}
return;
}
int d_memsize_cond_qp_ocp2dense(struct d_ocp_qp *ocp_qp, struct d_dense_qp *dense_qp) // XXX + args for algorithm type ???
{
int ii;
int N = ocp_qp->N;
int *nx = ocp_qp->nx;
int *nu = ocp_qp->nu;
int *nb = ocp_qp->nb;
int *ng = ocp_qp->ng;
// compute core qp size and max size
int nvt = 0;
int net = 0;
int nbt = 0;
int ngt = 0;
int nxM = 0;
int nuM = 0;
int nbM = 0;
int ngM = 0;
for(ii=0; ii<N; ii++)
{
nvt += nx[ii]+nu[ii];
net += nx[ii+1];
nbt += nb[ii];
ngt += ng[ii];
nxM = nx[ii]>nxM ? nx[ii] : nxM;
nuM = nu[ii]>nuM ? nu[ii] : nuM;
nbM = nb[ii]>nbM ? nb[ii] : nbM;
ngM = ng[ii]>ngM ? ng[ii] : ngM;
}
ii = N;
nvt += nx[ii]+nu[ii];
nbt += nb[ii];
ngt += ng[ii];
nxM = nx[ii]>nxM ? nx[ii] : nxM;
nuM = nu[ii]>nuM ? nu[ii] : nuM;
nbM = nb[ii]>nbM ? nb[ii] : nbM;
ngM = ng[ii]>ngM ? ng[ii] : ngM;
int size = 0;
size += (2+2*(N+1))*sizeof(struct d_strmat); // Gamma L Lx AL
size += (2+1*(N+1))*sizeof(struct d_strvec); // Gammab tmp_ngM tmp_nuxM
int nu_tmp = 0;
for(ii=0; ii<N; ii++)
{
nu_tmp += nu[ii];
size += d_size_strmat(nu_tmp+nx[0]+1, nx[ii+1]); // Gamma
}
for(ii=0; ii<=N; ii++)
size += d_size_strmat(nu[ii]+nx[ii]+1, nu[ii]+nx[ii]); // L
size += d_size_strmat(nxM+1, nxM); // Lx
size += d_size_strmat(nuM+nxM+1, nxM); // AL
for(ii=0; ii<N; ii++)
size += 1*d_size_strvec(nx[ii+1]); // Gammab
size += d_size_strvec(ngM); // tmp_ngM
size += 1*d_size_strvec(nuM+nxM); // tmp_nuxM
size += 1*d_size_strvec(ngM); // tmp_ngM
size = (size+63)/64*64; // make multiple of typical cache line size
size += 1*64; // align once to typical cache line size
return size;
}
void d_create_cond_qp_ocp2dense(struct d_ocp_qp *ocp_qp, struct d_dense_qp *dense_qp, struct d_cond_qp_ocp2dense_workspace *cond_ws, void *mem)
{
int ii;
int N = ocp_qp->N;
int *nx = ocp_qp->nx;
int *nu = ocp_qp->nu;
int *nb = ocp_qp->nb;
int *ng = ocp_qp->ng;
// compute core qp size and max size
int nvt = 0;
int net = 0;
int nbt = 0;
int ngt = 0;
int nxM = 0;
int nuM = 0;
int nbM = 0;
int ngM = 0;
for(ii=0; ii<N; ii++)
{
nvt += nx[ii]+nu[ii];
net += nx[ii+1];
nbt += nb[ii];
ngt += ng[ii];
nxM = nx[ii]>nxM ? nx[ii] : nxM;
nuM = nu[ii]>nuM ? nu[ii] : nuM;
nbM = nb[ii]>nbM ? nb[ii] : nbM;
ngM = ng[ii]>ngM ? ng[ii] : ngM;
}
ii = N;
nvt += nx[ii]+nu[ii];
nbt += nb[ii];
ngt += ng[ii];
nxM = nx[ii]>nxM ? nx[ii] : nxM;
nuM = nu[ii]>nuM ? nu[ii] : nuM;
nbM = nb[ii]>nbM ? nb[ii] : nbM;
ngM = ng[ii]>ngM ? ng[ii] : ngM;
// matrix struct
struct d_strmat *sm_ptr = (struct d_strmat *) mem;
cond_ws->Gamma = sm_ptr;
sm_ptr += N+1;
cond_ws->L = sm_ptr;
sm_ptr += N+1;
cond_ws->Lx = sm_ptr;
sm_ptr += 1;
cond_ws->AL = sm_ptr;
sm_ptr += 1;
// vector struct
struct d_strvec *sv_ptr = (struct d_strvec *) sm_ptr;
cond_ws->Gammab = sv_ptr;
sv_ptr += N+1;
cond_ws->tmp_ngM = sv_ptr;
sv_ptr += 1;
cond_ws->tmp_nuxM = sv_ptr;
sv_ptr += 1;
// align to typicl cache line size
size_t s_ptr = (size_t) sv_ptr;
s_ptr = (s_ptr+63)/64*64;
// void stuf
char *c_ptr = (char *) s_ptr;
char *c_tmp;
int nu_tmp = 0;
for(ii=0; ii<N; ii++)
{
nu_tmp += nu[ii];
d_create_strmat(nu_tmp+nx[0]+1, nx[ii+1], cond_ws->Gamma+ii, c_ptr);
c_ptr += (cond_ws->Gamma+ii)->memory_size;
}
for(ii=0; ii<=N; ii++)
{
d_create_strmat(nu[ii]+nx[ii]+1, nu[ii]+nx[ii], cond_ws->L+ii, c_ptr);
c_ptr += (cond_ws->L+ii)->memory_size;
}
d_create_strmat(nxM+1, nxM, cond_ws->Lx, c_ptr);
c_ptr += cond_ws->Lx->memory_size;
d_create_strmat(nuM+nxM+1, nxM, cond_ws->AL, c_ptr);
c_ptr += cond_ws->AL->memory_size;
for(ii=0; ii<N; ii++)
{
d_create_strvec(nx[ii+1], cond_ws->Gammab+ii, c_ptr);
c_ptr += (cond_ws->Gammab+ii)->memory_size;
}
d_create_strvec(ngM, cond_ws->tmp_ngM, c_ptr);
c_ptr += cond_ws->tmp_ngM->memory_size;
c_tmp = c_ptr;
d_create_strvec(nuM+nxM, cond_ws->tmp_nuxM, c_ptr);
c_ptr += cond_ws->tmp_nuxM->memory_size;
cond_ws->memsize = d_memsize_cond_qp_ocp2dense(ocp_qp, dense_qp);
return;
}
void d_cond_qp_ocp2dense(struct d_ocp_qp *ocp_qp, struct d_dense_qp *dense_qp, struct d_cond_qp_ocp2dense_workspace *cond_ws)
{
d_compute_Gamma(ocp_qp, cond_ws);
d_cond_RSQrq_N2nx3(ocp_qp, dense_qp->Hg, dense_qp->g, cond_ws);
d_cond_DCtd(ocp_qp, dense_qp->idxb, dense_qp->d_lb, dense_qp->d_ub, dense_qp->Ct, dense_qp->d_lg, dense_qp->d_ug, cond_ws);
return;
}
void d_expand_sol_dense2ocp(struct d_ocp_qp *ocp_qp, struct d_dense_qp_sol *dense_qp_sol, struct d_ocp_qp_sol *ocp_qp_sol, struct d_cond_qp_ocp2dense_workspace *cond_ws)
{
d_expand_sol(ocp_qp, dense_qp_sol, ocp_qp_sol->ux, ocp_qp_sol->pi, ocp_qp_sol->lam_lb, ocp_qp_sol->lam_ub, ocp_qp_sol->lam_lg, ocp_qp_sol->lam_ug, ocp_qp_sol->t_lb, ocp_qp_sol->t_ub, ocp_qp_sol->t_lg, ocp_qp_sol->t_ug, cond_ws->tmp_nuxM, cond_ws->tmp_ngM);
return;
}