/*! solve A*X=Y using dgbsv\n The argument is dgematrix Y. Y is overwritten and become the solution X. A is also overwritten. */ inline long dgbmatrix::dgbsv(dgematrix& mat) {VERBOSE_REPORT; #ifdef CPPL_DEBUG if(m!=n || n!=mat.m){ ERROR_REPORT; std::cerr << "These matrix and vector cannot be solved." << std::endl << "Your input was (" << m << "x" << n << ") and (" << mat.m << "x" << mat.n << ")." << std::endl; exit(1); } #endif//CPPL_DEBUG dgbmatrix newmat(m,n,kl,ku+kl); for(long i=0; i<m; i++){ for(long j=std::max(long(0),i-kl); j<std::min(n,i+ku+1); j++){ newmat(i,j) =operator()(i,j); }} long NRHS(mat.n), LDAB(2*kl+ku+1), *IPIV(new long[n]), LDB(mat.m), INFO(1); dgbsv_(n, kl, ku, NRHS, newmat.array, LDAB, IPIV, mat.array, LDB, INFO); delete [] IPIV; swap(*this,newmat); if(INFO!=0){ WARNING_REPORT; std::cerr << "Serious trouble happend. INFO = " << INFO << "." << std::endl; } return INFO; }
void GravityColumnSolverPolymer<FluxModel, Model>::solveSingleColumn(const std::vector<int>& column_cells, const double dt, std::vector<double>& s, std::vector<double>& c, std::vector<double>& cmax, std::vector<double>& sol_vec) { // This is written only to work with SinglePointUpwindTwoPhase, // not with arbitrary problem models. int col_size = column_cells.size(); // if (col_size == 1) { // sol_vec[2*column_cells[0] + 0] = 0.0; // sol_vec[2*column_cells[0] + 1] = 0.0; // return; // } StateWithZeroFlux state(s, c, cmax); // This holds s by reference. // Assemble. const int kl = 3; const int ku = 3; const int nrow = 2*kl + ku + 1; const int N = 2*col_size; // N unknowns: s and c for each cell. std::vector<double> hm(nrow*N, 0.0); // band matrix with 3 upper and 3 lower diagonals. std::vector<double> rhs(N, 0.0); const BandMatrixCoeff bmc(N, ku, kl); for (int ci = 0; ci < col_size; ++ci) { std::vector<double> F(2, 0.); std::vector<double> dFd1(4, 0.); std::vector<double> dFd2(4, 0.); std::vector<double> dF(4, 0.); const int cell = column_cells[ci]; const int prev_cell = (ci == 0) ? -999 : column_cells[ci - 1]; const int next_cell = (ci == col_size - 1) ? -999 : column_cells[ci + 1]; // model_.initResidual(cell, F); for (int j = grid_.cell_facepos[cell]; j < grid_.cell_facepos[cell+1]; ++j) { const int face = grid_.cell_faces[j]; const int c1 = grid_.face_cells[2*face + 0]; const int c2 = grid_.face_cells[2*face + 1]; if (c1 == prev_cell || c2 == prev_cell || c1 == next_cell || c2 == next_cell) { F.assign(2, 0.); dFd1.assign(4, 0.); dFd2.assign(4, 0.); fmodel_.fluxConnection(state, grid_, dt, cell, face, &F[0], &dFd1[0], &dFd2[0]); if (c1 == prev_cell || c2 == prev_cell) { hm[bmc(2*ci + 0, 2*(ci - 1) + 0)] += dFd2[0]; hm[bmc(2*ci + 0, 2*(ci - 1) + 1)] += dFd2[1]; hm[bmc(2*ci + 1, 2*(ci - 1) + 0)] += dFd2[2]; hm[bmc(2*ci + 1, 2*(ci - 1) + 1)] += dFd2[3]; } else { ASSERT(c1 == next_cell || c2 == next_cell); hm[bmc(2*ci + 0, 2*(ci + 1) + 0)] += dFd2[0]; hm[bmc(2*ci + 0, 2*(ci + 1) + 1)] += dFd2[1]; hm[bmc(2*ci + 1, 2*(ci + 1) + 0)] += dFd2[2]; hm[bmc(2*ci + 1, 2*(ci + 1) + 1)] += dFd2[3]; } hm[bmc(2*ci + 0, 2*ci + 0)] += dFd1[0]; hm[bmc(2*ci + 0, 2*ci + 1)] += dFd1[1]; hm[bmc(2*ci + 1, 2*ci + 0)] += dFd1[2]; hm[bmc(2*ci + 1, 2*ci + 1)] += dFd1[3]; rhs[2*ci + 0] += F[0]; rhs[2*ci + 1] += F[1]; } } F.assign(2, 0.); dF.assign(4, 0.); fmodel_.accumulation(grid_, cell, &F[0], &dF[0]); hm[bmc(2*ci + 0, 2*ci + 0)] += dF[0]; hm[bmc(2*ci + 0, 2*ci + 1)] += dF[1]; hm[bmc(2*ci + 1, 2*ci + 0)] += dF[2]; if (std::abs(dF[3]) < 1e-12) { hm[bmc(2*ci + 1, 2*ci + 1)] += 1e-12; } else { hm[bmc(2*ci + 1, 2*ci + 1)] += dF[3]; } rhs[2*ci + 0] += F[0]; rhs[2*ci + 1] += F[1]; } // model_.sourceTerms(); // Not needed // Solve. const int num_rhs = 1; int info = 0; std::vector<int> ipiv(N, 0); // Solution will be written to rhs. dgbsv_(&N, &kl, &ku, &num_rhs, &hm[0], &nrow, &ipiv[0], &rhs[0], &N, &info); if (info != 0) { std::cerr << "Failed column cells: "; std::copy(column_cells.begin(), column_cells.end(), std::ostream_iterator<int>(std::cerr, " ")); std::cerr << "\n"; THROW("Lapack reported error in dgtsv: " << info); } for (int ci = 0; ci < col_size; ++ci) { sol_vec[2*column_cells[ci] + 0] = -rhs[2*ci + 0]; sol_vec[2*column_cells[ci] + 1] = -rhs[2*ci + 1]; } }
int BandGenLinLapackSolver::solve(void) { if (theSOE == 0) { opserr << "WARNING BandGenLinLapackSolver::solve(void)- "; opserr << " No LinearSOE object has been set\n"; return -1; } int n = theSOE->size; // check iPiv is large enough if (iPivSize < n) { opserr << "WARNING BandGenLinLapackSolver::solve(void)- "; opserr << " iPiv not large enough - has setSize() been called?\n"; return -1; } int kl = theSOE->numSubD; int ku = theSOE->numSuperD; int ldA = 2*kl + ku +1; int nrhs = 1; int ldB = n; int info; double *Aptr = theSOE->A; double *Xptr = theSOE->X; double *Bptr = theSOE->B; int *iPIV = iPiv; // first copy B into X for (int i=0; i<n; i++) { *(Xptr++) = *(Bptr++); } Xptr = theSOE->X; // now solve AX = B #ifdef _WIN32 {if (theSOE->factored == false) // factor and solve DGBSV(&n,&kl,&ku,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info); else { // solve only using factored matrix unsigned int sizeC = 1; //DGBTRS("N", &sizeC, &n,&kl,&ku,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info); DGBTRS("N", &n,&kl,&ku,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info); }} #else {if (theSOE->factored == false) // factor and solve dgbsv_(&n,&kl,&ku,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info); else // solve only using factored matrix dgbtrs_("N",&n,&kl,&ku,&nrhs,Aptr,&ldA,iPIV,Xptr,&ldB,&info); } #endif // check if successfull if (info != 0) { opserr << "WARNING BandGenLinLapackSolver::solve() -"; opserr << "LAPACK routine returned " << info << endln; return -info; } theSOE->factored = true; return 0; }