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