|
| 1 | + |
| 2 | +static char help[] = "Modified snes tutorial 1\n\n"; |
| 3 | + |
| 4 | +#include <petscsnes.h> |
| 5 | + |
| 6 | +extern PetscErrorCode FormJacobian1(SNES, Vec, Mat, Mat, void *); |
| 7 | +extern PetscErrorCode FormFunction1(SNES, Vec, Vec, void *); |
| 8 | + |
| 9 | +int main(int argc, char **argv) |
| 10 | +{ |
| 11 | + SNES snes; |
| 12 | + KSP ksp; |
| 13 | + PC pc; |
| 14 | + Vec x, r; |
| 15 | + Mat J; |
| 16 | + PetscMPIInt size; |
| 17 | + PetscBool flg; |
| 18 | + PetscFunctionBeginUser; |
| 19 | + |
| 20 | + PetscCall(PetscInitialize(&argc, &argv, NULL, help)); |
| 21 | + PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); |
| 22 | + |
| 23 | + PetscCall(PetscOptionsSetValue(NULL, "-poisson_ksp_type", "cg")); |
| 24 | + PetscCall(PetscOptionsInsert(NULL, &argc, &argv, NULL)); |
| 25 | + |
| 26 | + PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes)); |
| 27 | + PetscCall(SNESSetOptionsPrefix(snes, "poisson_")); |
| 28 | + PetscCall(SNESSetFromOptions(snes)); |
| 29 | + |
| 30 | + PetscCall(VecCreate(PETSC_COMM_WORLD, &x)); |
| 31 | + PetscCall(VecSetSizes(x, PETSC_DECIDE, 2)); |
| 32 | + PetscCall(VecSetFromOptions(x)); |
| 33 | + PetscCall(VecDuplicate(x, &r)); |
| 34 | + |
| 35 | + PetscCall(MatCreate(PETSC_COMM_WORLD, &J)); |
| 36 | + PetscCall(MatSetSizes(J, PETSC_DECIDE, PETSC_DECIDE, 2, 2)); |
| 37 | + PetscCall(MatSetFromOptions(J)); |
| 38 | + PetscCall(MatSetUp(J)); |
| 39 | + |
| 40 | + PetscCall(SNESSetFunction(snes, r, FormFunction1, NULL)); |
| 41 | + PetscCall(SNESSetJacobian(snes, J, J, FormJacobian1, NULL)); |
| 42 | + |
| 43 | + PetscCall(SNESGetKSP(snes, &ksp)); |
| 44 | + PetscCall(KSPGetPC(ksp, &pc)); |
| 45 | + PetscCall(PCSetType(pc, PCNONE)); |
| 46 | + PetscCall(KSPSetTolerances(ksp, 1.e-4, PETSC_CURRENT, PETSC_CURRENT, 20)); |
| 47 | + |
| 48 | + |
| 49 | +// PetscCall(VecSet(x, pfive)); |
| 50 | + PetscCall(SNESSolve(snes, NULL, x)); |
| 51 | + |
| 52 | + PetscCall(VecDestroy(&x)); |
| 53 | + PetscCall(VecDestroy(&r)); |
| 54 | + PetscCall(MatDestroy(&J)); |
| 55 | + PetscCall(SNESDestroy(&snes)); |
| 56 | + PetscCall(PetscFinalize()); |
| 57 | + return 0; |
| 58 | +} |
| 59 | + |
| 60 | +PetscErrorCode FormFunction1(SNES snes, Vec x, Vec f, void *ctx) |
| 61 | +{ |
| 62 | + const PetscScalar *xx; |
| 63 | + PetscScalar *ff; |
| 64 | + |
| 65 | + PetscFunctionBeginUser; |
| 66 | + |
| 67 | + PetscCall(VecGetArrayRead(x, &xx)); |
| 68 | + PetscCall(VecGetArray(f, &ff)); |
| 69 | + |
| 70 | + /* Compute function */ |
| 71 | + ff[0] = xx[0] * xx[0] + xx[0] * xx[1] - 3.0; |
| 72 | + ff[1] = xx[0] * xx[1] + xx[1] * xx[1] - 6.0; |
| 73 | + |
| 74 | + /* Restore vectors */ |
| 75 | + PetscCall(VecRestoreArrayRead(x, &xx)); |
| 76 | + PetscCall(VecRestoreArray(f, &ff)); |
| 77 | + PetscFunctionReturn(PETSC_SUCCESS); |
| 78 | +} |
| 79 | + |
| 80 | +PetscErrorCode FormJacobian1(SNES snes, Vec x, Mat jac, Mat B, void *dummy) |
| 81 | +{ |
| 82 | + const PetscScalar *xx; |
| 83 | + PetscScalar A[4]; |
| 84 | + PetscInt idx[2] = {0, 1}; |
| 85 | + |
| 86 | + PetscFunctionBeginUser; |
| 87 | + |
| 88 | + PetscCall(VecGetArrayRead(x, &xx)); |
| 89 | + |
| 90 | + A[0] = 2.0 * xx[0] + xx[1]; |
| 91 | + A[1] = xx[0]; |
| 92 | + A[2] = xx[1]; |
| 93 | + A[3] = xx[0] + 2.0 * xx[1]; |
| 94 | + PetscCall(MatSetValues(B, 2, idx, 2, idx, A, INSERT_VALUES)); |
| 95 | + |
| 96 | + PetscCall(VecRestoreArrayRead(x, &xx)); |
| 97 | + |
| 98 | + PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); |
| 99 | + PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); |
| 100 | + if (jac != B) { |
| 101 | + PetscCall(MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY)); |
| 102 | + PetscCall(MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY)); |
| 103 | + } |
| 104 | + PetscFunctionReturn(PETSC_SUCCESS); |
| 105 | +} |
0 commit comments