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; }
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; }
NumericsSparseMatrix* NM_sparse(NumericsMatrix* A) { if(!A->matrix2) { A->matrix2 = newNumericsSparseMatrix(); } return A->matrix2; }
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); } } }
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; }
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; }
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; } }