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
00043
00044 Vec SimplePetscNonlinearSolver::Solve(PetscErrorCode (*pComputeResidual)(SNES,Vec,Vec,void*),
00045 PetscErrorCode (*pComputeJacobian)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),
00046 Vec initialGuess,
00047 unsigned fill,
00048 void* pContext)
00049 {
00050 SNES snes;
00051
00052
00053 Vec residual;
00054 VecDuplicate(initialGuess, &residual);
00055
00056 Mat jacobian;
00057
00058 PetscInt N;
00059
00060 VecGetSize(initialGuess,&N);
00061
00062 PetscTools::SetupMat(jacobian, N, N, fill);
00063
00064 SNESCreate(PETSC_COMM_WORLD, &snes);
00065 SNESSetFunction(snes, residual, pComputeResidual, pContext);
00066 SNESSetJacobian(snes, jacobian, jacobian, pComputeJacobian, pContext);
00067 SNESSetType(snes,SNESLS);
00068 SNESSetTolerances(snes,1.0e-5,1.0e-5,1.0e-5,PETSC_DEFAULT,PETSC_DEFAULT);
00069
00070
00071 Vec x;
00072 VecDuplicate(initialGuess, &x);
00073 VecCopy(initialGuess, x);
00074
00075
00076 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00077 SNESSolve(snes, x);
00078 #else
00079 SNESSolve(snes, PETSC_NULL, x);
00080 #endif
00081
00082 VecDestroy(residual);
00083 MatDestroy(jacobian);
00084
00085 SNESConvergedReason reason;
00086 SNESGetConvergedReason(snes,&reason);
00087 #define COVERAGE_IGNORE
00088 if (reason<0)
00089 {
00090 std::stringstream reason_stream;
00091 reason_stream << reason;
00092 VecDestroy(x);
00093 SNESDestroy(snes);
00094 EXCEPTION("Nonlinear Solver did not converge. Petsc reason code:"
00095 +reason_stream.str()+" .");
00096 }
00097 #undef COVERAGE_IGNORE
00098 SNESDestroy(snes);
00099
00100 return x;
00101 }