示例#1
0
GlobalFrictionContactProblem* from_fclib_global(const struct fclib_global* fclib_problem)
{
  GlobalFrictionContactProblem* problem;

  problem = malloc(sizeof(GlobalFrictionContactProblem));

  problem->dimension = fclib_problem->spacedim;
  problem->mu = fclib_problem->mu;
  problem->q = fclib_problem->f;
  problem->b = fclib_problem->w;

  problem->numberOfContacts = fclib_problem->H->n / fclib_problem->spacedim; /* cf fclib spec */

  problem->M = newNumericsMatrix();
  problem->M->storageType = 2; /* sparse */
  problem->M->size0 = fclib_problem->M->m;
  problem->M->size1 = fclib_problem->M->n;
  problem->M->matrix2 = newNumericsSparseMatrix();
  problem->M->matrix2->triplet=(CSparseMatrix*)fclib_problem->M;
  problem->M->matrix0 = NULL;
  problem->M->matrix1 = NULL;

  problem->H = newNumericsMatrix();
  problem->H->storageType = 2; /* sparse */
  problem->H->size0 = fclib_problem->H->m;
  problem->H->size1 = fclib_problem->H->n;
  problem->H->matrix2 = newNumericsSparseMatrix();
  problem->H->matrix2->triplet=(CSparseMatrix*)fclib_problem->H;
  problem->H->matrix0 = NULL;
  problem->H->matrix1 = NULL;

  return problem;

}
示例#2
0
NumericsMatrix* createNumericsMatrix(int storageType, int size0, int size1)
{
    NumericsMatrix* M = newNumericsMatrix();

    void* data;

    switch (storageType)
    {
    case NM_DENSE:
        data = malloc(size0*size1*sizeof(double));
        break;
    case NM_SPARSE_BLOCK:
        data = newSBM();
        break;
    case NM_SPARSE:
        data = newNumericsSparseMatrix();
        break;
    default:
        printf("createNumericsMatrix :: storageType value %d not implemented yet !", storageType);
        exit(EXIT_FAILURE);
    }

    fillNumericsMatrix(M, storageType, size0, size1, data);

    return M;
}
示例#3
0
NumericsSparseMatrix* NM_sparse(NumericsMatrix* A)
{
    if(!A->matrix2)
    {
        A->matrix2 = newNumericsSparseMatrix();
    }
    return A->matrix2;
}
示例#4
0
void NM_copy_to_sparse(const NumericsMatrix* const A, NumericsMatrix* B)
{
    assert(A);
    assert(B);
    B->size0 = A->size0;
    B->size1 = A->size1;

    assert(B->storageType == NM_SPARSE);
    if (!B->matrix2)
    {
        B->matrix2 = newNumericsSparseMatrix();
    }

    switch (A->storageType)
    {
    case NM_DENSE:
    {
        B->matrix2->triplet = cs_spalloc(0,0,1,1,1);
        NM_dense_to_sparse(A, B);
        break;
    }
    case NM_SPARSE_BLOCK:
    {
        // XXX this is suboptimal since the matrix A might have already been converted
        // to csc or triplet --xhub
        B->matrix1 = A->matrix1;
        B->storageType = NM_SPARSE_BLOCK;
        NM_triplet(B);
        B->matrix1 = NULL;
        B->storageType = NM_SPARSE;
        break;
    }
    case NM_SPARSE:
    {
        NM_copy(A, B);
        break;
    }
    default:
    {
        printf("NM_copy_to_sparse :: Unsupported storage type %d, exiting!\n", A->storageType);
        exit(EXIT_FAILURE);
    }
    }
}
示例#5
0
int gfc3d_LmgcDriver(double *reaction,
                                       double *velocity,
                                       double *globalVelocity,
                                       double *q,
                                       double *b,
                                       double *mu,
                                       double *Mdata,
                                       unsigned int nzM,
                                       unsigned int *rowM,
                                       unsigned int *colM,
                                       double* Hdata,
                                       unsigned int nzH,
                                       unsigned int *rowH,
                                       unsigned int *colH,
                                       unsigned int n,
                                       unsigned int nc,
                                       int solver_id,
                                       int isize,
                                       int *iparam,
                                       int dsize,
                                       double *dparam,
                                       int verbose,
                                       int outputFile,
                                       int freq_output)
{

  /* NumericsMatrix M, H; */
  NumericsMatrix * M =newNumericsMatrix();
  M->storageType = 2; /* sparse */
  M->size0 = n;
  M->size1 = n;


  NumericsMatrix * H =newNumericsMatrix();
  H->storageType = 2;
  H->size0 = M->size0;
  H->size1 = 3 * nc;

  NumericsSparseMatrix * SM =newNumericsSparseMatrix();
  M->matrix2 = SM;
  SM->triplet =   (CSparseMatrix * )malloc(sizeof(CSparseMatrix));
  CSparseMatrix * _M = SM->triplet;
  SM->origin = NS_TRIPLET;

  csi * _colM = alloc_memory_csi(nzM, colM);
  csi * _rowM = alloc_memory_csi(nzM, rowM);

  _M->nzmax = nzM;
  _M->nz = nzM;
  _M->m = M->size0;
  _M->n = M->size1;
  _M->p = (csi *) _colM;
  _M->i = (csi *) _rowM;
  double * _Mdata = alloc_memory_double(nzM, Mdata);
  _M->x = _Mdata;

  DEBUG_PRINTF("_M->n=%li\t",_M->n);
  DEBUG_PRINTF("_M->m=%li\n",_M->m);

  NumericsSparseMatrix * SH =newNumericsSparseMatrix();
  H->matrix2 = SH;
  SH->triplet =   (CSparseMatrix * )malloc(sizeof(CSparseMatrix));
  CSparseMatrix * _H = SH->triplet;
  SH->origin = NS_TRIPLET;

  csi * _colH = alloc_memory_csi(nzH, colH);
  csi * _rowH = alloc_memory_csi(nzH, rowH);

  _H->nzmax = nzH;
  _H->nz = nzH;
  _H->m = H->size0;
  _H->n = H->size1;

  _H->p = _colH;
  _H->i =  _rowH;
  double * _Hdata = alloc_memory_double(nzH, Hdata);
  _H->x = _Hdata;

  for (int i=0; i< _M->nz; ++i)
  {
    _M->p[i] --;
    _M->i[i] --;
    /* DEBUG_PRINTF("%d -> %d,%d\n", i, _M->p[i], _M->i[i]); */

  }

  for (int i=0; i< _H->nz; ++i)
  {
    _H->p[i] --;
    _H->i[i] --;
    /* DEBUG_PRINTF("%d -> %d,%d\n", i, _H->p[i], _H->i[i]); */
  }

  GlobalFrictionContactProblem * problem =(GlobalFrictionContactProblem*)malloc(sizeof(GlobalFrictionContactProblem));

  problem->dimension = 3;
  problem->numberOfContacts = nc;
  problem->env = NULL;
  problem->workspace = NULL;

  problem->M = M;
  problem->H = H;
  problem->q = q;
  problem->b = b;
  problem->mu = mu;

  SolverOptions numerics_solver_options;

  gfc3d_setDefaultSolverOptions(&numerics_solver_options, solver_id);

  int iSize_min = isize < numerics_solver_options.iSize ? isize : numerics_solver_options.iSize;
  for (int i = 0; i < iSize_min; ++i) 
    numerics_solver_options.iparam[i] = iparam[i];

  int dSize_min = dsize <  numerics_solver_options.dSize ? dsize : numerics_solver_options.dSize;
  for (int i=0; i < dSize_min; ++i)
    numerics_solver_options.dparam[i] = dparam[i];

  /* solver_options_print(&numerics_solver_options); */
  /* FILE * file  =  fopen("toto.dat", "w"); */
  /* globalFrictionContact_printInFile(problem, file); */
  /* fclose(file); */
  int rinfo =  gfc3d_driver(problem,
			    reaction,
			    velocity,
			    globalVelocity,
			    &numerics_solver_options);

  /* FILE * file1  =  fopen("tutu.dat", "w"); */
  /* globalFrictionContact_printInFile(problem, file1); */
  /* fclose(file1); */
  if(outputFile == 1)
  {
    /* dump in C format */
  }
  else if (outputFile == 2)
  {
    /* dump in Numerics .dat format */
  }
  else if (outputFile == 3)
  {
#ifdef WITH_FCLIB
    fccounter++;
    if (fccounter % freq_output == 0)
    {
      char fname[256];
      snprintf(fname, sizeof(fname), "LMGC_GFC3D-i%.5d-%i-%.5d.hdf5", numerics_solver_options.iparam[7], nc, fccounter);
      printf("Dump LMGC_GFC3D-i%.5d-%i-%.5d.hdf5.\n", numerics_solver_options.iparam[7], nc, fccounter);
      /* printf("ndof = %i.\n", ndof); */

      FILE * foutput  =  fopen(fname, "w");
      int n = 100;
      char * title = (char *)malloc(n * sizeof(char *));
      strncpy(title, "LMGC dump in hdf5", n);
      char * description = (char *)malloc(n * sizeof(char *));

      snprintf(description, n, "Rewriting in hdf5 through siconos of %s in FCLIB format", fname);
      char * mathInfo = (char *)malloc(n * sizeof(char *));
      strncpy(mathInfo, "unknown", n);

      globalFrictionContact_fclib_write(problem,
                                        title,
                                        description,
                                        mathInfo,
                                        fname);


      fclose(foutput);
    }
#else
    printf("Fclib is not available ...\n");
#endif

  }


  freeNumericsMatrix(M);
  freeNumericsMatrix(H);
  free(M);
  free(H);
  free(problem);

  /* free(_colM); */
  /* free(_colH); */

  /* free(_rowM); */
  /* free(_rowH); */

  return rinfo;
}
示例#6
0
GlobalFrictionContactProblem* from_fclib_global(const struct fclib_global* fclib_problem)
{
  GlobalFrictionContactProblem* problem;

  problem = malloc(sizeof(GlobalFrictionContactProblem));

  problem->dimension = fclib_problem->spacedim;
  problem->mu = fclib_problem->mu;
  problem->q = fclib_problem->f;
  problem->b = fclib_problem->w;

  problem->numberOfContacts = fclib_problem->H->n / fclib_problem->spacedim; /* cf fclib spec */

  problem->M = newNumericsMatrix();
  problem->M->storageType = 2; /* sparse */
  problem->M->size0 = fclib_problem->M->m;
  problem->M->size1 = fclib_problem->M->n;
  problem->M->matrix2 = newNumericsSparseMatrix();
  problem->M->matrix0 = NULL;
  problem->M->matrix1 = NULL;

  CSparseMatrix * M = (CSparseMatrix*)malloc(sizeof(CSparseMatrix));
  M->nzmax = (csi) fclib_problem->M->nzmax;
  M->m = (csi) fclib_problem->M->m;
  M->n = (csi) fclib_problem->M->n;
 
  M->x =  fclib_problem->M->x;
  
  if (fclib_problem->M->nz == -1)
  {
    /* compressed colums */
    problem->M->matrix2->csc= M;
    problem->M->matrix2->triplet=NULL;
    problem->M->matrix2->trans_csc=NULL;
    M->nz = (csi) fclib_problem->M->nz;
    M->p = (csi*) malloc(sizeof(csi)*(M->n+1));
    int_to_csi(fclib_problem->M->p, M->p, (unsigned) (M->n+1));
  }
  else if (fclib_problem->M->nz == -2)
  {
    /* compressed rows */
    M->nz = (csi) fclib_problem->M->nz;
    M->p = (csi*) malloc(sizeof(csi)*(M->m+1));
    int_to_csi(fclib_problem->M->p, M->p, (unsigned) (M->m+1));
    /* since  problem->M->matrix2->csr does not exist, we need
       to fill transform M into a triplet or csc before returning
     */
    
    fprintf(stderr, "from_fclib_local not implemented for csr matrices.\n");
    exit(EXIT_FAILURE); ;
  }
  else
  {
    /* triplet */
    problem->M->matrix2->triplet=M;
    problem->M->matrix2->csc=NULL;
    problem->M->matrix2->trans_csc=NULL;
    M->nz = (csi) fclib_problem->M->nz;
    M->p = (csi*) malloc(sizeof(csi)*M->nzmax);
    int_to_csi(fclib_problem->M->p, M->p, (unsigned) M->nzmax);
  }
  M->i = (csi*) malloc(sizeof(csi)*M->nzmax);
  int_to_csi(fclib_problem->M->i, M->i, (unsigned) M->nzmax);

  
  problem->H = newNumericsMatrix();
  problem->H->storageType = 2; /* sparse */
  problem->H->size0 = fclib_problem->H->m;
  problem->H->size1 = fclib_problem->H->n;
  problem->H->matrix2 = newNumericsSparseMatrix();
  problem->H->matrix0 = NULL;
  problem->H->matrix1 = NULL;
  
  CSparseMatrix * H = (CSparseMatrix*)malloc(sizeof(CSparseMatrix));;

  H->nzmax = (csi) fclib_problem->H->nzmax;
  H->m = (csi) fclib_problem->H->m;
  H->n = (csi) fclib_problem->H->n;
  H->nz = (csi) fclib_problem->H->nz;
  H->x =  fclib_problem->H->x;

  if (fclib_problem->H->nz == -1)
  {
    /* compressed colums */
    problem->H->matrix2->csc= H;
    problem->H->matrix2->triplet=NULL;
    problem->H->matrix2->trans_csc=NULL;
    H->p = (csi*) malloc(sizeof(csi)*(H->n+1));
    int_to_csi(fclib_problem->H->p, H->p, (unsigned) (H->n+1));
  }
  else if (fclib_problem->H->nz == -2)
  {
    /* compressed rows */
    fprintf(stderr, "from_fclib_local not implemented for csr matrices.\n");
    exit(EXIT_FAILURE); ;
  }
  else
  {
    /* triplet */
    problem->H->matrix2->triplet=H;
    problem->H->matrix2->csc=NULL;
    problem->H->matrix2->trans_csc=NULL;
    H->p = (csi*) malloc(sizeof(csi)*H->nzmax);
    int_to_csi(fclib_problem->H->p, H->p, (unsigned) H->nzmax);
  }

  H->i = (csi*) malloc(sizeof(csi)*H->nzmax);
  int_to_csi(fclib_problem->H->i, H->i, (unsigned) H->nzmax);



  
  return problem;

}
示例#7
0
void NM_copy(const NumericsMatrix* const A, NumericsMatrix* B)
{
    int sizeA = A->size0 * A->size1;
    int sizeB = B->size0 * B->size1;
    B->size0 = A->size0;
    B->size1 = A->size1;

    switch (A->storageType)
    {
    case NM_DENSE:
    {
        if (B->matrix0)
        {
            if (sizeB < sizeA)
            {
                B->matrix0 = (double*) realloc(B->matrix0, sizeA * sizeof(double));
            }
        }
        else
        {
            B->matrix0 = (double*) malloc(sizeA * sizeof(double));
        }
        cblas_dcopy(sizeA, A->matrix0, 1, B->matrix0, 1);

        /* invalidations */
        NM_clearSparseBlock(B);
        NM_clearSparseStorage(B);

        break;
    }
    case NM_SPARSE_BLOCK:
    {
        int need_blocks = 0;

        SparseBlockStructuredMatrix* A_ = A->matrix1;
        SparseBlockStructuredMatrix* B_ = B->matrix1;

        if (B_)
        {
            if (B_->nbblocks < A_->nbblocks)
            {
                need_blocks = 1;
                for (unsigned i=0; i<B_->nbblocks; ++i)
                {
                    free(B_->block [i]);
                    B_->block [i] = NULL;
                }
                B_->block = (double **) realloc(B_->block, A_->nbblocks * sizeof(double *));
            }
            B_->nbblocks = A_->nbblocks;

            if (B_->blocknumber0 < A_->blocknumber0)
            {
                B_->blocksize0 = (unsigned int*) realloc(B_->blocksize0, A_->blocknumber0 * sizeof(unsigned int));
            }
            B_->blocknumber0 = A_->blocknumber0;

            if (B_->blocknumber1 < A_->blocknumber1)
            {
                B_->blocksize1 = (unsigned int*) realloc(B_->blocksize1, A_->blocknumber1 * sizeof(unsigned int));
            }
            B_->blocknumber1 = A_->blocknumber1;

            if (B_->filled1 < A_->filled1)
            {
                B_->index1_data = (size_t*) realloc(B_->index1_data, A_->filled1 * sizeof(size_t));
            }
            B_->filled1 = A_->filled1;

            if (B_->filled2 < A_->filled2)
            {
                B_->index2_data = (size_t*) realloc(B_->index2_data, A_->filled2 * sizeof(size_t));
            }
            B_->filled2 = A_->filled2;
        }
        else
        {
            B->matrix1 = newSBM();
            B_ = B->matrix1;

            B_->block = (double **) malloc(A_->nbblocks * sizeof(double *));
            B_->nbblocks = A_->nbblocks;

            B_->blocksize0 = (unsigned int*) malloc(A_->blocknumber0 * sizeof(unsigned int));
            B_->blocknumber0 = A_->blocknumber0;

            B_->blocksize1 = (unsigned int*) malloc(A_->blocknumber1 * sizeof(unsigned int));
            B_->blocknumber1 = A_->blocknumber1;

            B_->index1_data = (size_t*) malloc(A_->filled1 * sizeof(size_t));
            B_->filled1 = A_->filled1;

            B_->index2_data = (size_t*) malloc(A_->filled2 * sizeof(size_t));
            B_->filled2 = A_->filled2;
        }

        memcpy(B_->blocksize0, A_->blocksize0, A_->blocknumber0 * sizeof(unsigned int));
        memcpy(B_->blocksize1, A_->blocksize1, A_->blocknumber1 * sizeof(unsigned int));
        memcpy(B_->index1_data, A_->index1_data, A_->filled1 * sizeof(size_t));
        memcpy(B_->index2_data, A_->index2_data, A_->filled2 * sizeof(size_t));

        /* cf copySBM */
        unsigned int currentRowNumber ;
        size_t colNumber;
        unsigned int nbRows, nbColumns;
        for (currentRowNumber = 0 ; currentRowNumber < A_->filled1 - 1; ++currentRowNumber)
        {
            for (size_t blockNum = A_->index1_data[currentRowNumber];
                    blockNum < A_->index1_data[currentRowNumber + 1]; ++blockNum)
            {
                assert(blockNum < A_->filled2);
                colNumber = A_->index2_data[blockNum];
                /* Get dim. of the current block */
                nbRows = A_->blocksize0[currentRowNumber];
                if (currentRowNumber != 0)
                    nbRows -= A_->blocksize0[currentRowNumber - 1];
                nbColumns = A_->blocksize1[colNumber];

                if (colNumber != 0)
                    nbColumns -= A_->blocksize1[colNumber - 1];

                if (need_blocks)
                {
                    B_->block[blockNum] = (double*)malloc(nbRows * nbColumns * sizeof(double));
                }

                for (unsigned int i = 0; i < nbRows * nbColumns; i++)
                {
                    B_->block[blockNum] [i] = A_->block[blockNum] [i] ;
                }
            }
        }

        /* invalidations */
        NM_clearDense(B);
        NM_clearSparseStorage(B);

        break;
    }
    case NM_SPARSE:
    {
        CSparseMatrix* A_;
        CSparseMatrix* B_;

        if (!B->matrix2)
        {
            B->matrix2 = newNumericsSparseMatrix();
        }

        if (A->matrix2->triplet)
        {
            A_ = A->matrix2->triplet;

            if (!B->matrix2->triplet)
            {
                B->matrix2->triplet = cs_spalloc(A_->m, A_->n, A_->nzmax, 0, 1);
            }

            B_ = B->matrix2->triplet;
        }
        else
        {
            assert (A->matrix2->csc);

            A_ = A->matrix2->csc;

            if (!B->matrix2->csc)
            {
                B->matrix2->csc = cs_spalloc(A_->m, A_->n, A_->nzmax, 0, 0);
            }

            B_ = B->matrix2->csc;
        }

        assert (A_);
        assert (B_);

        if (B_ ->nzmax < A_ ->nzmax)
        {
            B_->x = (double *) realloc(B_->x, A_->nzmax * sizeof(double));
            B_->i = (csi *) realloc(B_->i, A_->nzmax * sizeof(csi));
        }
        else if (!(B_->x))
        {
            B_->x = (double *) malloc(A_->nzmax * sizeof(double));
        }

        if (A_->nz >= 0)
        {
            /* triplet */
            B_->p = (csi *) realloc(B_->p, A_->nzmax * sizeof(csi));
        }
        else
        {
            if (B_->n < A_->n)
            {
                /* csc */
                B_-> p = (csi *) realloc(B_->p, (A_->n + 1) * sizeof(csi));
            }
        }

        B_->nzmax = A_->nzmax;
        B_->nz = A_->nz;
        B_->m = A_->m;
        B_->n = A_->n;

        memcpy(B_->x, A_->x, A_->nzmax * sizeof(double));
        memcpy(B_->i, A_->i, A_->nzmax * sizeof(csi));

        if (A_->nz >= 0)
        {
            memcpy(B_->p, A_->p, A_->nzmax * sizeof(csi));
        }
        else
        {
            memcpy(B_->p, A_->p, (A_->n + 1) * sizeof(csi));
        }


        /* invalidations */
        NM_clearDense(B);
        NM_clearSparseBlock(B);

        if (B_->nz >= 0)
        {
            NM_clearCSC(B);
            NM_clearCSCTranspose(B);
        }
        else
        {
            NM_clearTriplet(B);
        }

        break;
    }
    }
}
/* Alart & Curnier solver for sparse global problem */
void gfc3d_nonsmooth_Newton_AlartCurnier(
  GlobalFrictionContactProblem* problem,
  double *reaction,
  double *velocity,
  double *globalVelocity,
  int *info,
  SolverOptions* options)
{

  assert(problem);
  assert(reaction);
  assert(velocity);
  assert(info);
  assert(options);

  assert(problem->dimension == 3);

  assert(options->iparam);
  assert(options->dparam);

  assert(problem->q);
  assert(problem->mu);
  assert(problem->M);
  assert(problem->H);

  assert(!problem->M->matrix0);
//  assert(problem->M->matrix1);

  assert(!options->iparam[4]); // only host

  /* M is square */
  assert(problem->M->size0 == problem->M->size1);

  assert(problem->M->size0 == problem->H->size0);

  unsigned int iter = 0;
  unsigned int itermax = options->iparam[0];
  unsigned int erritermax = options->iparam[7];

  if (erritermax == 0)
  {
    /* output a warning here */
    erritermax = 1;
  }

  assert(itermax > 0);
  assert(options->iparam[3] > 0);

  double tolerance = options->dparam[0];
  assert(tolerance > 0);

  if (verbose > 0)
    printf("------------------------ GFC3D - _nonsmooth_Newton_AlartCurnier - Start with tolerance = %g\n", tolerance);


  /* sparse triplet storage */
  NM_triplet(problem->M);
  NM_triplet(problem->H);

  unsigned int ACProblemSize = sizeOfPsi(NM_triplet(problem->M),
                                         NM_triplet(problem->H));

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

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

  assert((int)localProblemSize == problem->numberOfContacts * problem->dimension);

  assert((int)globalProblemSize == problem->H->size0); /* size(velocity) ==
                                                   * Htrans*globalVelocity */


  AlartCurnierFun3x3Ptr computeACFun3x3 = NULL;

  switch (options->iparam[10])
  {
  case 0:
  {
    computeACFun3x3 = &computeAlartCurnierSTD;
    break;
  }
  case 1:
  {
    computeACFun3x3 = &computeAlartCurnierJeanMoreau;
    break;
  };
  case 2:
  {
    computeACFun3x3 = &fc3d_AlartCurnierFunctionGenerated;
    break;
  }
  case 3:
  {
    computeACFun3x3 = &fc3d_AlartCurnierJeanMoreauFunctionGenerated;
    break;
  }
  }

  if(options->iparam[9] == 0)
  {
    /* allocate memory */
    assert(options->dWork == NULL);
    assert(options->iWork == NULL);
    options->dWork = (double *) malloc(
                       (localProblemSize + /* F */
                        3 * localProblemSize + /* A */
                        3 * localProblemSize + /* B */
                        localProblemSize + /* rho */
                        ACProblemSize + /* psi */
                        ACProblemSize + /* rhs */
                        ACProblemSize + /* tmp2 */
                        ACProblemSize + /* tmp3 */
                        ACProblemSize   /* solution */) *  sizeof(double));

    /* XXX big hack here */
    options->iWork = (int *) malloc(
                       (3 * localProblemSize + /* iA */
                        3 * localProblemSize + /* iB */
                        3 * localProblemSize + /* pA */
                        3 * localProblemSize)  /* pB */
                       * sizeof(csi));

    options->iparam[9] = 1;

  }

  assert(options->dWork != NULL);
  assert(options->iWork != NULL);

  double *F = options->dWork;
  double *A = F +   localProblemSize;
  double *B = A +   3 * localProblemSize;
  double *rho = B + 3 * localProblemSize;

  double * psi = rho + localProblemSize;
  double * rhs = psi + ACProblemSize;
  double * tmp2 = rhs + ACProblemSize;
  double * tmp3 = tmp2 + ACProblemSize;
  double * solution = tmp3 + ACProblemSize;

  /* XXX big hack --xhub*/
  csi * iA = (csi *)options->iWork;
  csi * iB = iA + 3 * localProblemSize;
  csi * pA = iB + 3 * localProblemSize;
  csi * pB = pA + 3 * localProblemSize;

  CSparseMatrix A_;
  CSparseMatrix B_;
  CSparseMatrix *J;

  A_.p = pA;
  B_.p = pB;
  A_.i = iA;
  B_.i = iB;

  init3x3DiagBlocks(problem->numberOfContacts, A, &A_);
  init3x3DiagBlocks(problem->numberOfContacts, B, &B_);

  J = cs_spalloc(NM_triplet(problem->M)->n + A_.m + B_.m,
                 NM_triplet(problem->M)->n + A_.m + B_.m,
                 NM_triplet(problem->M)->nzmax + 2*NM_triplet(problem->H)->nzmax +
                 2*A_.n + A_.nzmax + B_.nzmax, 1, 1);

  assert(A_.n == problem->H->size1);
  assert(A_.nz == problem->numberOfContacts * 9);
  assert(B_.n == problem->H->size1);
  assert(B_.nz == problem->numberOfContacts * 9);

  fc3d_AlartCurnierFunction(
    localProblemSize,
    computeACFun3x3,
    reaction, velocity,
    problem->mu, rho,
    F, A, B);

  csi Astart = initACPsiJacobian(NM_triplet(problem->M),
                                 NM_triplet(problem->H),
                                 &A_, &B_, J);

  assert(Astart > 0);

  assert(A_.m == A_.n);
  assert(B_.m == B_.n);

  assert(A_.m == problem->H->size1);

  // compute rho here
  for(unsigned int i = 0; i < localProblemSize; ++i) rho[i] = 1.;

  // direction
  for(unsigned int i = 0; i < ACProblemSize; ++i) rhs[i] = 0.;



  // quick hack to make things work
  // need to use the functions from NumericsMatrix --xhub


  NumericsMatrix *AA_work = createNumericsMatrix(NM_SPARSE,  (int)J->m, (int)J->n);

  NumericsSparseMatrix* SM = newNumericsSparseMatrix();
  SM->triplet = J;
  NumericsMatrix *AA = createNumericsMatrixFromData(NM_SPARSE,  (int)J->m, (int)J->n, SM);

  info[0] = 1;

  /* update local velocity from global velocity */
  /* an assertion ? */
  cblas_dcopy(localProblemSize, problem->b, 1, velocity, 1);
  NM_tgemv(1., problem->H, globalVelocity, 1, velocity);
  double linear_solver_residual=0.0;
  while(iter++ < itermax)
  {

    /* compute psi */
    ACPsi(problem, computeACFun3x3, globalVelocity, reaction, velocity, rho, psi);

    /* compute A & B */
    fc3d_AlartCurnierFunction(localProblemSize,
                              computeACFun3x3,
                              reaction, velocity,
                              problem->mu, rho,
                              F, A, B);
    /* update J */
    updateACPsiJacobian(NM_triplet(problem->M),
                        NM_triplet(problem->H),
                        &A_, &B_, J, Astart);

    /* rhs = -psi */
    cblas_dcopy(ACProblemSize, psi, 1, rhs, 1);
    cblas_dscal(ACProblemSize, -1., rhs, 1);

    /* get compress column storage for linear ops */
    CSparseMatrix* Jcsc = cs_compress(J);

    /* Solve: J X = -psi */

    /* Solve: AWpB X = -F */
    NM_copy(AA, AA_work);

    int info_solver = NM_gesv(AA_work, rhs);
    if (info_solver > 0)
    {
      fprintf(stderr, "------------------------ GFC3D - NSN_AC - solver failed info = %d\n", info_solver);
      break;
      info[0] = 2;
      CHECK_RETURN(!cs_check_triplet(NM_triplet(AA_work)));
    }

    /* Check the quality of the solution */
    if (verbose > 0)
    {
      cblas_dcopy_msan(ACProblemSize, psi, 1, tmp3, 1);
      NM_gemv(1., AA, rhs, 1., tmp3);
      linear_solver_residual = cblas_dnrm2(ACProblemSize, tmp3, 1);
      /* fprintf(stderr, "fc3d esolve: linear equation residual = %g\n", */
      /*         cblas_dnrm2(problemSize, tmp3, 1)); */
      /* for the component wise scaled residual: cf mumps &
       * http://www.netlib.org/lapack/lug/node81.html */
    }

    /* line search */
    double alpha = 1;

    /* set current solution */
    for(unsigned int i = 0; i < globalProblemSize; ++i)
    {
      solution[i] = globalVelocity[i];
    }
    for(unsigned int i = 0; i < localProblemSize; ++i)
    {
      solution[i+globalProblemSize] = velocity[i];
      solution[i+globalProblemSize+localProblemSize] = reaction[i];
    }

    DEBUG_EXPR_WE(
      for(unsigned int i = 0; i < globalProblemSize; ++i)
      {
        printf("globalVelocity[%i] = %6.4e\n",i,globalVelocity[i]);
      }
      for(unsigned int i = 0; i < localProblemSize; ++i)
      {
        printf("velocity[%i] = %6.4e\t",i,velocity[i]);
        printf("reaction[%i] = %6.4e\n",i,reaction[i]);
      }
      );


    int info_ls = _globalLineSearchSparseGP(problem,
                                            computeACFun3x3,
                                            solution,
                                            rhs,
                                            globalVelocity,
                                            reaction, velocity,
                                            problem->mu, rho, F, psi, Jcsc,
                                            tmp2, &alpha, 100);


    cs_spfree(Jcsc);
    if(!info_ls)
    {
      cblas_daxpy(ACProblemSize, alpha, rhs, 1, solution, 1);
    }
    else
    {
      cblas_daxpy(ACProblemSize, 1, rhs, 1., solution, 1);
    }

    for(unsigned int e = 0 ; e < globalProblemSize; ++e)
    {
      globalVelocity[e] = solution[e];
    }

    for(unsigned int e = 0 ; e < localProblemSize; ++e)
    {
      velocity[e] = solution[e+globalProblemSize];
    }

    for(unsigned int e = 0; e < localProblemSize; ++e)
    {
      reaction[e] = solution[e+globalProblemSize+localProblemSize];
    }

    options->dparam[1] = INFINITY;

    if(!(iter % erritermax))
    {

      gfc3d_compute_error(problem,
                          reaction, velocity, globalVelocity,
                          tolerance,
                          &(options->dparam[1]));
    }

    if(verbose > 0)
      printf("------------------------ GFC3D - NSN_AC - iteration %d, residual = %g, linear solver residual = %g, tolerance = %g \n", iter, options->dparam[1],linear_solver_residual, tolerance);

    if(options->dparam[1] < tolerance)
    {
      info[0] = 0;
      break;
    }


  }