// Solve with no rock compressibility (linear eqn). void IncompTpfa::solveIncomp(const double dt, SimulatorState& state, WellState& well_state) { // Set up properties. computePerSolveDynamicData(dt, state, well_state); // Assemble. UnstructuredGrid* gg = const_cast<UnstructuredGrid*>(&grid_); int ok = ifs_tpfa_assemble(gg, &forces_, &trans_[0], &gpress_omegaweighted_[0], h_); if (!ok) { OPM_THROW(std::runtime_error, "Failed assembling pressure system."); } // Solve. linsolver_.solve(h_->A, h_->b, h_->x); // Obtain solution. assert(int(state.pressure().size()) == grid_.number_of_cells); assert(int(state.faceflux().size()) == grid_.number_of_faces); ifs_tpfa_solution soln = { NULL, NULL, NULL, NULL }; soln.cell_press = &state.pressure()[0]; soln.face_flux = &state.faceflux()[0]; if (wells_ != NULL) { assert(int(well_state.bhp().size()) == wells_->number_of_wells); assert(int(well_state.perfRates().size()) == wells_->well_connpos[ wells_->number_of_wells ]); soln.well_flux = &well_state.perfRates()[0]; soln.well_press = &well_state.bhp()[0]; } ifs_tpfa_press_flux(gg, &forces_, &trans_[0], h_, &soln); }
/// Solve pressure equation, by Newton iterations. void CompressibleTpfa::solve(const double dt, BlackoilState& state, WellState& well_state) { const int nc = grid_.number_of_cells; const int nw = (wells_ != 0) ? wells_->number_of_wells : 0; // Set up dynamic data. computePerSolveDynamicData(dt, state, well_state); computePerIterationDynamicData(dt, state, well_state); // Assemble J and F. assemble(dt, state, well_state); double inc_norm = 0.0; int iter = 0; double res_norm = residualNorm(); std::cout << "\nIteration Residual Change in p\n" << std::setw(9) << iter << std::setw(18) << res_norm << std::setw(18) << '*' << std::endl; while ((iter < maxiter_) && (res_norm > residual_tol_)) { // Solve for increment in Newton method: // incr = x_{n+1} - x_{n} = -J^{-1}F // (J is Jacobian matrix, F is residual) solveIncrement(); ++iter; // Update pressure vars with increment. for (int c = 0; c < nc; ++c) { state.pressure()[c] += pressure_increment_[c]; } for (int w = 0; w < nw; ++w) { well_state.bhp()[w] += pressure_increment_[nc + w]; } // Stop iterating if increment is small. inc_norm = incrementNorm(); if (inc_norm <= change_tol_) { std::cout << std::setw(9) << iter << std::setw(18) << '*' << std::setw(18) << inc_norm << std::endl; break; } // Set up dynamic data. computePerIterationDynamicData(dt, state, well_state); // Assemble J and F. assemble(dt, state, well_state); // Update residual norm. res_norm = residualNorm(); std::cout << std::setw(9) << iter << std::setw(18) << res_norm << std::setw(18) << inc_norm << std::endl; } if ((iter == maxiter_) && (res_norm > residual_tol_) && (inc_norm > change_tol_)) { OPM_THROW(std::runtime_error, "CompressibleTpfa::solve() failed to converge in " << maxiter_ << " iterations."); } std::cout << "Solved pressure in " << iter << " iterations." << std::endl; // Compute fluxes and face pressures. computeResults(state, well_state); }