int variationalInequality_driver(VariationalInequality* problem, 
                                 double *x, double *w, 
                                 SolverOptions* options)
{
  if (options == NULL)
    numerics_error("variationalInequality_driver", "null input for solver and/or global options");

  assert(options->isSet);
  if (verbose > 0)
    solver_options_print(options);

  /* Solver name */
  /*char * name = options->solverName;*/

  int info = -1 ;

  /* Check for trivial case */
  info = checkTrivialCase_vi(problem, x, w, options);
  if (info == 0){
    double error;
    variationalInequality_computeError(problem, x , w, options->dparam[0], options, &error);
    printf("variationalInequality_driver. error = %8.4e\n", error);
    return info;
  }

  switch (options->solverId)
  {
    /* Non Smooth Gauss Seidel (NSGS) */
  /* Extra Gradient algorithm */
  case SICONOS_VI_EG:
  {
    numerics_printf_verbose(1,
             " ========================== Call ExtraGradient (EG) solver for VI problem ==========================\n");
    variationalInequality_ExtraGradient(problem, x , w , &info , options);
    break;
  }
  case SICONOS_VI_FPP:
  {
    numerics_printf_verbose(1,
             " ========================== Call Fixed Point Projection (FPP) solver for VI problem ==========================\n");
    variationalInequality_FixedPointProjection(problem, x , w , &info , options);
    break;
  }
  case SICONOS_VI_HP:
  {
    numerics_printf_verbose(1,
             " ========================== Call Hyperplane Projection (HP) solver for VI problem ==========================\n");
    variationalInequality_HyperplaneProjection(problem, x , w , &info , options);
    break;
  }
  case SICONOS_VI_BOX_QI:
  {
    variationalInequality_box_newton_QiLSA(problem, x, w, &info, options);
    break;
  }
  case SICONOS_VI_BOX_AVI_LSA:
  {
    vi_box_AVI_LSA(problem, x, w, &info, options);
    break;
  }
  case SICONOS_VI_BOX_PATH:
  {
    vi_box_path(problem, x, w, &info, options);
    break;
  }
  default:
  {
    fprintf(stderr, "Numerics, variationalInequality_driver failed. Unknown solver.\n");
    exit(EXIT_FAILURE);

  }
  }

  return info;

}
int _globalLineSearchSparseGP(
  GlobalFrictionContactProblem *problem,
  AlartCurnierFun3x3Ptr computeACFun3x3,
  double *solution,
  double *direction,
  double *mu,
  double *rho,
  double *F,
  double *psi,
  CSparseMatrix *J,
  double *tmp,
  double alpha[1],
  unsigned int maxiter_ls)
{
  double inf = 1e10;
  double alphamin = 1e-16;
  double alphamax = inf;

  double m1 = 0.01, m2 = 0.99;

  unsigned int n = (unsigned)NM_triplet(problem->M)->m;

  unsigned int m = problem->H->size1;

  unsigned int problem_size = n+2*m;

  // Computation of q(t) and q'(t) for t =0

  double q0 = 0.5 * cblas_ddot(problem_size, psi, 1, psi, 1);

  //  tmp <- J * direction
  cblas_dscal(problem_size, 0., tmp, 1);
  cs_gaxpy(J, direction, tmp);

  double dqdt0 = cblas_ddot(problem_size, psi, 1, tmp, 1);
  DEBUG_PRINTF("dqdt0=%e\n",dqdt0);
  DEBUG_PRINTF("q0=%e\n",q0);

  for(unsigned int iter = 0; iter < maxiter_ls; ++iter)
  {

    // tmp <- alpha*direction+solution
    cblas_dcopy(problem_size, solution, 1, tmp, 1);
    cblas_daxpy(problem_size, alpha[0], direction, 1, tmp, 1);

    ACPsi(
      problem,
      computeACFun3x3,
      tmp,  /* v */
      tmp+problem->M->size0+problem->H->size1, /* P */
      tmp+problem->M->size0, /* U */
      rho, psi);

    double q  = 0.5 * cblas_ddot(problem_size, psi, 1, psi, 1);

    assert(q >= 0);

    double slope = (q - q0) / alpha[0];

    int C1 = (slope >= m2 * dqdt0);
    int C2 = (slope <= m1 * dqdt0);

    DEBUG_PRINTF("C1=%i\t C2=%i\n",C1,C2);
    if(C1 && C2)
    {
      numerics_printf_verbose(1, "---- GFC3D - NSN_AC - global line search success. Number of ls iteration = %i  alpha = %.10e, q = %.10e",
                              iter,
                              alpha[0], q);
      
      return 0;

    }
    else if(!C1)
    {
      alphamin = alpha[0];
    }
    else
    {
      // not(C2)
      alphamax = alpha[0];
    }

    if(alpha[0] < inf)
    {
      alpha[0] = 0.5 * (alphamin + alphamax);
    }
    else
    {
      alpha[0] = alphamin;
    }

  }
  numerics_printf_verbose(1,"---- GFC3D - NSN_AC - global line search unsuccessful. Max number of ls iteration reached  = %i  with alpha = %.10e",
                  maxiter_ls, alpha[0]);
  

  return -1;
}