1 #include <private/snesimpl.h> /*I "petscsnes.h" I*/ 2 3 typedef struct { 4 PetscInt sweeps; 5 PetscBool norms; 6 } SNES_GS; 7 8 #undef __FUNCT__ 9 #define __FUNCT__ "SNESReset_GS" 10 PetscErrorCode SNESReset_GS(SNES snes) 11 { 12 PetscFunctionBegin; 13 PetscFunctionReturn(0); 14 } 15 16 #undef __FUNCT__ 17 #define __FUNCT__ "SNESDestroy_GS" 18 PetscErrorCode SNESDestroy_GS(SNES snes) 19 { 20 PetscErrorCode ierr; 21 22 PetscFunctionBegin; 23 ierr = SNESReset_GS(snes);CHKERRQ(ierr); 24 ierr = PetscFree(snes->data); 25 PetscFunctionReturn(0); 26 } 27 28 #undef __FUNCT__ 29 #define __FUNCT__ "SNESSetUp_GS" 30 PetscErrorCode SNESSetUp_GS(SNES snes) 31 { 32 PetscFunctionBegin; 33 PetscFunctionReturn(0); 34 } 35 36 #undef __FUNCT__ 37 #define __FUNCT__ "SNESSetFromOptions_GS" 38 PetscErrorCode SNESSetFromOptions_GS(SNES snes) 39 { 40 PetscErrorCode ierr; 41 SNES_GS *gs = (SNES_GS *)snes->data; 42 43 PetscFunctionBegin; 44 ierr = PetscOptionsHead("SNES GS options");CHKERRQ(ierr); 45 ierr = PetscOptionsBool("-snes_gs_norms","Compute norms for monitoring","none",gs->norms,&gs->norms,PETSC_NULL);CHKERRQ(ierr); 46 ierr = PetscOptionsTail();CHKERRQ(ierr); 47 PetscFunctionReturn(0); 48 } 49 50 #undef __FUNCT__ 51 #define __FUNCT__ "SNESView_GS" 52 PetscErrorCode SNESView_GS(SNES snes, PetscViewer viewer) 53 { 54 PetscFunctionBegin; 55 PetscFunctionReturn(0); 56 } 57 58 #undef __FUNCT__ 59 #define __FUNCT__ "SNESSolve_GS" 60 PetscErrorCode SNESSolve_GS(SNES snes) 61 { 62 Vec F; 63 Vec X; 64 Vec B; 65 PetscInt i; 66 PetscReal fnorm; 67 PetscErrorCode ierr; 68 SNES_GS *gs = (SNES_GS *)snes->data; 69 70 PetscFunctionBegin; 71 72 X = snes->vec_sol; 73 F = snes->vec_func; 74 B = snes->vec_rhs; 75 76 ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 77 snes->iter = 0; 78 snes->norm = 0.; 79 ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 80 81 snes->reason = SNES_CONVERGED_ITERATING; 82 /* compute the initial function and preconditioned update delX */ 83 ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 84 if (snes->domainerror) { 85 snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 86 PetscFunctionReturn(0); 87 } 88 /* convergence test */ 89 ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 90 if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 91 ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 92 snes->norm = fnorm; 93 ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 94 SNESLogConvHistory(snes,fnorm,0); 95 ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 96 97 /* set parameter for default relative tolerance convergence test */ 98 snes->ttol = fnorm*snes->rtol; 99 /* test convergence */ 100 ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 101 if (snes->reason) PetscFunctionReturn(0); 102 103 /* Call general purpose update function */ 104 if (snes->ops->update) { 105 ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 106 } 107 for (i = 0; i < snes->max_its; i++) { 108 ierr = SNESComputeGS(snes, B, X);CHKERRQ(ierr); 109 /* only compute norms if requested or about to exit due to maximum iterations */ 110 if (gs->norms || i == snes->max_its - 1) { 111 ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 112 if (snes->domainerror) { 113 snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 114 PetscFunctionReturn(0); 115 } 116 ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 117 if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm"); 118 /* Monitor convergence */ 119 ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 120 snes->iter = i+1; 121 snes->norm = fnorm; 122 ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 123 } 124 SNESLogConvHistory(snes,snes->norm,0); 125 ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 126 /* Test for convergence */ 127 ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 128 if (snes->reason) PetscFunctionReturn(0); 129 130 /* Call general purpose update function */ 131 if (snes->ops->update) { 132 ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 133 } 134 } 135 if (!snes->reason) snes->reason = SNES_CONVERGED_ITS; /* GS is meant to be used as a preconditioner */ 136 PetscFunctionReturn(0); 137 } 138 139 /*MC 140 SNESGS - Just calls the user-provided solution routine provided with SNESSetGS() 141 142 Level: advanced 143 144 Notes: 145 the Gauss-Seidel smoother is inherited through composition. If a solver has been created with SNESGetPC(), it will have 146 its parent's Gauss-Seidel routine associated with it. 147 148 .seealso: SNESCreate(), SNES, SNESSetType(), SNESSetGS(), SNESType (for list of available types) 149 M*/ 150 151 EXTERN_C_BEGIN 152 #undef __FUNCT__ 153 #define __FUNCT__ "SNESCreate_GS" 154 PetscErrorCode SNESCreate_GS(SNES snes) 155 { 156 SNES_GS *gs; 157 PetscErrorCode ierr; 158 159 PetscFunctionBegin; 160 snes->ops->destroy = SNESDestroy_GS; 161 snes->ops->setup = SNESSetUp_GS; 162 snes->ops->setfromoptions = SNESSetFromOptions_GS; 163 snes->ops->view = SNESView_GS; 164 snes->ops->solve = SNESSolve_GS; 165 snes->ops->reset = SNESReset_GS; 166 167 snes->usesksp = PETSC_FALSE; 168 snes->usespc = PETSC_FALSE; 169 170 snes->max_its = 10000; 171 snes->max_funcs = 10000; 172 173 ierr = PetscNewLog(snes, SNES_GS, &gs);CHKERRQ(ierr); 174 snes->data = (void*) gs; 175 gs->norms = PETSC_FALSE; 176 PetscFunctionReturn(0); 177 } 178 EXTERN_C_END 179