/* Siconos is a program dedicated to modeling, simulation and control
 * of non smooth dynamical systems.
 *
 * Copyright 2021 INRIA.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

/*!\file lcp_pred.h
  \brief Header for lcp solvers with extract-predict mechanism (Unstable, under devel.)

*/
#ifndef LCP_pred_H
#define LCP_pred_H

#include "LCP_Solvers.h"

/** structure used to define the lcp problem - Deprecated.
 */
typedef struct
{
} method_lcp;


#if defined(__cplusplus) && !defined(BUILD_AS_CPP)
extern "C"
{
#endif

  /**
     lcp_solver_pred is a generic interface allowing the call of one of the LCP solvers.
     - At first, the signs of q elements are checked to detect the trivial case of positive q.\n
     - Then it tries to find z by assuming that the indices of the non-zero elements
     are the same as the previous solution (previous solutions with trivial case of q positive excepted of course).\n
     - If q is not positive and prediction failed, the regular LCP solver is called.\n

     \param[in] vec          On enter, a (\f$n \times n\f$)-vector of doubles which contains the components of the LCP matrix with a Fortran storage.
     \param[in] q            On enter, a n-vector of doubles which contains the components of the constant right hand side vector.
     \param[in] n            On enter, an integer which represents the dimension of the LCP problem.
     \param[in] ptvec          On enter, a union containing the LCP structure.
     \n \n
     \param[in,out] z        On enter, an initial guess for iterative LCP solvers.\n
     On return, a n-vector of doubles which contains the solution of the problem.
     \param[out] w           On return, a n-vector of doubles which contains the complementary solution of the problem.
     \n
     \param[in]     firsttime      At 1, forces the regular LCP solver to be used (for initialization purpose).
     \param[out]    soltype        On return, indicates how the solution was found (0 : no sol,1 : q positive,2 : prediction,3 : LCP solver)
     \param[in,out] indic          The set of indices of non-zero z values in ascending order
     \param[in,out] indicop        The complementary set of indices of "indic".
     \param[in,out] submatlcp      The submatrix of M defined by "indic".
     \param[in,out] submatlcpop    The submatrix of M defined by "indicop".
     \param[in,out] ipiv           Pivot indices in LU factorization of "submatlcp".
     \param[in,out] sizesublcp     "submatlcp" size.
     \param[in,out] sizesublcpop   "submatlcpop" size.
     \param subq
     \param bufz
     \param newz
     \param workspace
     \return integer
     - 0 : successful\n
     - >0 : otherwise (see specific solvers for more information about the log info)

  */
  int lcp_solver_pred(double *vec, double *q , int *n , method_lcp * ptvec ,
                      double *z , double *w ,
                      int firsttime, int *soltype , int *indic , int *indicop ,
                      double *submatlcp ,
                      double *submatlcpop,
                      int *ipiv, int *sizesublcp, int *sizesublcpop,
                      double *subq, double *bufz, double *newz, double *workspace);
  /**
   *  lcp_solver_block_pred_vec solves a LCP with a matrix stored block by block.\n
   *  - It iterates by solving successively diagonal sub-LCPs (Gauss-Seidel block by block).\n
   *  - "pred" means that for each diagonal sub-LCP (Mi,qi), the position of non-zero terms zi_k~ of its previous solution \n
   *  in block iteration are stored as well as the corresponding submatrix Mi~ of this diagonal block. \n
   *  Thus Mi~ * zi_k~ = -qi_k~. The solver tries first to solve the new sub-LCP (Mi,qi_k+1) \n
   *  by solving the linear system Mi~ * zi_k+1~ = -qi_k+1~. If this does not work, the regular LCP algorithm is called.\n
   *  - "vec" means that a set of LCP solver methods is provided, and applied individually to the corresponding diagonal sub-LCP.\n
   *  If there are less solvers than diagonal blocks, the last solver is applied to all last diagonal blocks.\n
   *
   * \param blmat    On enter, the sparse block matrix M of the LCP
   * \param blmatpred   On enter, the position of non-zero z values block by block and all corresponding submatrices
   * \param nbmethod On enter, the number of available solving methods provided
   * \param q        On enter, the vector of doubles of the LCP
   * \param ptvec       On enter, a pointer on the list of solving methods
   *
   * \param z        On enter/return, a vector of doubles which contains the initial iterate for the LCP(q,M) and returns the solution of the problem.
   * \param w        On return, a vector of doubles which returns the solution of the problem.
   * \param it_end   On return, an integer which returns the final number of block iterations
   * \param itt_end  On return, an integer which returns the total number of local LCP iterations or pivots
   * \param res      On return, a double which returns the final value of error criteria.
   *
   * \return info    Integer identifiant for the solver result\n
   *                 0 : convergence\n
   *                 >0 : no convergence (see solver for specific info value)\n
   *
   * \param maxiterglob
   * \param tolglob
   * lcp_solver_block_pred_vec is a generic interface which considers LCP with a sparse block structure. The global LCP is solved
   * as a succession of local LCP solved via lcp_solver_pred.\n
   *
   * list Keywords to call solvers:
   *
   *   - Lemke    for lcp_lexicolemke
   *   - PGS      for lcp_pgs
   *   - RPGS     for lcp_rpgs
   *   - CPG      for lcp_cpg
   *   - QP       for lcp_qp
   *   - NSQP     for lcp_nsqp
   *   - Latin    for lcp_latin
   *   - Newton   for lcp_newton_min
   *
   * Data file example:\n
   * If we consider the matrix M and the right-hand-side q defined as
   *
   * \f$
   * M=\left[\begin{array}{cccc|cc|cc}
   *          1 & 2 & 0 & 4   & 3 &-1   & 0 & 0\\
   *          2 & 1 & 0 & 0   & 4 & 1   & 0 & 0\\
   *          0 & 0 & 1 &-1   & 0 & 0   & 0 & 0\\
   *          5 & 0 &-1 & 6   & 0 & 6   & 0 & 0\\
   *          \hline
   *          0 & 0 & 0 & 0   & 1 & 0   & 0 & 5\\
   *          0 & 0 & 0 & 0   & 0 & 2   & 0 & 2\\
   *          \hline
   *          0 & 0 & 2 & 1   & 0 & 0   & 2 & 2\\
   *          0 & 0 & 2 & 2   & 0 & 0   & -1 & 2\\
   *        \end{array}\right] \quad, q=\left[\begin{array}{c}-1\\-1\\0\\-1\\\hline 1\\0\\\hline -1\\2\end{array}\right].
   * \f$
   *
   * then
   * - the number of non null blocks is 6 (blmat.nbblocks) and the number of diagonal blocks is 3 (blmat.size)
   * - the vector blmat.blocksize of diagonal blocks sizes is equal to [4,2,2]
   * - the vectors blmat.ColumnIndex and blmat.RowIndex of non null blocks indices are equal to [0,1,1,2,0,2] and [0,0,1,1,2,2]
   * - the blmat.block contains all non null block matrices stored in Fortran order (column by column) as\n
   *   blmat.block[0] = {1,2,0,5,2,1,0,0,0,0,1,-1,4,0,-1,6}\n
   *   blmat.block[1] = {3,4,0,0,-1,1,0,6}\n
   *   ...\n
   *   blmat.block[5] = {2,-1,2,2}
   */
  int lcp_solver_block_pred_vec(SparseBlockStructuredMatrix *blmat,
                                SparseBlockStructuredMatrixPred *blmatpred,
                                int nbmethod,
                                int maxiterglob, double tolglob,
                                double *q, method_lcp ** ptvec,
                                double *z, double *w,
                                int *it_end, int *itt_end , double *res);

#if defined(__cplusplus) && !defined(BUILD_AS_CPP)
}
#endif

#endif
