00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00036 #include "SimplePetscNonlinearSolver.hpp"
00037 #include "Exception.hpp"
00038 #include "petscsnes.h"
00039 #include "PetscTools.hpp"
00040 #include <sstream>
00041
00042
00072 Vec SimplePetscNonlinearSolver::Solve(PetscErrorCode (*pComputeResidual)(SNES,Vec,Vec,void*),
00073 PetscErrorCode (*pComputeJacobian)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),
00074 Vec initialGuess,
00075 void *pContext)
00076 {
00077 SNES snes;
00078
00079
00080 Vec residual;
00081 VecDuplicate(initialGuess, &residual);
00082
00083 Mat jacobian;
00084
00085 PetscInt N;
00086
00087 VecGetSize(initialGuess,&N);
00088
00089 PetscTools::SetupMat(jacobian, N, N);
00090
00091 SNESCreate(PETSC_COMM_WORLD, &snes);
00092 SNESSetFunction(snes, residual, pComputeResidual, pContext);
00093 SNESSetJacobian(snes, jacobian, jacobian, pComputeJacobian, pContext);
00094 SNESSetType(snes,SNESLS);
00095 SNESSetTolerances(snes,1.0e-5,1.0e-5,1.0e-5,PETSC_DEFAULT,PETSC_DEFAULT);
00096
00097
00098 Vec x;
00099 VecDuplicate(initialGuess, &x);
00100 VecCopy(initialGuess, x);
00101
00102
00103 #if (PETSC_VERSION_MINOR == 2) //Old API
00104 SNESSolve(snes, x);
00105 #else
00106 SNESSolve(snes, PETSC_NULL, x);
00107 #endif
00108
00109 VecDestroy(residual);
00110 MatDestroy(jacobian);
00111
00112 SNESConvergedReason reason;
00113 SNESGetConvergedReason(snes,&reason);
00114 #define COVERAGE_IGNORE
00115 if (reason<0)
00116 {
00117 std::stringstream reason_stream;
00118 reason_stream << reason;
00119 VecDestroy(x);
00120 SNESDestroy(snes);
00121 EXCEPTION("Nonlinear Solver did not converge. Petsc reason code:"
00122 +reason_stream.str()+" .");
00123 }
00124 #undef COVERAGE_IGNORE
00125 SNESDestroy(snes);
00126
00127 return x;
00128 }