-----------------------------------------------------------------------------
| 147 | } |
| 148 | //----------------------------------------------------------------------------- |
| 149 | std::pair<int, bool> nls::petsc::NewtonSolver::solve(Vec x) |
| 150 | { |
| 151 | // Reset iteration counts |
| 152 | _iteration = 0; |
| 153 | _krylov_iterations = 0; |
| 154 | _residual = -1; |
| 155 | _residual0 = 0; |
| 156 | |
| 157 | if (!_fnF) |
| 158 | { |
| 159 | throw std::runtime_error("Function for computing residual vector has not " |
| 160 | "been provided to the NewtonSolver."); |
| 161 | } |
| 162 | |
| 163 | if (!_fnJ) |
| 164 | { |
| 165 | throw std::runtime_error("Function for computing Jacobian has not " |
| 166 | "been provided to the NewtonSolver."); |
| 167 | } |
| 168 | |
| 169 | if (_system) |
| 170 | _system(x); |
| 171 | assert(_b); |
| 172 | _fnF(x, _b); |
| 173 | |
| 174 | // Check convergence |
| 175 | bool newton_converged = false; |
| 176 | if (convergence_criterion == "residual") |
| 177 | std::tie(_residual, newton_converged) = this->_converged(*this, _b); |
| 178 | else if (convergence_criterion == "incremental") |
| 179 | { |
| 180 | // We need to do at least one Newton step with the ||dx||-stopping |
| 181 | // criterion |
| 182 | newton_converged = false; |
| 183 | } |
| 184 | else |
| 185 | { |
| 186 | throw std::runtime_error("Unknown convergence criterion: " |
| 187 | + convergence_criterion); |
| 188 | } |
| 189 | |
| 190 | // FIXME: check that this is efficient if A and/or P are unchanged |
| 191 | // Set operators |
| 192 | if (_matP) |
| 193 | _solver.set_operators(_matJ, _matP); |
| 194 | else |
| 195 | _solver.set_operators(_matJ, _matJ); |
| 196 | |
| 197 | if (!_dx) |
| 198 | MatCreateVecs(_matJ, &_dx, nullptr); |
| 199 | |
| 200 | // Start iterations |
| 201 | while (!newton_converged and _iteration < max_it) |
| 202 | { |
| 203 | // Compute Jacobian |
| 204 | assert(_matJ); |
| 205 | _fnJ(x, _matJ); |
| 206 |
nothing calls this directly
no test coverage detected