bool SolveNormalEquation(const taucs_ccs_matrix * A, const taucsType * b, taucsType * x) { taucs_ccs_matrix * ATmat = MatrixTranspose(A); if (! ATmat) { return false; } taucs_ccs_matrix * ATAmat = Mul2NonSymmMatSymmResult(ATmat,A); taucsType * rhs = new taucsType[A->n]; MulNonSymmMatrixVector(ATmat, b, rhs); // solve the system int rc = taucs_linsolve(ATAmat, NULL, 1, x, rhs, SIVANfactor, SIVANopt_arg); taucs_ccs_free(ATmat); taucs_ccs_free(ATAmat); delete[] rhs; if (rc != TAUCS_SUCCESS) { return false; } else { return true; } }
//---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpCholeskyTaucs & ClpCholeskyTaucs::operator=(const ClpCholeskyTaucs& rhs) { if (this != &rhs) { ClpCholeskyBase::operator=(rhs); taucs_ccs_free(matrix_); if (factorization_) taucs_supernodal_factor_free(factorization_); factorization_ = NULL; sizeFactorT_ = rhs.sizeFactorT_; matrix_ = rhs.matrix_; if (matrix_) { choleskyStartT_ = (int *) malloc((numberRows_ + 1) * sizeof(int)); CoinMemcpyN(rhs.choleskyStartT_, (numberRows_ + 1), choleskyStartT_); choleskyRowT_ = (int *) malloc(sizeFactorT_ * sizeof(int)); CoinMemcpyN(rhs.choleskyRowT_, sizeFactorT_, choleskyRowT_); sparseFactorT_ = (double *) malloc(sizeFactorT_ * sizeof(double)); CoinMemcpyN(rhs.sparseFactorT_, sizeFactorT_, sparseFactorT_); matrix_->colptr = choleskyStartT_; matrix_->rowind = choleskyRowT_; matrix_->values.d = sparseFactorT_; } else { sparseFactorT_ = NULL; choleskyStartT_ = NULL; choleskyRowT_ = NULL; } delete rowCopyT_; rowCopyT_ = rhs.rowCopyT_->clone(); } return *this; }
//------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpCholeskyTaucs::~ClpCholeskyTaucs () { taucs_ccs_free(matrix_); if (factorization_) taucs_supernodal_factor_free(factorization_); delete rowCopyT_; }
DllExport void FreeSymbolicSolver(void *sp) { struct SymbolicSolver_tag * s = (struct SymbolicSolver_tag *) sp; if (s == NULL) return; if (s->matrix) taucs_ccs_free(s->matrix); if (s->factorization) taucs_supernodal_factor_free(s->factorization); if (s->perm) free(s->perm); if (s->invperm) free(s->invperm); if (s->tmp_b) free (s->tmp_b); if (s->tmp_x) free (s->tmp_x); s->matrix = s->factorization = NULL; s->perm = s->invperm = NULL; s->tmp_b = s->tmp_x = NULL; }
DllExport int FreeCGSolver(void * sp) { struct CGSolver_tag * s = (struct CGSolver_tag *)sp; int rc = 0; if (sp == NULL) { return 0; } if (s->matrix != NULL) { taucs_ccs_free(s->matrix); s->matrix = NULL; } return rc; }
// Will create the actual numerical factorization of the given ATA matrix // provided the symbolic factor with id factorId bool FactorATA_UseSymbolic(const int matrixID, const int symbFactorId) { if (matrixID >= (int)matrixArray.size() || symbFactorId >= (int)factorArray.size() || matrixID < 0 || symbFactorId < 0) return false; if (factorArray[symbFactorId].hasNumericalValues) { taucs_supernodal_factor_free_numeric(factorArray[symbFactorId].SL); } factorArray[symbFactorId].hasNumericalValues = true; taucs_ccs_free(factorArray[symbFactorId].PAP); return matrixArray[matrixID]->FactorATA_UseSymbolic(factorArray[symbFactorId].SL, &factorArray[symbFactorId].PAP, factorArray[symbFactorId].perm, factorArray[symbFactorId].invperm); }
DllExport int NumericFactor( struct SymbolicSolver_tag *sp, int n, int nnz, int *rowIndex, int *colIndex, double *value ) { int ret = -1; struct SymbolicSolver_tag * s = (struct SymbolicSolver_tag *) sp; taucs_ccs_matrix * m = taucs_ccs_create(n, n, nnz, TAUCS_DOUBLE|TAUCS_LOWER|TAUCS_SYMMETRIC); if (m == NULL) return -1; // copy elements to matrix memcpy(m->rowind, rowIndex, sizeof(int) * nnz); memcpy(m->values.d, value, sizeof(double) * nnz); memcpy(m->colptr, colIndex, sizeof(int) * (n+1)); m = taucs_ccs_permute_symmetrically(m, s->perm, s->invperm); ret = taucs_ccs_factor_llt_numeric(m, s->factorization); taucs_ccs_free(m); return ret; }
DllExport int FreeSolver( struct Solver_tag * sp ) { struct Solver_tag * s = (struct Solver_tag *)sp; int rc = 0; if (sp == NULL) { return 0; } if (s->matrix != NULL) { taucs_ccs_free(s->matrix); s->matrix = NULL; } if (s->factorization != NULL) { rc = taucs_linsolve(NULL, &s->factorization, 0, NULL, NULL, NULL, NULL); s->factorization = NULL; } return rc; }
int main(int argc, char* argv[]) { double start; int rc; int i,j; taucs_ccs_matrix* A = NULL; void* X; void* B; void* Y; void* Z; void* opt_arg[] = { NULL }; double opt_nrhs = 1.0; char* opt_ijv = NULL; char* opt_ijv_zero = NULL; char* opt_hb = NULL; char* opt_bin = NULL; char* opt_log = "stdout"; double opt_3d = -1.0; double opt_2d = -1.0; char* opt_2d_type = "dirichlet"; int opt_3d_rand = 0;/*not random*/ double opt_3d_small = -1.0;/*regular*/ double opt_shift = 0.0; int opt_sreal = 0; int opt_dreal = 0; int opt_scomplex = 0; int opt_dcomplex = 0; int datatype = TAUCS_DOUBLE; int opt_all1rhs = 0; double rerr; for (i=0; argv[i]; i++) { int understood = FALSE; understood |= taucs_getopt_boolean(argv[i],opt_arg,"taucs_run.sreal",&opt_sreal); understood |= taucs_getopt_boolean(argv[i],opt_arg,"taucs_run.dreal",&opt_dreal); understood |= taucs_getopt_boolean(argv[i],opt_arg,"taucs_run.scomplex",&opt_scomplex); understood |= taucs_getopt_boolean(argv[i],opt_arg,"taucs_run.dcomplex",&opt_dcomplex); understood |= taucs_getopt_string(argv[i],opt_arg,"taucs_run.ijv",&opt_ijv); understood |= taucs_getopt_string(argv[i],opt_arg,"taucs_run.ijvz",&opt_ijv_zero); understood |= taucs_getopt_string(argv[i],opt_arg,"taucs_run.hb", &opt_hb ); understood |= taucs_getopt_string(argv[i],opt_arg,"taucs_run.bin", &opt_bin ); understood |= taucs_getopt_string(argv[i],opt_arg,"taucs_run.log",&opt_log); understood |= taucs_getopt_double(argv[i],opt_arg,"taucs_run.mesh3d",&opt_3d); understood |= taucs_getopt_boolean(argv[i],opt_arg,"taucs_run.mesh3d.rand",&opt_3d_rand); understood |= taucs_getopt_double(argv[i],opt_arg,"taucs_run.mesh3d.small",&opt_3d_small); understood |= taucs_getopt_double(argv[i],opt_arg,"taucs_run.mesh2d",&opt_2d); understood |= taucs_getopt_string(argv[i],opt_arg,"taucs_run.mesh2d.type",&opt_2d_type); understood |= taucs_getopt_double(argv[i],opt_arg,"taucs_run.shift",&opt_shift); understood |= taucs_getopt_double(argv[i],opt_arg,"taucs_run.nrhs",&opt_nrhs); understood |= taucs_getopt_string(argv[i],opt_arg,"taucs_run.params",&gl_parameters); understood |= taucs_getopt_boolean(argv[i],opt_arg,"taucs_run.all1rhs",&opt_all1rhs); if (!understood) taucs_printf("taucs_run: illegal option [%s]\n", argv[i]); } if (opt_sreal ) datatype = TAUCS_SINGLE; if (opt_dreal ) datatype = TAUCS_DOUBLE; if (opt_scomplex) datatype = TAUCS_SCOMPLEX; if (opt_dcomplex) datatype = TAUCS_DCOMPLEX; taucs_logfile(opt_log); if (opt_3d > 0) { if ( opt_3d_small > 0 ) { A = taucs_ccs_generate_mesh3d_random((int)opt_3d_small,(int)opt_3d,(int)opt_3d,opt_3d_rand); } A = taucs_ccs_generate_mesh3d_random((int)opt_3d,(int)opt_3d,(int)opt_3d,opt_3d_rand); if (!A) { taucs_printf("Matrix generation failed\n"); return 1; } datatype = TAUCS_DOUBLE; } if (opt_2d > 0) { A = taucs_ccs_generate_mesh2d((int)opt_2d,opt_2d_type); if (!A) { taucs_printf("Matrix generation failed\n"); return 1; } datatype = TAUCS_DOUBLE; } if (opt_ijv) { switch (datatype) { case TAUCS_SINGLE: A = taucs_ccs_read_ijv (opt_ijv,TAUCS_SYMMETRIC | TAUCS_SINGLE); break; break; case TAUCS_DOUBLE: A = taucs_ccs_read_ijv (opt_ijv,TAUCS_SYMMETRIC | TAUCS_DOUBLE); break; break; case TAUCS_SCOMPLEX: A = taucs_ccs_read_ijv (opt_ijv,TAUCS_HERMITIAN | TAUCS_SCOMPLEX); break; break; case TAUCS_DCOMPLEX: A = taucs_ccs_read_ijv (opt_ijv,TAUCS_HERMITIAN | TAUCS_DCOMPLEX); break; break; default: taucs_printf("taucs_run: incorrect datatype\n"); return 1; break; } } if (opt_ijv_zero) { switch (datatype) { case TAUCS_SINGLE: A = taucs_ccs_read_ijv_zero_based (opt_ijv_zero,TAUCS_SYMMETRIC | TAUCS_SINGLE); break; break; case TAUCS_DOUBLE: A = taucs_ccs_read_ijv_zero_based (opt_ijv_zero,TAUCS_SYMMETRIC | TAUCS_DOUBLE); break; break; case TAUCS_SCOMPLEX: A = taucs_ccs_read_ijv_zero_based(opt_ijv_zero,TAUCS_HERMITIAN | TAUCS_SCOMPLEX); break; break; case TAUCS_DCOMPLEX: A = taucs_ccs_read_ijv_zero_based(opt_ijv_zero,TAUCS_HERMITIAN | TAUCS_DCOMPLEX); break; break; default: taucs_printf("taucs_run: incorrect datatype\n"); return 1; break; } } if (opt_hb) { switch (datatype) { case TAUCS_SINGLE: A = taucs_ccs_read_hb (opt_hb, TAUCS_SINGLE); break; break; case TAUCS_DOUBLE: A = taucs_ccs_read_hb (opt_hb, TAUCS_DOUBLE); break; break; case TAUCS_SCOMPLEX: A = taucs_ccs_read_hb (opt_hb, TAUCS_SCOMPLEX); break; break; case TAUCS_DCOMPLEX: A = taucs_ccs_read_hb (opt_hb, TAUCS_DCOMPLEX); break; break; default: taucs_printf("taucs_run: incorrect datatype\n"); return 1; break; } datatype = A->flags; } if (opt_bin) { A = taucs_ccs_read_binary(opt_bin); } if (!A) { taucs_printf("taucs_run: there is no matrix!\n"); return 1; } if (opt_shift) { int i,j; int ip; if (datatype & TAUCS_DOUBLE) { for (j=0; j<A->n; j++) { int found = 0; for (ip = (A->colptr)[j]; ip < (A->colptr)[j+1]; ip++) { i = (A->rowind)[ip]; if (i == j) { (A->values.d)[ip] += opt_shift; found = 1; break; } } if (!found) { taucs_printf("taucs_run: the matrix is missing a diagonal element so I can't shift\n"); return 1; } } } else { taucs_printf("taucs_run: shift only works on double-precision matrices\n"); return 1; } } taucs_printf("taucs_run: matrix dimentions %d by %d with %d nonzeros\n", A->m, A->n, (A->colptr)[ A->n ]); X = taucs_vec_create((A->n)*(int)opt_nrhs,A->flags); B = taucs_vec_create((A->m)*(int)opt_nrhs,A->flags); Y = taucs_vec_create((A->n)*(int)opt_nrhs,A->flags); Z = taucs_vec_create((A->m)*(int)opt_nrhs,A->flags); if (!X || !B || !Y || !Z) { taucs_printf("taucs_run: vector allocation failed\n"); return 1; } if (!opt_all1rhs) { for(j=0;j<(int)opt_nrhs;j++) { for(i=0; i<A->n; i++) { #ifdef TAUCS_SINGLE_IN_BUILD if (datatype & TAUCS_SINGLE) ((taucs_single*)X)[i+j*(A->n)]=(taucs_single) ((double)rand()/(double)RAND_MAX); #endif #ifdef TAUCS_DOUBLE_IN_BUILD if (datatype & TAUCS_DOUBLE) //((taucs_double*)X)[i+j*(A->n)]=(taucs_double) ((double)rand()/(double)RAND_MAX); ((taucs_double*)X)[i+j*(A->n)]=0.1 + i * 0.01; #endif #ifdef TAUCS_SCOMPLEX_IN_BUILD if (datatype & TAUCS_SCOMPLEX) { taucs_single cre,cim; cre = (taucs_single) ((double)rand()/(double)RAND_MAX); cim = (taucs_single) ((double)rand()/(double)RAND_MAX); ((taucs_scomplex*)X)[i+j*(A->n)] = taucs_ccomplex_create(cre,cim); } #endif #ifdef TAUCS_DCOMPLEX_IN_BUILD if (datatype & TAUCS_DCOMPLEX) { taucs_single zre,zim; zre = (taucs_double) ((double)rand()/(double)RAND_MAX); zim = (taucs_double) ((double)rand()/(double)RAND_MAX); ((taucs_dcomplex*)X)[i+j*(A->n)] = taucs_zcomplex_create(zre,zim); } #endif } } taucs_ccs_times_vec_many(A,X,B,(int)opt_nrhs); } else { for(j=0;j<(int)opt_nrhs;j++) { for(i=0; i<A->m; i++) { #ifdef TAUCS_SINGLE_IN_BUILD if (datatype & TAUCS_SINGLE) ((taucs_single*)B)[i+j*(A->m)]= 1.0; #endif #ifdef TAUCS_DOUBLE_IN_BUILD if (datatype & TAUCS_DOUBLE) ((taucs_double*)B)[i+j*(A->m)]= 1.0; #endif #ifdef TAUCS_SCOMPLEX_IN_BUILD if (datatype & TAUCS_SCOMPLEX) { taucs_single cre,cim; cre = 1.0; cim = 0.0; ((taucs_scomplex*)B)[i+j*(A->m)] = taucs_ccomplex_create(cre,cim); } #endif #ifdef TAUCS_DCOMPLEX_IN_BUILD if (datatype & TAUCS_DCOMPLEX) { taucs_single zre,zim; zre = 1.0; zim = 0.0; ((taucs_dcomplex*)B)[i+j*(A->m)] = taucs_zcomplex_create(zre,zim); } #endif } } } start = taucs_wtime(); rc = taucs_linsolve(A,NULL,(int)opt_nrhs,Y,B,argv,opt_arg); taucs_printf("total solve time is %.2e sec\n", taucs_wtime() - start); if (!opt_all1rhs && opt_nrhs == 1) { taucs_vec_axpby_many(A->n,A->flags,1.0,X,-1.0,Y,Z,(int)opt_nrhs); rerr = taucs_vec_norm2(A->n, A->flags,Z) / taucs_vec_norm2(A->n, A->flags, X); taucs_printf("relative 2-norm of error is %.2e\n", rerr); } rnorm_many(A,Y,B,Z,(int)opt_nrhs); if (opt_nrhs == 1) { double xnorm = taucs_vec_norm2(A->n,A->flags,Y); taucs_printf("2-norm of x is %.2e\n", xnorm); } // Silencing valgrind if (X) taucs_vec_free(A->flags,X); if (B) taucs_vec_free(A->flags,B); if (Y) taucs_vec_free(A->flags,Y); if (Z) taucs_vec_free(A->flags,Z); taucs_ccs_free(A); return 0; }
/* Factorize - filling in rowsDropped and returning number dropped */ int ClpCholeskyTaucs::factorize(const double * diagonal, int * rowsDropped) { const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const double * element = model_->clpMatrix()->getElements(); const CoinBigIndex * rowStart = rowCopyT_->getVectorStarts(); const int * rowLength = rowCopyT_->getVectorLengths(); const int * column = rowCopyT_->getIndices(); const double * elementByRow = rowCopyT_->getElements(); int numberColumns = model_->clpMatrix()->getNumCols(); int iRow; double * work = new double[numberRows_]; CoinZeroN(work, numberRows_); const double * diagonalSlack = diagonal + numberColumns; int newDropped = 0; double largest; //perturbation double perturbation = model_->diagonalPerturbation() * model_->diagonalNorm(); perturbation = perturbation * perturbation; if (perturbation > 1.0) { //if (model_->model()->logLevel()&4) std::cout << "large perturbation " << perturbation << std::endl; perturbation = sqrt(perturbation); perturbation = 1.0; } for (iRow = 0; iRow < numberRows_; iRow++) { double * put = sparseFactorT_ + choleskyStartT_[iRow]; int * which = choleskyRowT_ + choleskyStartT_[iRow]; int number = choleskyStartT_[iRow+1] - choleskyStartT_[iRow]; if (!rowLength[iRow]) rowsDropped_[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; work[iRow] = diagonalSlack[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; double multiplier = diagonal[iColumn] * elementByRow[k]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { double value = element[j] * multiplier; work[jRow] += value; } } } int j; for (j = 0; j < number; j++) { int jRow = which[j]; put[j] = work[jRow]; work[jRow] = 0.0; } } else { // dropped int j; for (j = 1; j < number; j++) { put[j] = 0.0; } put[0] = 1.0; } } //check sizes double largest2 = maximumAbsElement(sparseFactorT_, sizeFactorT_); largest2 *= 1.0e-19; largest = CoinMin(largest2, 1.0e-11); int numberDroppedBefore = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int dropped = rowsDropped_[iRow]; // Move to int array rowsDropped[iRow] = dropped; if (!dropped) { CoinBigIndex start = choleskyStartT_[iRow]; double diagonal = sparseFactorT_[start]; if (diagonal > largest2) { sparseFactorT_[start] = diagonal + perturbation; } else { sparseFactorT_[start] = diagonal + perturbation; rowsDropped[iRow] = 2; numberDroppedBefore++; } } } taucs_supernodal_factor_free_numeric(factorization_); // need to permute taucs_ccs_matrix * permuted = taucs_ccs_permute_symmetrically(matrix_, permuteInverse_, permute_); int rCode = taucs_ccs_factor_llt_numeric(permuted, factorization_); taucs_ccs_free(permuted); if (rCode) printf("return code of %d from factor\n", rCode); delete [] work; choleskyCondition_ = 1.0; bool cleanCholesky; if (model_->numberIterations() < 200) cleanCholesky = true; else cleanCholesky = false; /* How do I find out where 1.0e100's are in cholesky? */ if (cleanCholesky) { //drop fresh makes some formADAT easier int oldDropped = numberRowsDropped_; if (newDropped || numberRowsDropped_) { std::cout << "Rank " << numberRows_ - newDropped << " ( " << newDropped << " dropped)"; if (newDropped > oldDropped) std::cout << " ( " << newDropped - oldDropped << " dropped this time)"; std::cout << std::endl; newDropped = 0; for (int i = 0; i < numberRows_; i++) { char dropped = rowsDropped[i]; rowsDropped_[i] = dropped; if (dropped == 2) { //dropped this time rowsDropped[newDropped++] = i; rowsDropped_[i] = 0; } } numberRowsDropped_ = newDropped; newDropped = -(1 + newDropped); } } else { if (newDropped) { newDropped = 0; for (int i = 0; i < numberRows_; i++) { char dropped = rowsDropped[i]; int oldDropped = rowsDropped_[i]; rowsDropped_[i] = dropped; if (dropped == 2) { assert (!oldDropped); //dropped this time rowsDropped[newDropped++] = i; rowsDropped_[i] = 1; } } } numberRowsDropped_ += newDropped; if (numberRowsDropped_) { std::cout << "Rank " << numberRows_ - numberRowsDropped_ << " ( " << numberRowsDropped_ << " dropped)"; if (newDropped) { std::cout << " ( " << newDropped << " dropped this time)"; } std::cout << std::endl; } } status_ = 0; return newDropped; }
/* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyTaucs::order(ClpInterior * model) { numberRows_ = model->numberRows(); rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); numberRowsDropped_ = 0; model_ = model; rowCopyT_ = model->clpMatrix()->reverseOrderedCopy(); const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const CoinBigIndex * rowStart = rowCopyT_->getVectorStarts(); const int * rowLength = rowCopyT_->getVectorLengths(); const int * column = rowCopyT_->getIndices(); // We need two arrays for counts int * which = new int [numberRows_]; int * used = new int[numberRows_]; CoinZeroN(used, numberRows_); int iRow; sizeFactorT_ = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactorT_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; } } delete [] which; // Now we have size - create arrays and fill in matrix_ = taucs_ccs_create(numberRows_, numberRows_, sizeFactorT_, TAUCS_DOUBLE | TAUCS_SYMMETRIC | TAUCS_LOWER); if (!matrix_) return 1; // Space for starts choleskyStartT_ = matrix_->colptr; choleskyRowT_ = matrix_->rowind; sparseFactorT_ = matrix_->values.d; sizeFactorT_ = 0; which = choleskyRowT_; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; choleskyStartT_[iRow] = sizeFactorT_; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactorT_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; // Sort std::sort(which, which + number); // move which on which += number; } } choleskyStartT_[numberRows_] = sizeFactorT_; delete [] used; permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; int * perm, *invp; // There seem to be bugs in ordering if model too small if (numberRows_ > 10) taucs_ccs_order(matrix_, &perm, &invp, (const char *) "genmmd"); else taucs_ccs_order(matrix_, &perm, &invp, (const char *) "identity"); CoinMemcpyN(perm, numberRows_, permuteInverse_); free(perm); CoinMemcpyN(invp, numberRows_, permute_); free(invp); // need to permute taucs_ccs_matrix * permuted = taucs_ccs_permute_symmetrically(matrix_, permuteInverse_, permute_); // symbolic factorization_ = taucs_ccs_factor_llt_symbolic(permuted); taucs_ccs_free(permuted); return factorization_ ? 0 : 1; }
int sci_taucs_chfact(char* fname, void* pvApiCtx) { SciErr sciErr; int stat = 0; int* perm = NULL; int* invperm = NULL; taucs_ccs_matrix *PAPT; taucs_ccs_matrix B; void *C = NULL; taucs_handle_factors *pC; SciSparse A; int mA = 0; // rows int nA = 0; // cols int iNbItem = 0; int* piNbItemRow = NULL; int* piColPos = NULL; double* pdblSpReal = NULL; double* pdblSpImg = NULL; int iComplex = 0; int* piAddr1 = NULL; /* Check numbers of input/output arguments */ CheckInputArgument(pvApiCtx, 1, 1); CheckOutputArgument(pvApiCtx, 1, 1); /* get A the sparse matrix to factorize */ sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr1); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } if (isVarComplex(pvApiCtx, piAddr1)) { iComplex = 1; sciErr = getComplexSparseMatrix(pvApiCtx, piAddr1, &mA, &nA, &iNbItem, &piNbItemRow, &piColPos, &pdblSpReal, &pdblSpImg); } else { sciErr = getSparseMatrix(pvApiCtx, piAddr1, &mA, &nA, &iNbItem, &piNbItemRow, &piColPos, &pdblSpReal); } if (sciErr.iErr) { printError(&sciErr, 0); return 1; } // fill struct sparse A.m = mA; A.n = nA; A.it = iComplex; A.nel = iNbItem; A.mnel = piNbItemRow; A.icol = piColPos; A.R = pdblSpReal; A.I = pdblSpImg; stat = spd_sci_sparse_to_taucs_sparse(&A, &B); if ( stat != A_PRIORI_OK ) { if ( stat == MAT_IS_NOT_SPD ) { freeTaucsSparse(B); Scierror(999, _("%s: Wrong value for input argument #%d: Must be symmetric positive definite matrix."), fname, 1); } /* the message for the other problem (not enough memory in stk) is treated automaticaly */ return 1; } /* find the permutation */ taucs_ccs_genmmd(&B, &perm, &invperm); if ( !perm ) { freeTaucsSparse(B); Scierror(999, _("%s: No more memory.\n") , fname); return 1; } /* apply permutation */ PAPT = taucs_ccs_permute_symmetrically(&B, perm, invperm); FREE(invperm); freeTaucsSparse(B); /* factor */ C = taucs_ccs_factor_llt_mf(PAPT); taucs_ccs_free(PAPT); if (C == NULL) { /* Note : an error indicator is given in the main scilab window * (out of memory, no positive definite matrix , etc ...) */ Scierror(999, _("%s: An error occurred: %s\n"), fname, _("factorization")); return 1; } /* put in an handle (Chol fact + perm + size) */ pC = (taucs_handle_factors*)MALLOC( sizeof(taucs_handle_factors) ); pC->p = perm; pC->C = C; pC->n = A.n; /* add in the list of Chol Factors */ AddAdrToList((Adr) pC, 0, &ListCholFactors); /* FIXME add a test here .. */ /* create the scilab object to store the pointer onto the Chol handle */ sciErr = createPointer(pvApiCtx, 2, (void *)pC); if (sciErr.iErr) { printError(&sciErr, 0); return 1; } /* return the pointer */ AssignOutputVariable(pvApiCtx, 1) = 2; ReturnArguments(pvApiCtx); return 0; }
//计算每个cell的缩放的大小(主要是计算cellScale[][]的值) void Resizer::computeCellScale(float _S[3]) { //计算每个cell的Phi值 computeCellPhi(); //计算每个cell的W[][3]和scaleEstimation[][3]值 computeCellW(); computeCellScaleEstimation(_S); //先定义临时变量存放每个cell的9个变量 double **temp = new double *[(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)]; for(int i=0;i<(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1);i++) temp[i] = new double[9]; //对temp[][]赋初值为0.0 for(int i=0;i<(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1);i++) for(int j=0;j<9;j++) temp[i][j] = 0.0; //对temp[][]重新计算 for(int k=0;k<CELLNUM;k++) { for(int j=0;j<CELLNUM;j++) { for(int i=0;i<CELLNUM;i++) { int cellIndex = computeCellIndex1(i,j,k); temp[cellIndex][0] += cellPhi[k][j][i]*cellPhi[k][j+1][i]+cellPhi[k][j][i]*cellPhi[k+1][j][i]; //ScX的平方 temp[cellIndex][1] += cellPhi[k][j][i]*cellPhi[k][j][i+1]+cellPhi[k][j][i]*cellPhi[k+1][j][i]; //ScY的平方 temp[cellIndex][2] += cellPhi[k][j][i]*cellPhi[k][j][i+1]+cellPhi[k][j][i]*cellPhi[k][j+1][i]; //ScZ的平方 temp[cellIndex][3] += -cellPhi[k][j][i]*cellPhi[k][j+1][i]; //ScX*Sd2X temp[cellIndex][4] += -cellPhi[k][j][i]*cellPhi[k+1][j][i]; //ScX*Sd3X temp[cellIndex][5] += -cellPhi[k][j][i]*cellPhi[k][j][i+1]; //ScY*Sd1Y temp[cellIndex][6] += -cellPhi[k][j][i]*cellPhi[k+1][j][i]; //ScY*Sd3Y temp[cellIndex][7] += -cellPhi[k][j][i]*cellPhi[k][j][i+1]; //ScZ*Sd1Z temp[cellIndex][8] += -cellPhi[k][j][i]*cellPhi[k][j+1][i]; //ScZ*Sd2Z //对Sd1所在的位置加上两项 cellIndex = computeCellIndex1(i+1,j,k); temp[cellIndex][1] += cellPhi[k][j][i]*cellPhi[k][j][i+1]; temp[cellIndex][2] += cellPhi[k][j][i]*cellPhi[k][j][i+1]; //对Sd2所在的位置加上两项 cellIndex = computeCellIndex1(i,j+1,k); temp[cellIndex][0] += cellPhi[k][j][i]*cellPhi[k][j+1][i]; temp[cellIndex][2] += cellPhi[k][j][i]*cellPhi[k][j+1][i]; //对Sd3所在的位置加上两项 cellIndex = computeCellIndex1(i,j,k+1); temp[cellIndex][0] += cellPhi[k][j][i]*cellPhi[k+1][j][i]; temp[cellIndex][1] += cellPhi[k][j][i]*cellPhi[k+1][j][i]; } } } //首先定义整个矩阵(注意在grid的右侧、上侧、前侧各加了一层,主要是为了方便计算) int m = 3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+3*CELLLAYER; //矩阵的行数 int n = 3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+3*CELLLAYER; //矩阵的列数 //矩阵中非0元的个数(注意计算过程:整个矩阵的0---3*ALLCELLNUM-1行,每行有最多8个非0元素;3*ALLCELLNUM---ALLCELLNUM+CELLLAYER*3-1行,每行有CELLNUM个非0元素) //注意要考虑对角线的元素 int nnz = 6*ALLCELLNUM+5*ALLCELLNUM+4*ALLCELLNUM; //稀疏矩阵中非0元素的个数 //存放整个矩阵的变量 taucs_ccs_matrix *pMatrix; //为pMatrix申请空间 pMatrix = taucs_ccs_create(m,n,nnz,TAUCS_DOUBLE); //设置pMatrix的一些属性(对称和下三角) pMatrix->flags += TAUCS_SYMMETRIC; pMatrix->flags += TAUCS_LOWER; int num1=0; //计数器,主要是为记录colptr[]位置下标 int num2=0; //计数器,主要是为记录rowind[]和values.d[]位置下标 int count=0; //主要是为记录colptr[]存放的值 //下面开始存放矩阵(注意:调用taucs库稀疏矩阵必须按列进行存储) //首先考虑X方向 for(int k=0;k<CELLNUM+1;k++) //高 { for(int j=0;j<CELLNUM+1;j++) //列 { for(int i=0;i<CELLNUM+1;i++) //行 { if(i==CELLNUM||j==CELLNUM||k==CELLNUM) //壳上的点 { //此时该行的元素都为0 pMatrix->colptr[num1] = count; num1++; } else //不是壳上的点 { //colptr[]存储每一列开始元素对应的下标 //rowind[]存储每个元素在相应的列中的下标 //value.d[]存储每个元素的元素值,注意要与rowind[]相对应 pMatrix->colptr[num1] = count; num1++; int cellIndex1 = computeCellIndex(i,j,k); //此下标用于取W和scaleEstimation的值 int cellIndex2 = computeCellIndex1(i,j,k); //此下标用于取temp的值 pMatrix->rowind[num2] = computeCellIndex1(i,j,k); pMatrix->values.d[num2] = 2.0*(W[cellIndex1][0]+W[cellIndex1][2])/(scaleEstimation[cellIndex1][0]*scaleEstimation[cellIndex1][0])+(4.0/3.0)*2.0*temp[cellIndex2][0]; num2++; pMatrix->rowind[num2] = computeCellIndex1(i,j+1,k); pMatrix->values.d[num2] = (4.0/3.0)*2.0*temp[cellIndex2][3]; num2++; pMatrix->rowind[num2] = computeCellIndex1(i,j,k+1); pMatrix->values.d[num2] = (4.0/3.0)*2.0*temp[cellIndex2][4]; num2++; pMatrix->rowind[num2] = (CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+computeCellIndex1(i,j,k); pMatrix->values.d[num2] = -2.0*W[cellIndex1][0]/(scaleEstimation[cellIndex1][0]*scaleEstimation[cellIndex1][1]); num2++; pMatrix->rowind[num2] = 2*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+computeCellIndex1(i,j,k); pMatrix->values.d[num2] = -2.0*W[cellIndex1][2]/(scaleEstimation[cellIndex1][0]*scaleEstimation[cellIndex1][2]); num2++; pMatrix->rowind[num2] = 3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+k*CELLNUM+j; pMatrix->values.d[num2] = 1.0; num2++; count = count+6; } } } } //处理Y方向(num1,num2和count应该接上面的值) for(int k=0;k<CELLNUM+1;k++) //高 { for(int j=0;j<CELLNUM+1;j++) //列 { for(int i=0;i<CELLNUM+1;i++) //行 { if(i==CELLNUM||j==CELLNUM||k==CELLNUM) //壳上的点 { //此时该行的元素都为0 pMatrix->colptr[num1] = count; num1++; } else //不是壳上的点 { //colptr[]存储每一列开始元素对应的下标 //rowind[]存储每个元素在相应的列中的下标 //value.d[]存储每个元素的元素值,注意要与rowind[]相对应 pMatrix->colptr[num1] = count; num1++; int cellIndex1 = computeCellIndex(i,j,k); //i,j,k对应的不带壳的grid中cell的下标 int cellIndex2 = computeCellIndex1(i,j,k); pMatrix->rowind[num2] = (CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+computeCellIndex1(i,j,k); pMatrix->values.d[num2] = 2.0*(W[cellIndex1][0]+W[cellIndex1][1])/(scaleEstimation[cellIndex1][1]*scaleEstimation[cellIndex1][1])+(4.0/3.0)*2.0*temp[cellIndex2][1]; num2++; pMatrix->rowind[num2] = (CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+computeCellIndex1(i+1,j,k); pMatrix->values.d[num2] = (4.0/3.0)*2.0*temp[cellIndex2][5]; num2++; pMatrix->rowind[num2] = (CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+computeCellIndex1(i,j,k+1); pMatrix->values.d[num2] = (4.0/3.0)*2.0*temp[cellIndex2][6]; num2++; pMatrix->rowind[num2] = 2*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+computeCellIndex1(i,j,k); pMatrix->values.d[num2] = -2.0*W[cellIndex1][1]/(scaleEstimation[cellIndex1][1]*scaleEstimation[cellIndex1][2]); num2++; pMatrix->rowind[num2] = 3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+CELLLAYER+k*CELLNUM+i; pMatrix->values.d[num2] = 1.0; num2++; count = count+5; } } } } //处理Z方向(num1,num2和count应该接上面的值) for(int k=0;k<CELLNUM+1;k++) //高 { for(int j=0;j<CELLNUM+1;j++) //列 { for(int i=0;i<CELLNUM+1;i++) //行 { if(i==CELLNUM||j==CELLNUM||k==CELLNUM) //壳上的点 { //此时该行的元素都为0 pMatrix->colptr[num1] = count; num1++; } else //不是壳上的点 { //colptr[]存储每一列开始元素对应的下标 //rowind[]存储每个元素在相应的列中的下标 //value.d[]存储每个元素的元素值,注意要与rowind[]相对应 pMatrix->colptr[num1] = count; num1++; int cellIndex1 = computeCellIndex(i,j,k); //i,j,k对应的不带壳的grid中cell的下标 int cellIndex2 = computeCellIndex1(i,j,k); pMatrix->rowind[num2] = 2*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+computeCellIndex1(i,j,k); pMatrix->values.d[num2] = 2.0*(W[cellIndex1][1]+W[cellIndex1][2])/(scaleEstimation[cellIndex1][2]*scaleEstimation[cellIndex1][2])+(4.0/3.0)*2.0*temp[cellIndex2][2]; num2++; pMatrix->rowind[num2] = 2*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+computeCellIndex1(i+1,j,k); pMatrix->values.d[num2] = (4.0/3.0)*2.0*temp[cellIndex2][7]; num2++; pMatrix->rowind[num2] = 2*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+computeCellIndex1(i,j+1,k); pMatrix->values.d[num2] = (4.0/3.0)*2.0*temp[cellIndex2][8]; num2++; pMatrix->rowind[num2] = 3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+2*CELLLAYER+j*CELLNUM+i; pMatrix->values.d[num2] = 1.0; num2++; count = count+4; } } } } //注意:pMatrix->colptr[]共有n+1个元素,即使为0,也应存储 for(int i=num1;i<=n;i++) //此处n应能取到 pMatrix->colptr[i] = count; taucs_double *x = new taucs_double[3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+3*CELLLAYER]; //存放运算得到的未知数结果 //对矩阵x赋初值(加快收敛速度) for(int k=0;k<CELLNUM+1;k++) //高 { for(int j=0;j<CELLNUM+1;j++) //列 { for(int i=0;i<CELLNUM+1;i++) //行 { if(i==CELLNUM||j==CELLNUM||k==CELLNUM) //壳上的点,其对应的x[i]值赋值为0 { int index = computeCellIndex1(i,j,k); x[index] = 0.0; } else //不是壳上的点 { int index = computeCellIndex1(i,j,k); x[index] = _S[0]; x[(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+index] = _S[1]; x[2*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+index] = _S[2]; } } } } //其余x[]值赋值为0 for(int i=3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1);i<3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+3*CELLLAYER;i++) x[i] = 0.0; taucs_double *b = new taucs_double[3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+3*CELLLAYER]; //存放右边的列矩阵 //对矩阵b赋值 for(int i=0;i<3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1);i++) b[i] = 0.0; for(int i=3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1);i<3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+CELLLAYER;i++) b[i] = CELLNUM*_S[0]; for(int i=3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+CELLLAYER;i<3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+2*CELLLAYER;i++) b[i] = CELLNUM*_S[1]; for(int i=3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+2*CELLLAYER;i<3*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+3*CELLLAYER;i++) b[i] = CELLNUM*_S[2]; //调用函数解决问题 //注意:原论文其实是要计算预处理矩阵,主要是为了早点收敛 //我没有计算基于两点:1)时间紧迫,计算预处理矩阵又得花不少时间 2)直接计算收敛速度也很快的 int result = taucs_minres(pMatrix,NULL,NULL,x,b,1000,1e-4); //判断结果 if (result != TAUCS_SUCCESS) { printf ("Solution error.\n"); if (result==TAUCS_ERROR) printf ("Generic error."); if (result==TAUCS_ERROR_NOMEM) printf ("NOMEM error."); if (result==TAUCS_ERROR_BADARGS) printf ("BADARGS error."); if (result==TAUCS_ERROR_MAXDEPTH) printf ("MAXDEPTH error."); if (result==TAUCS_ERROR_INDEFINITE) printf ("NOT POSITIVE DEFINITE error."); } else { printf ("Solution success.\n"); //为cellScale[][3]申请空间 cellScale = new double *[ALLCELLNUM]; for(int i=0;i<ALLCELLNUM;i++) cellScale[i] = new double[3]; //正确求得解,将其赋值给cellScale[][3] for(int k=0;k<CELLNUM+1;k++) //高 { for(int j=0;j<CELLNUM+1;j++) //列 { for(int i=0;i<CELLNUM+1;i++) //行 { if(i==CELLNUM||j==CELLNUM||k==CELLNUM) //壳上的点,其对应的x[i]值是不需要的 { } else //不是壳上的点 { int cellIndex1 = computeCellIndex(i,j,k); //i,j,k对应的不带壳的grid中cell的下标 int cellIndex2 = computeCellIndex1(i,j,k); //i,j,k对应的带壳的grid中cell的下标 cellScale[cellIndex1][0] = x[cellIndex2]; cellScale[cellIndex1][1] = x[(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+cellIndex2]; cellScale[cellIndex1][2] = x[2*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)+cellIndex2]; } } } } } taucs_ccs_free(pMatrix); //此处可以释放W[][]和scaleEstimation[][]的资源了 for(int i=0;i<ALLCELLNUM;i++) { delete[] W[i]; } delete[] W; for(int i=0;i<ALLCELLNUM;i++) { delete[] scaleEstimation[i]; } delete[] scaleEstimation; printf("W和scaleEstimation释放资源没问题.\n"); //释放x[]和b[]的资源 delete[] x; delete[] b; printf("x和b释放资源没问题.\n"); }
//这个函数功能比较难 void Resizer::computeNewCellVertex() { double ***temp1 = new double **[3]; for(int i=0;i<3;i++) temp1[i] = new double *[(CELLNUM+2)*(CELLNUM+2)*(CELLNUM+2)]; for(int i=0;i<3;i++) for(int j=0;j<(CELLNUM+2)*(CELLNUM+2)*(CELLNUM+2);j++) temp1[i][j] = new double[4]; double **temp2 = new double *[3]; for(int i=0;i<3;i++) temp2[i] = new double[(CELLNUM+2)*(CELLNUM+2)*(CELLNUM+2)]; //为变量newCellVertex[][]申请空间 newCellVertex = new double *[(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1)]; for(int i=0;i<(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1);i++) newCellVertex[i] = new double[3]; //初始化所有元素为0 for(int i=0;i<3;i++) { for(int j=0;j<(CELLNUM+2)*(CELLNUM+2)*(CELLNUM+2);j++) { temp2[i][j] = 0.0; for(int k=0;k<4;k++) temp1[i][j][k] = 0.0; } } //对每个cell进行遍历,每次考虑8个顶点 for(int p=0;p<3;p++) { for(int k=0;k<CELLNUM;k++) //高 { for(int j=0;j<CELLNUM;j++) //列 { for(int i=0;i<CELLNUM;i++) //行 { int cellIndex = computeCellIndex(i,j,k); //(CELLNUM) //当前cell沿X方向的脆弱性 double tempVulnerability = cellVulnerability[cellIndex][p]; //当前cell的的Phi值 double tempPhi = cellPhi[k][j][i]; //当前cell的X方向的缩放大小 double tempScale = cellScale[cellIndex][p]; //当前cell的X方向缩放后的棱长 double t = tempScale*edgeLength[p]; //对于每个cell进行处理 //对第0个顶点 cellIndex = computeCellIndex2(i,j,k); temp1[p][cellIndex][0] += 2.0*tempPhi+tempVulnerability; temp1[p][cellIndex][1] += -tempVulnerability; temp1[p][cellIndex][2] += -tempPhi; temp1[p][cellIndex][3] += -tempPhi; temp2[p][cellIndex] += -2.0*tempVulnerability*t; //对第1个顶点 cellIndex = computeCellIndex2(i+1,j,k); temp1[p][cellIndex][0] += 2.0*tempPhi+tempVulnerability; temp1[p][cellIndex][2] += -tempPhi; temp1[p][cellIndex][3] += -tempPhi; temp2[p][cellIndex] += 2.0*tempVulnerability*t; //对第2个顶点 cellIndex = computeCellIndex2(i,j+1,k); temp1[p][cellIndex][0] += 2.0*tempPhi+tempVulnerability; temp1[p][cellIndex][1] += -tempVulnerability; temp1[p][cellIndex][3] += -tempPhi; temp2[p][cellIndex] += -2.0*tempVulnerability*t; //对第3个顶点 cellIndex = computeCellIndex2(i+1,j+1,k); temp1[p][cellIndex][0] += 2.0*tempPhi+tempVulnerability; temp1[p][cellIndex][3] += -tempPhi; temp2[p][cellIndex] += 2.0*tempVulnerability*t; //对第4个顶点 cellIndex = computeCellIndex2(i,j,k+1); temp1[p][cellIndex][0] += 2.0*tempPhi+tempVulnerability; temp1[p][cellIndex][1] += -tempVulnerability; temp1[p][cellIndex][2] += -tempPhi; temp2[p][cellIndex] += -2.0*tempVulnerability*t; //对第5个顶点 cellIndex = computeCellIndex2(i+1,j,k+1); temp1[p][cellIndex][0] += 2.0*tempPhi+tempVulnerability; temp1[p][cellIndex][2] += -tempPhi; temp2[p][cellIndex] += 2.0*tempVulnerability*t; //对第6个顶点 cellIndex = computeCellIndex2(i,j+1,k+1); temp1[p][cellIndex][0] += 2.0*tempPhi+tempVulnerability; temp1[p][cellIndex][1] += -tempVulnerability; temp2[p][cellIndex] += -2.0*tempVulnerability*t; //对第7个顶点 cellIndex = computeCellIndex2(i+1,j+1,k+1); temp1[p][cellIndex][0] += 2.0*tempPhi+tempVulnerability; temp2[p][cellIndex] += 2.0*tempVulnerability*t; } } } } //首先定义整个稀疏对称矩阵 int m = (CELLNUM+2)*(CELLNUM+2)*(CELLNUM+2); //矩阵的行数 int n = (CELLNUM+2)*(CELLNUM+2)*(CELLNUM+2); //矩阵的列数 //稀疏矩阵中所有的非0元素的总个数 int nnz = 4*(CELLNUM+1)*(CELLNUM+1)*(CELLNUM+1); //存放整个矩阵的变量 taucs_ccs_matrix *pMatrix[3]; //为pMatrix[]申请空间 for(int i=0;i<3;i++) pMatrix[i] = taucs_ccs_create(m,n,nnz,TAUCS_DOUBLE); //设置pMatrix的一些属性(对称和下三角) for(int i=0;i<3;i++) { pMatrix[i]->flags += TAUCS_SYMMETRIC; pMatrix[i]->flags += TAUCS_LOWER; } //X,Y,Z方向综合考虑 for(int p=0;p<3;p++) { int num=0; //计数器,主要是为记录rowind[]和values.d[]位置下标 int count=0; //主要是为记录colptr[]存放的值 for(int k=0;k<(CELLNUM+2);k++) //高 { for(int j=0;j<(CELLNUM+2);j++) //列 { for(int i=0;i<(CELLNUM+2);i++) //行 { if(i==CELLNUM+1||j==CELLNUM+1||k==CELLNUM+1) { int cellIndex = computeCellIndex2(i,j,k); pMatrix[p]->colptr[cellIndex] = count; } else { int cellIndex = computeCellIndex2(i,j,k); pMatrix[p]->colptr[cellIndex] = count; pMatrix[p]->rowind[num] = cellIndex; pMatrix[p]->values.d[num] = 2.0*temp1[p][cellIndex][0]; num++; pMatrix[p]->rowind[num] = computeCellIndex2(i+1,j,k); pMatrix[p]->values.d[num] = 2.0*temp1[p][cellIndex][1]; num++; pMatrix[p]->rowind[num] = computeCellIndex2(i,j+1,k); pMatrix[p]->values.d[num] = 2.0*temp1[p][cellIndex][2]; num++; pMatrix[p]->rowind[num] = computeCellIndex2(i,j,k+1); pMatrix[p]->values.d[num] = 2.0*temp1[p][cellIndex][3]; num++; count = count+4; } } } } pMatrix[p]->colptr[(CELLNUM+2)*(CELLNUM+2)*(CELLNUM+2)] = count; } taucs_double **x = new taucs_double *[3]; //存放运算得到的未知数结果 for(int i=0;i<3;i++) x[i] = new taucs_double[(CELLNUM+2)*(CELLNUM+2)*(CELLNUM+2)]; //对矩阵x[]进行赋值(以便快速收敛) for(int p=0;p<3;p++) { for(int k=0;k<(CELLNUM+2);k++) //高 { for(int j=0;j<(CELLNUM+2);j++) //列 { for(int i=0;i<(CELLNUM+2);i++) //行 { if(i>CELLNUM||j>CELLNUM||k>CELLNUM) { int cellIndex = computeCellIndex2(i,j,k); x[p][cellIndex] = 0.0; } else { if(p==0) { int cellIndex = computeCellIndex2(i,j,k); x[p][cellIndex] = oldCellVertex[computeCellIndex1(i,j,k)][p]; } else if(p==1) { int cellIndex = computeCellIndex2(j,i,k); //此处注意 x[p][cellIndex] = oldCellVertex[computeCellIndex1(i,j,k)][p]; } else //p==2 { int cellIndex = computeCellIndex2(k,i,j); //此处注意 x[p][cellIndex] = oldCellVertex[computeCellIndex1(i,j,k)][p]; } } } } } } taucs_double **b = new taucs_double *[3]; //存放右边的列矩阵 for(int i=0;i<3;i++) b[i] = new taucs_double[(CELLNUM+2)*(CELLNUM+2)*(CELLNUM+2)]; //对矩阵b[]进行赋值 for(int i=0;i<3;i++) { for(int j=0;j<(CELLNUM+2)*(CELLNUM+2)*(CELLNUM+2);j++) { b[i][j] = temp2[i][j]; } } //先对X方向调用函数解决问题 for(int p=0;p<3;p++) { int result = taucs_minres(pMatrix[p],NULL,NULL,x[p],b[p],1000,0.0001); //判断结果 if (result != TAUCS_SUCCESS) { printf ("Solution error.\n"); if (result==TAUCS_ERROR) printf ("Generic error."); if (result==TAUCS_ERROR_NOMEM) printf ("NOMEM error."); if (result==TAUCS_ERROR_BADARGS) printf ("BADARGS error."); if (result==TAUCS_ERROR_MAXDEPTH) printf ("MAXDEPTH error."); if (result==TAUCS_ERROR_INDEFINITE) printf ("NOT POSITIVE DEFINITE error."); } else { printf ("Solution success.\n"); //正确求得解,将其赋值给newCellVertex[][] for(int k=0;k<(CELLNUM+2);k++) //高 { for(int j=0;j<(CELLNUM+2);j++) //列 { for(int i=0;i<(CELLNUM+2);i++) //行 { if(i>CELLNUM||j>CELLNUM||k>CELLNUM) { //这不是我们要的 } else { if(p==0) { int cellIndex = computeCellIndex2(i,j,k); newCellVertex[computeCellIndex1(i,j,k)][p] = x[p][cellIndex]; } else if(p==1) { int cellIndex = computeCellIndex2(j,i,k); //此处注意 newCellVertex[computeCellIndex1(i,j,k)][p] = x[p][cellIndex]; } else //p==2 { int cellIndex = computeCellIndex2(k,i,j); //此处注意 newCellVertex[computeCellIndex1(i,j,k)][p] = x[p][cellIndex]; } } } } } } } for(int i=0;i<200;i++) { printf("(%f,%f,%f)<---->(%f,%f,%f)\n",oldCellVertex[i][0],oldCellVertex[i][1],oldCellVertex[i][2],newCellVertex[i][0],newCellVertex[i][1],newCellVertex[i][2]); } //释放资源 //释放temp1[][][] for(int i=0;i<3;i++) { for(int j=0;j<(CELLNUM+2)*(CELLNUM+2)*(CELLNUM+2);j++) { delete[] temp1[i][j]; } } for(int i=0;i<3;i++) { delete[] temp1[i]; } delete[] temp1; printf("temp1释放资源没问题.\n"); //释放temp2[][] for(int i=0;i<3;i++) { delete[] temp2[i]; } delete[] temp2; printf("temp2释放资源没问题.\n"); //释放x[][] for(int i=0;i<3;i++) { delete[] x[i]; } delete[] x; printf("x释放资源没问题.\n"); //释放b[][] for(int i=0;i<3;i++) { delete[] b[i]; } delete[] b; printf("b释放资源没问题.\n"); for(int i=0;i<3;i++) taucs_ccs_free(pMatrix[i]); printf("pMatrix释放资源没问题.\n"); }
taucs_ccs_matrix *taucs_dtl(ccs_permute_symmetrically) (taucs_ccs_matrix * A, int *perm, int *invperm) { taucs_ccs_matrix *PAPT; int n; int nnz; /* * int* colptr; */ int *len; int i, j, ip, I, J; taucs_datatype AIJ; assert(A->flags & TAUCS_SYMMETRIC || A->flags & TAUCS_HERMITIAN); assert(A->flags & TAUCS_LOWER); n = A->n; nnz = (A->colptr)[n]; PAPT = taucs_dtl(ccs_create) (n, n, nnz); if (!PAPT) return NULL; /* * PAPT->flags = TAUCS_SYMMETRIC | TAUCS_LOWER; */ PAPT->flags = A->flags; len = (int *) taucs_malloc(n * sizeof(int)); /* * colptr = (int*) taucs_malloc(n * sizeof(int)); */ if (!len) { taucs_printf("taucs_ccs_permute_symmetrically: out of memory\n"); taucs_ccs_free(PAPT); return NULL; } for (j = 0; j < n; j++) len[j] = 0; for (j = 0; j < n; j++) { for (ip = (A->colptr)[j]; ip < (A->colptr)[j + 1]; ip++) { /* * i = (A->rowind)[ip] - (A->indshift); */ i = (A->rowind)[ip]; I = invperm[i]; J = invperm[j]; if (I < J) { int T = I; I = J; J = T; } len[J]++; } } (PAPT->colptr)[0] = 0; for (j = 1; j <= n; j++) (PAPT->colptr)[j] = (PAPT->colptr)[j - 1] + len[j - 1]; for (j = 0; j < n; j++) len[j] = (PAPT->colptr)[j]; for (j = 0; j < n; j++) { for (ip = (A->colptr)[j]; ip < (A->colptr)[j + 1]; ip++) { /* * i = (A->rowind)[ip] - (A->indshift); */ i = (A->rowind)[ip]; AIJ = (A->taucs_values)[ip]; I = invperm[i]; J = invperm[j]; if (I < J) { int T = I; I = J; J = T; if (A->flags & TAUCS_HERMITIAN) AIJ = taucs_conj(AIJ); } /* * (PAPT->rowind)[ len[J] ] = I + (PAPT->indshift); */ (PAPT->rowind)[len[J]] = I; (PAPT->taucs_values)[len[J]] = AIJ; len[J]++; } } taucs_free(len); return PAPT; }
void Clear() { if (PAP) { taucs_ccs_free(PAP); PAP = 0; } if (SL) { taucs_supernodal_factor_free(SL); SL = 0; } if (perm) { free(perm); perm = 0; } if (invperm) { free(invperm); invperm = 0; } }